diff --git a/.gitattributes b/.gitattributes index e4128278c0..e605bb500a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,4 +11,4 @@ *.jpg binary *.png binary *.pdf binary -*.rc text working-tree-encoding=UTF-16LE-BOM eol=CRLF +*.rc binary diff --git a/.gitignore b/.gitignore index 828a72484b..8c09fbda16 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,10 @@ x64 .DS_Store kernels/config.h kernels/hash.h +kernels/export.linux.map +kernels/export.macosx.map + include/embree3/rtcore_config.h build +cmake_install.cmake +uninstall.cmake diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8bfb408cf1..8ccdf3c509 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,476 +1,642 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 +stages: + - build + - test + - benchmark + - release + - scan + - protex + +#################################################################### +# Templates +#################################################################### + +.build: + stage: build + script: "python scripts/test.py build" + after_script: [sleep 5] # required to get job log + retry: 1 + artifacts: + paths: + - build/ + - .ctest_conf + expire_in: 1 day + +.test: + stage: test + script: "python scripts/test.py test" + after_script: [sleep 5] # required to get job log + retry: 1 + +.build_and_test: + stage: build + script: + - "python scripts/test.py build" + - "python scripts/test.py test" + after_script: [sleep 5] # required to get job log + retry: 1 + ##################################################################### # Continuous Test #################################################################### -continuous-macosx-x64-Debug-ICC2020.1-ISPC1.12.0-SSE2-TBB2020.2: - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2020.1 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:2" - tags: [mac] - only: [pushes] +continuous-linux-WebAssembly: + stage: build + script: + - source /emsdk/emsdk_env.sh + - mkdir build + - cd build + - emcmake cmake -DCMAKE_BUILD_TYPE=Release -DEMBREE_TUTORIALS=OFF -DEMBREE_TASKING_SYSTEM=INTERNAL .. + - emmake make -j + image: $DOCKER_REGISTRY/embree/ubuntu:20.04 + tags: [embree, docker] + only: [pushes] + +continuous-macosx-ARM-Debug-CLANG-ISPC1.17.0-NEON-TBB_HOMEBREW: + extends: .build_and_test + before_script: ["python scripts/test.py configure platform:arm64 build:Debug compiler:CLANG ISPC_SUPPORT:ON ispc:ispc1.17.0 isa:NEON tasking:TBB_HOMEBREW intensity:2"] + tags: [embree, mac-arm] + only: [pushes] + +continuous-macosx-ARM-Debug-CLANG-ISPC1.17.0-NEON-AVX2-TBB_HOMEBREW: + extends: .build_and_test + before_script: ["python scripts/test.py configure platform:arm64 build:Debug compiler:CLANG ISPC_SUPPORT:ON ispc:ispc1.17.0 isa:NEON2X tasking:TBB_HOMEBREW intensity:2"] + tags: [embree, mac-arm] + only: [pushes] + +#continuous-macosx-x64-Debug-ICC2020.1-ISPC1.14.1-SSE2-TBB2021.1.1: +# extends: .build_and_test +# before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2020.1 ispc:ispc1.14.1 isa:SSE2 tasking:TBB2021.1.1 intensity:2"] +# tags: [embree, mac] +# only: [pushes] +# +continuous-windows-x64-RelWithDebInfo-V140-ISPC1.9.2-SSE2-TBB2021.2.0: + extends: .build_and_test + before_script: ["python scripts/test.py configure platform:x64 threads:4 build:RelWithDebInfo compiler:V140 ispc:ispc1.9.2 isa:SSE2 tasking:TBB2021.2.0 intensity:2"] + tags: [embree, win10, v120] + only: [pushes] + +#continuous-windows-Win32-RelWithDebInfoDebug-V140-ISPC1.12.0-SSE2-TBB2021.2.0: +# extends: .build_and_test +# before_script: ["python scripts\\test.py configure platform:Win32 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2021.2.0 intensity:2"] +# tags: [embree, win10, v140] +# only: [pushes] -continuous-windows-x64-RelWithDebInfo-V140-ISPC1.9.2-SSE2-TBB2019.2: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.9.2 isa:SSE2 tasking:TBB2019.2 intensity:2" - tags: [win10, v120] +continuous-windows-x64-RelWithDebInfo-V141-ISPC1.17.0-SSE2-TBB2021.2.0: + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:V141 ispc:ispc1.17.0 isa:SSE2 tasking:TBB2021.2.0 intensity:2 maxinstancelevelcount:8"] + tags: [embree, win10, v141] only: [pushes] -#continuous-windows-Win32-RelWithDebInfoDebug-V140-ISPC1.12.0-SSE2-TBB2020.2: -# script: "python scripts\\test.py platform:Win32 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:2" -# tags: [win10, v140] -# only: [pushes] + #continuous-windows-x64-RelWithDebInfo-ICX2022.0.0-ISPC1.16.1-AVX512: + # extends: .build_and_test + # before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:ICX2022.0.0 ispc:ispc1.16.1 isa:AVX512 tasking:INT threads:16 intensity:2"] + # tags: [embree, win10, avx512vl] + # only: [pushes] -continuous-windows-x64-RelWithDebInfo-V141-ISPC1.13.0-SSE2-TBB2020.2: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V141 ispc:ispc1.13.0 isa:SSE2 tasking:TBB2020.2 intensity:2 maxinstancelevelcount:8" - tags: [win10, v141] - only: [pushes] - -continuous-macosx-x64-Debug-CLANG-ISPC1.13.0-SSE2-TBB2020.2: - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:SSE2 tasking:TBB2020.2 intensity:2" - tags: [mac] +continuous-macosx-x64-Debug-CLANG-ISPC1.17.0-SSE2-TBB2020.2: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.17.0 isa:SSE2 tasking:TBB2020.2 intensity:2"] + tags: [embree, mac] only: [pushes] -continuous-linux-avx512vl-x64-Debug-ICC2019.4-ISPC1.12.0-AVX512SKX-TBB2019.9: +continuous-linux-avx512vl-x64-Debug-ICC2019.4-ISPC1.12.0-AVX512-TBB2021.2.0: + extends: .build_and_test + before_script: ["python scripts/test.py configure platform:x64 build:Debug compiler:ICC2019.4 ispc:ispc1.12.0 isa:AVX512 frequency_level:simd256 tasking:TBB2021.2.0 intensity:2 maxinstancelevelcount:4"] image: $DOCKER_REGISTRY/embree/fedora:27 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2019.4 ispc:ispc1.12.0 isa:AVX512SKX tasking:TBB2019.9 intensity:2 maxinstancelevelcount:4" - tags: [docker, avx512vl] - only: [pushes] + tags: [embree, docker, avx512vl] + only: [pushes] -continuous-linux-avx512vl-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX512SKX-TBB2020.2: +continuous-linux-avx512vl-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX512-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX512 frequency_level:simd128 tasking:TBB2021.2.0 GLFW:OFF intensity:2"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX512SKX tasking:TBB2020.2 GLFW:OFF intensity:2" - tags: [docker, avx512vl] + tags: [embree, docker, avx512vl] only: [pushes] -continuous-linux-x64-Debug-CLANG5.0.0-ISPC1.13.0-AVX2-INT-ADDRSANITIZER: +continuous-linux-x64-Debug-CLANG5.0.0-ISPC1.17.0-AVX2-INT-ADDRSANITIZER: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG5.0.0 ispc:ispc1.17.0 isa:AVX tasking:INT intensity:1 addrsanitizer:ON"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG5.0.0 ispc:ispc1.13.0 isa:AVX tasking:INT intensity:1 addrsanitizer:ON" - tags: [docker] + tags: [embree, docker] only: [pushes] continuous-ubuntu20.04-x64-Debug-GCC-ISPC1.12.0-AVX2-TBB-NAMESPACE: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.12.0 isa:AVX2 frequency_level:simd256 tasking:TBB intensity:1 api_namespace:myembree"] image: $DOCKER_REGISTRY/embree/ubuntu:20.04 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.12.0 isa:AVX2 tasking:TBB intensity:1 api_namespace:myembree" - tags: [docker] + tags: [embree, docker] only: [pushes] +continuous-linux-avx512vl-x64-Debug-ICX2022.1.2-ISPC1.17.0-AVX512-TBB2021.2.0: + extends: .build_and_test + before_script: ["python scripts/test.py configure platform:x64 build:Debug threads:4 compiler:ICX2022.1.2 ispc:ispc1.17.0 isa:AVX512 frequency_level:simd256 tasking:TBB2021.2.0 intensity:2"] + image: $DOCKER_REGISTRY/embree/ubuntu:20.04 + tags: [embree, docker, avx512vl] + only: [pushes] + #continuous-ubuntu17.10-x64-Debug-GCC-ISPC1.12.0-AVX2-TBB-NAMESPACE: +# extends: .build_and_test +# before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.12.0 isa:AVX2 tasking:TBB intensity:1 api_namespace:myembree"] # image: $DOCKER_REGISTRY/embree/ubuntu:17.10 -# script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.12.0 isa:AVX2 tasking:TBB intensity:1 api_namespace:myembree" -# tags: [docker] +# tags: [embree, docker] # only: [pushes] -continuous-centos7.4-x64-Debug-GCC-ISPC1.13.0-AVX2-TBB: +continuous-centos7.4-x64-Debug-GCC-ISPC1.17.0-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:AVX2 frequency_level:simd128 tasking:TBB intensity:1"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.12.0 isa:AVX2 tasking:TBB intensity:1" - tags: [docker] + tags: [embree, docker] only: [pushes] -continuous-fedora32-x64-Debug-GCC-ISPC-AVX512SKX-TBB: +continuous-fedora32-x64-Debug-GCC-ISPC-AVX512-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX512 tasking:TBB COMPACT_POLYS:ON MIN_WIDTH:ON intensity:2"] image: $DOCKER_REGISTRY/embree/fedora:32 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX512SKX tasking:TBB COMPACT_POLYS:ON MIN_WIDTH:ON intensity:2" - tags: [docker, avx512vl] + tags: [embree, docker, avx512vl] only: [pushes] -continuous-linux-x64-Debug-GCC-ISPC1.13.0-SSE2-TBB-KLOCKWORK: +continuous-linux-x64-Debug-GCC-ISPC1.17.0-SSE2-TBB-KLOCWORK: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:SSE2 tasking:TBB klocwork:ON intensity:0"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:SSE2 tasking:TBB klocwork:ON intensity:0" - tags: [docker] - only: [pushes] + tags: [embree, docker] + dependencies: [] + artifacts: + paths: [klocwork/*] + +continuous-kw-gen-report: + stage: scan + image: $DOCKER_REGISTRY/embree/centos:7.4 + needs: ["continuous-linux-x64-Debug-GCC-ISPC1.17.0-SSE2-TBB-KLOCWORK"] + script: + - scripts/klocwork_gen_report.sh + - scripts/store_files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID klocwork "klocwork/report.log" + tags: [embree, docker] + artifacts: + paths: [klocwork/*] continuous-linux-x64-PROTEX: + stage: protex image: amd64/openjdk:8 script: "scripts/source_scan_protex.sh" - tags: [docker] + tags: [embree, docker] dependencies: [] + needs: [] ##################################################################### # Intensive Nightly Tests #################################################################### nightly-windows-x64-RelWithDebInfo-V140-ISPC1.9.2-SSE2-INT: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.9.2 isa:SSE2 tasking:INT intensity:2" - tags: [win10, v120] - only: [schedules] + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.9.2 isa:SSE2 tasking:INT intensity:2"] + tags: [embree, win10, v120] + only: [web, schedules] nightly-windows-x64-RelWithDebInfo-V140-ISPC1.9.2-AVX-TBB2019.2: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.9.2 isa:AVX tasking:TBB2019.2 intensity:4" - tags: [win10, v120, avx] - only: [schedules] + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.9.2 isa:AVX tasking:TBB2019.2 intensity:4"] + tags: [embree, win10, v120, avx] + only: [web, schedules] nightly-windows-Win32-RelWithDebInfo-V140-ISPC1.12.0-SSE2-TBB2020.2: - script: "python scripts\\test.py platform:Win32 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:2" - tags: [win10, v140] - only: [schedules] - + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:Win32 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:2"] + tags: [embree, win10, v140] + only: [web, schedules] + nightly-windows-x64-RelWithDebInfo-V140-ISPC1.12.0-AVX2-PPL: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:AVX2 tasking:PPL intensity:2" - tags: [win10, v140, avx2] - only: [schedules] + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:AVX2 frequency_level:simd256 tasking:PPL intensity:2"] + tags: [embree, win10, v140, avx2] + only: [web, schedules] nightly-windows-x64-RelWithDebInfo-V141-ISPC1.13.0-AVX2-TBB2019.9-STATIC: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V141 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 intensity:2 STATIC_LIB:ON" - tags: [win10, v141] - only: [schedules] + extends: .build_and_test + before_script: ["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"] + tags: [embree, win10, v141] + only: [web, schedules] nightly-windows-x64-RelWithDebInfo-V142-ISPC1.13.0-AVX2-TBB2020.2-STATIC: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:V142 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:2" - tags: [win10, v142] - only: [schedules] + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:V142 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:2"] + tags: [embree, win10, v142] + only: [web, schedules] nightly-windows-x64-RelWithDebInfo-LLVM-CLANG-ISPC1.13.0-AVX2-TBB2019.9-NAMESPACE: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:LLVM_CLANG ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 intensity:4 api_namespace:myembree" - tags: [win10, llvm_clang] - only: [schedules] + extends: .build_and_test + before_script: ["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"] + tags: [embree, win10, llvm_clang] + only: [web, schedules] nightly-windows-x64-RelWithDebInfo-ICC17-ISPC1.13.0-AVX2-TBB2019.2: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:ICC17-VC14 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.2 intensity:4" - tags: [win10, icc17] - only: [schedules] - -#nightly-windows-x64-RelWithDebInfo-ICC18-ISPC1.13.0-AVX512SKX-TBB2020.2: -# script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:ICC18-VC14 ispc:ispc1.13.0 isa:AVX512SKX tasking:TBB2020.2 intensity:2" -# tags: [win10, icc18, avx512vl] -# only: [schedules] + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:ICC17-VC14 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd128 tasking:TBB2019.2 intensity:4"] + tags: [embree, win10, icc17] + only: [web, schedules] -nightly-windows-x64-RelWithDebInfo-ICC19-ISPC1.13.0-AVX512SKX-TBB2019.9: - script: "python scripts\\test.py platform:x64 build:RelWithDebInfo compiler:ICC19-VC14 ispc:ispc1.13.0 isa:AVX512SKX tasking:TBB2019.9 intensity:2" - tags: [win10, icc19, avx512vl] - only: [schedules] +#nightly-windows-x64-RelWithDebInfo-ICC18-ISPC1.13.0-AVX512-TBB2020.2: +# extends: .build_and_test +# before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:ICC18-VC14 ispc:ispc1.13.0 isa:AVX512 tasking:TBB2020.2 intensity:2"] +# tags: [embree, win10, icc18, avx512vl] +# only: [web, schedules] +# + +nightly-windows-x64-RelWithDebInfo-ICC19-ISPC1.13.0-AVX512-TBB2019.9: + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:RelWithDebInfo compiler:ICC19-VC14 ispc:ispc1.13.0 isa:AVX512 tasking:TBB2019.9 intensity:2"] + tags: [embree, win10, icc19, avx512vl] + only: [web, schedules] +nightly-windows-x64-RelWithDebInfo-ICC17-ISPC1.14.1-AVX2-TBB2021.2.0: + extends: .build_and_test + before_script: ["python scripts\\test.py configure platform:x64 build:Release compiler:V142 ispc:ispc1.14.1 isa:AVX2 tasking:TBB2021.2.0 intensity:2"] + tags: [embree, win10, v142] + only: [web, schedules] # CLANG compilation and testing of different ISAs nightly-macosx-x64-Debug-CLANG-ISPC1.12.0-SSE2-TBB2020.2-NAMESPACE: - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:4 api_namespace:myembree maxinstancelevelcount:4" - tags: [mac] - only: [schedules] + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:4 api_namespace:myembree maxinstancelevelcount:4"] + tags: [embree, mac] + only: [web, schedules] nightly-macosx-x64-Debug-CLANG-ISPC1.13.0-AVX-INT: - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:AVX tasking:INT intensity:4" - tags: [mac] # avx - only: [schedules] + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:AVX tasking:INT intensity:4"] + tags: [embree, mac] # avx + only: [web, schedules] nightly-macosx-x64-Debug-CLANG-ISPC1.13.0-SSE2-TBB2019.9-STATIC: - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:SSE2 tasking:TBB2019.9 intensity:4 STATIC_LIB:ON" - tags: [mac] # avx2 - only: [schedules] + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:SSE2 tasking:TBB2019.9 intensity:4 STATIC_LIB:ON"] + tags: [embree, mac] # avx2 + only: [web, schedules] # ICC compilation and testing of different ISAs -#nightly-macosx-x64-Debug-ICC15-ISPC1.13.0-AVX-INT: -# script: "scripts/test.py platform:x64 build:Debug compiler:ICC15 ispc:ispc1.13.0 isa:AVX tasking:INT intensity:4" -# tags: [mac, icc15] -# only: [schedules] - -nightly-macosx-x64-Debug-ICC2019.4-ISPC1.13.0-AVX2-TBB2020.2: - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2019.4 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:4" - tags: [mac] - only: [schedules] - -nightly-macosx-x64-Debug-ICC2020.1-ISPC1.13.0-AVX2-TBB2019.9: - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2020.1 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 intensity:4" - tags: [mac] - only: [schedules] + #nightly-macosx-x64-Debug-ICC15-ISPC1.13.0-AVX-INT: + # extends: .build_and_test + # before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC15 ispc:ispc1.13.0 isa:AVX tasking:INT intensity:4"] + # tags: [embree, mac, icc15] + # only: [web, schedules] + # + + #nightly-macosx-x64-Debug-ICC2019.4-ISPC1.13.0-AVX2-TBB2020.2: + # extends: .build_and_test + # before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2019.4 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd256 tasking:TBB2020.2 intensity:4"] + # tags: [embree, mac] + # only: [web, schedules] + + #nightly-macosx-x64-Debug-ICC2020.1-ISPC1.13.0-AVX2-TBB2019.9: + # extends: .build_and_test + # before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2020.1 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd128 tasking:TBB2019.9 intensity:4"] + # tags: [embree, mac] + # only: [web, schedules] + +nightly-macosx-x64-Debug-ICC2021.1.1-ISPC1.13.0-AVX2-TBB2021.1.1: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2021.1.1 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd128 tasking:TBB2021.1.1 intensity:4"] + tags: [embree, mac] + only: [web, schedules] # CLANG compilation and testing of different ISAs nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.12.0-SSE2-TBB-NAMESPACE: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2019.9 intensity:4 api_namespace:myembree maxinstancelevelcount:8"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2019.9 intensity:4 api_namespace:myembree maxinstancelevelcount:8" - tags: [docker] - only: [schedules] - -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX-TBB2019.9-VALGRIND: - image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX tasking:TBB2019.9 intensity:4 memcheck:ON" - tags: [docker] # avx - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG5.0.0-ISPC1.13.0-AVX2-INT-ADDRSANITIZER: +nightly-linux-x64-Debug-CLANG5.0.0-ISPC1.15.0-AVX2-INT-ADDRSANITIZER: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG5.0.0 ispc:ispc1.15.0 isa:AVX tasking:INT intensity:2 addrsanitizer:ON"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG5.0.0 ispc:ispc1.13.0 isa:AVX tasking:INT intensity:2 addrsanitizer:ON" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-STATIC: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.16.1-AVX2-TBB2021.2.0-STATIC: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.16.1 isa:AVX2 frequency_level:simd128 tasking:TBB2021.2.0 intensity:4 STATIC_LIB:ON"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:4 STATIC_LIB:ON" - tags: [docker] # avx2 - only: [schedules] + tags: [embree, docker] # avx2 + only: [web, schedules] -nightly-linux-knl-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX512KNL-TBB2019.9: - image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX512KNL tasking:TBB2019.9 intensity:3 GLFW:OFF" - tags: [docker-knl] - only: [schedules] - -nightly-linux-avx512vl-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX512SKX-TBB2020.2: +nightly-linux-avx512vl-x64-Debug-CLANG4.0.0-ISPC1.16.1-AVX512-TBB2020.2: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.16.1 isa:AVX512 frequency_level:simd256 tasking:TBB2020.2 intensity:3"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX512SKX tasking:TBB2020.2 intensity:3" - tags: [docker, avx512vl] - only: [schedules] + tags: [embree, docker, avx512vl] + only: [web, schedules] # GCC compilation and testing of different ISAs -nightly-linux-x64-Debug-GCC-ISPC1.13.0-SSE2-TBB2020.2: +nightly-linux-x64-Debug-GCC-ISPC1.16.1-SSE2-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.16.1 isa:SSE2 tasking:TBB2021.2.0 intensity:4"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:SSE2 tasking:TBB2020.2 intensity:4" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-GCC-ISPC1.13.0-AVX-TBB2019.9: +nightly-linux-x64-Debug-GCC-ISPC1.16.1-AVX-TBB2019.9: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.16.1 isa:AVX tasking:TBB2019.9 intensity:4"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:AVX tasking:TBB2019.9 intensity:4" - tags: [docker] # avx - only: [schedules] + tags: [embree, docker] # avx + only: [web, schedules] -nightly-linux-x64-Debug-GCC-ISPC1.13.0-AVX2-TBB2020.2: +nightly-linux-x64-Debug-GCC-ISPC1.17.0-AVX2-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 intensity:4"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:4" - tags: [docker] # avx2 - only: [schedules] + tags: [embree, docker] # avx2 + only: [web, schedules] # ICC compilation and testing of different ISAs -nightly-linux-x64-Debug-ICC2015.3-ISPC1.13.0-SSE2-TBB2019.2: +nightly-linux-x64-Debug-ICC2015.3-ISPC1.16.1-SSE2-TBB2019.2: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2015.3 ispc:ispc1.16.1 isa:SSE2 tasking:TBB2019.2 intensity:4"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2015.3 ispc:ispc1.13.0 isa:SSE2 tasking:TBB2019.2 intensity:4" - tags: [docker] - only: [schedules] - -nightly-linux-x64-Debug-ICC2016.3-ISPC1.13.0-AVX-TBB2019.2: - image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2016.3 ispc:ispc1.13.0 isa:AVX tasking:TBB2019.2 intensity:4" - tags: [docker] # avx - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-knl-x64-Debug-ICC2017.1-ISPC1.13.0-AVX512KNL-TBB2019.2: +nightly-linux-x64-Debug-ICC2016.3-ISPC1.16.1-AVX-TBB2019.2: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2016.3 ispc:ispc1.16.1 isa:AVX tasking:TBB2019.2 intensity:4"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2017.1 ispc:ispc1.13.0 isa:AVX512KNL tasking:TBB2019.2 intensity:3" - tags: [docker-knl] - only: [schedules] + tags: [embree, docker] # avx + only: [web, schedules] -nightly-linux-avx512vl-x64-Debug-ICC2017.1-ISPC1.13.0-AVX512SKX-TBB2019.2: +nightly-linux-avx512vl-x64-Debug-ICC2017.1-ISPC1.16.1-AVX512-TBB2019.2: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2017.1 ispc:ispc1.16.1 isa:AVX512 frequency_level:simd256 tasking:TBB2019.2 intensity:4"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2017.1 ispc:ispc1.13.0 isa:AVX512SKX tasking:TBB2019.2 intensity:4" - tags: [docker, avx512vl] - only: [schedules] + tags: [embree, docker, avx512vl] + only: [web, schedules] -nightly-linux-avx512vl-x64-Debug-ICC2018.0-ISPC1.13.0-AVX512SKX-TBB2019.9: +nightly-linux-avx512vl-x64-Debug-ICC2018.0-ISPC1.16.1-AVX512-TBB2019.9: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2018.0 ispc:ispc1.16.1 isa:AVX512 tasking:TBB2019.9 intensity:4"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2018.0 ispc:ispc1.13.0 isa:AVX512SKX tasking:TBB2019.9 intensity:4" - tags: [docker, avx512vl] - only: [schedules] + tags: [embree, docker, avx512vl] + only: [web, schedules] -nightly-linux-x64-Debug-ICC2019.4-ISPC1.13.0-AVX2-TBB2020.2: +nightly-linux-x64-Debug-ICC2019.4-ISPC1.16.1-AVX2-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2019.4 ispc:ispc1.16.1 isa:AVX2 tasking:TBB2021.2.0 intensity:4"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2019.4 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:4" - tags: [docker] # avx2 - only: [schedules] + tags: [embree, docker] # avx2 + only: [web, schedules] -nightly-linux-x64-Debug-ICC2020.1-ISPC1.13.0-AVX2-TBB2019.9: +nightly-linux-x64-Debug-ICC2020.1-ISPC1.17.0-AVX2-TBB2019.9: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:ICC2020.1 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 intensity:4"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:ICC2020.1 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 intensity:4" - tags: [docker] # avx2 - only: [schedules] + tags: [embree, docker] # avx2 + only: [web, schedules] # Testing on different Linux distributions -nightly-ubuntu20.04-x64-Debug-GCC-ISPC1.13.0-AVX2-TBB: +nightly-ubuntu20.04-x64-Debug-GCC-ISPC1.17.0-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:AVX2 tasking:TBB intensity:3"] image: $DOCKER_REGISTRY/embree/ubuntu:20.04 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:AVX2 tasking:TBB intensity:3" - tags: [docker] - only: [schedules] - -nightly-ubuntu16.04-x64-Debug-GCC-ISPC1.13.0-AVX2-TBB: + tags: [embree, docker] + only: [web, schedules] + +nightly-ubuntu20.04-x64-Release-GCC-ISPC1.14.1-AVX2-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Release compiler:GCC ispc:ispc1.14.1 isa:AVX2 tasking:TBB2021.2.0 intensity:2"] + image: $DOCKER_REGISTRY/embree/ubuntu:20.04 + tags: [embree, docker] + only: [web, schedules] + +nightly-ubuntu16.04-x64-Debug-GCC-ISPC1.17.0-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:AVX2 tasking:TBB MIN_WIDTH:ON intensity:3"] image: $DOCKER_REGISTRY/embree/ubuntu:16.04 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:AVX2 tasking:TBB MIN_WIDTH:ON intensity:3" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-centos7.4-x64-Debug-GCC-ISPC1.13.0-AVX2-TBB: +nightly-centos7.4-x64-Debug-GCC-ISPC1.17.0-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:AVX2 tasking:TBB COMPACT_POLYS:ON intensity:3"] image: $DOCKER_REGISTRY/embree/centos:7.4 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:AVX2 tasking:TBB COMPACT_POLYS:ON intensity:3" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -#nightly-centos7.0-x64-Debug-GCC-ISPC1.13.0-AVX2-TBB: +#nightly-centos7.0-x64-Debug-GCC-ISPC1.17.0-AVX2-TBB: +# extends: .build_and_test +# before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc1.17.0 isa:AVX2 tasking:TBB intensity:3"] # image: $DOCKER_REGISTRY/embree/centos:7.0 -# script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc1.13.0 isa:AVX2 tasking:TBB intensity:3" -# tags: [docker] -# only: [schedules] +# tags: [embree, docker] +# only: [web, schedules] -nightly-fedora32-x64-Debug-GCC-ISPC-AVX512SKX-TBB: +nightly-fedora32-x64-Debug-GCC-ISPC-AVX512-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc isas:AVX512 tasking:TBB intensity:3"] image: $DOCKER_REGISTRY/embree/fedora:32 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc isas:AVX512SKX tasking:TBB intensity:3" - tags: [docker, avx512vl] - only: [schedules] + tags: [embree, docker, avx512vl] + only: [web, schedules] -nightly-fedora28-x64-Debug-GCC-ISPC-AVX512SKX-TBB: +nightly-fedora28-x64-Debug-GCC-ISPC-AVX512-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB intensity:3"] image: $DOCKER_REGISTRY/embree/fedora:28 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB intensity:3" - tags: [docker, avx512vl] - only: [schedules] - + tags: [embree, docker, avx512vl] + only: [web, schedules] + nightly-fedora27-x64-Debug-GCC-ISPC-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX2 tasking:TBB intensity:3"] image: $DOCKER_REGISTRY/embree/fedora:27 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX2 tasking:TBB intensity:3" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] nightly-fedora26-x64-Debug-GCC-ISPC-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX2 tasking:TBB intensity:3"] image: $DOCKER_REGISTRY/embree/fedora:26 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX2 tasking:TBB intensity:3" - tags: [docker] - only: [schedules] - + tags: [embree, docker] + only: [web, schedules] + nightly-fedora25-x64-Debug-GCC-ISPC-AVX2-TBB: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX2 tasking:TBB intensity:3"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:GCC ispc:ispc isa:AVX2 tasking:TBB intensity:3" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] # Compilation test of disabled features nightly-linux-x64-Debug-CLANG4.0.0-AVX2-TBB2019.9-NO-ISPC: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 ISPC_SUPPORT:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 ISPC_SUPPORT:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-NO-TUTORIALS: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-NO-TUTORIALS: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 TUTORIALS:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 TUTORIALS:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2019.9-BACKFACECULLING: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2019.9-BACKFACECULLING: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 BACKFACE_CULLING:ON intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 BACKFACE_CULLING:ON intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-IGNORE-INVALID-RAYS: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-IGNORE-INVALID-RAYS: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 IGNORE_INVALID_RAYS:ON intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 IGNORE_INVALID_RAYS:ON intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2019.9-NO-FILTER-FUNCTION: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2019.9-NO-FILTER-FUNCTION: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 FILTER_FUNCTION:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 FILTER_FUNCTION:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-RAYMASKS: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-RAYMASKS: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 RAY_MASK:ON intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 RAY_MASK:ON intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2019.9-NO-PACKETS: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2019.9-NO-PACKETS: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 RAY_PACKETS:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 RAY_PACKETS:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-STATCOUNTER: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-STATCOUNTER: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 STAT_COUNTER:ON intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 STAT_COUNTER:ON intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] # Compilation test of individual ISAs -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-ISAS-SSE2-TBB2019.9: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-ISAS-SSE2-TBB2019.9: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isas:SSE2 tasking:TBB2019.9 intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isas:SSE2 tasking:TBB2019.9 intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-ISAS-SSE42-TBB2020.2: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-ISAS-SSE42-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isas:SSE42 tasking:TBB2021.2.0 intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isas:SSE42 tasking:TBB2020.2 intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-ISAS-AVX-TBB2019.9: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-ISAS-AVX-TBB2019.9: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isas:AVX tasking:TBB2019.9 intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isas:AVX tasking:TBB2019.9 intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-ISAS-AVX2-TBB2020.2: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-ISAS-AVX2-TBB2021.2.0: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isas:AVX2 tasking:TBB2021.2.0 intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isas:AVX2 tasking:TBB2020.2 intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-ISAS-AVX512SKX-TBB2019.9: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-ISAS-AVX512-TBB2019.9: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isas:AVX512 tasking:TBB2019.9 intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isas:AVX512SKX tasking:TBB2019.9 intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] # Compilation test of individual primitive types enabled -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-TRI: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-TRI: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2019.9-QUAD: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2019.9-QUAD: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 TRI:OFF QUAD:ON GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 TRI:OFF QUAD:ON GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-GRID: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-GRID: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 TRI:OFF QUAD:OFF GRID:ON CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 TRI:OFF QUAD:OFF GRID:ON CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2019.9-CURVE: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2019.9-CURVE: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 TRI:ON QUAD:OFF GRID:OFF CURVE:ON SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 TRI:ON QUAD:OFF GRID:OFF CURVE:ON SUBDIV:OFF USERGEOM:OFF INSTANCE:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-SUBDIV: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-SUBDIV: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:ON USERGEOM:OFF INSTANCE:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:ON USERGEOM:OFF INSTANCE:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2019.9-USERGEOM: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2019.9-USERGEOM: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2019.9 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:ON INSTANCE:OFF intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:ON INSTANCE:OFF intensity:0" - tags: [docker] - only: [schedules] + tags: [embree, docker] + only: [web, schedules] -nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.13.0-AVX2-TBB2020.2-INSTANCE: +nightly-linux-x64-Debug-CLANG4.0.0-ISPC1.17.0-AVX2-TBB2021.2.0-INSTANCE: + extends: .build_and_test + before_script: ["scripts/test.py configure platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.17.0 isa:AVX2 tasking:TBB2021.2.0 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:ON intensity:0"] image: $DOCKER_REGISTRY/embree/fedora:25 - script: "scripts/test.py platform:x64 build:Debug compiler:CLANG4.0.0 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 TRI:ON QUAD:OFF GRID:OFF CURVE:OFF SUBDIV:OFF USERGEOM:OFF INSTANCE:ON intensity:0" - tags: [docker] - only: [schedules] - + tags: [embree, docker] + only: [web, schedules] ##################################################################### # Release Builds #################################################################### -release-windows-x64-Release-ICC19-VC141-ISPC1.13.0-TBB2020.2-PACKAGE-ZIP: - script: "python scripts\\test.py platform:x64 build:Release compiler:ICC19-VC141 ispc:ispc1.13.0 isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB2020.2 intensity:4 package:ZIP" - tags: [win10, icc17, avx512vl] +release-windows-x64-Release-ICC19-VC141-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP: + stage: release + needs: [] + script: + - "python scripts/test.py configure platform:x64 build:Release compiler:ICC19-VC141 ispc:ispc1.17.0 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.2.0 intensity:4 package:ZIP" + - "python scripts/test.py build" + - "python scripts/test.py test" + tags: [embree, win10, icc17, avx512vl] only: [web, schedules] artifacts: name: "$env:CI_JOB_NAME" @@ -478,19 +644,19 @@ release-windows-x64-Release-ICC19-VC141-ISPC1.13.0-TBB2020.2-PACKAGE-ZIP: when: always expire_in: 2 mos -release-windows-x64-Release-ICC19-VC141-ISPC1.13.0-TBB2020.2-PACKAGE-MSI: - script: "python scripts\\test.py platform:x64 build:Release compiler:ICC19-VC141 ispc:ispc1.13.0 isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB2020.2 intensity:4 package:MSI" - tags: [win10, icc17, avx512vl] - only: [web, schedules] - artifacts: - name: "$env:CI_JOB_NAME" - paths: [build/*.msi] - when: always - expire_in: 2 mos +release-windows-x64-Release-ICC19-VC141-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP-manual: + extends: release-windows-x64-Release-ICC19-VC141-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP + only: [pushes] + when: manual -release-macosx-x64-Release-ICC2020.1-ISPC1.13.0-TBB2020.2-PACKAGE-ZIP: - script: "scripts/test.py platform:x64 build:Release compiler:ICC2020.1 ispc:ispc1.13.0 isas:SSE2-SSE42-AVX-AVX2 tasking:TBB2020.2 intensity:4 package:ZIP" - tags: [mac] +release-macosx-x64-Release-ICC2021.1.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP: + stage: release + needs: [] + script: + - "scripts/test.py configure platform:x64 build:Release compiler:ICC2021.1.1 ispc:ispc1.17.0 isas:SSE2-SSE42-AVX-AVX2 tasking:TBB2021.2.0 intensity:4 package:ZIP" + - "scripts/test.py build" + - "scripts/test.py test" + tags: [embree, mac, sign] only: [web, schedules] artifacts: name: "$CI_JOB_NAME" @@ -498,20 +664,19 @@ release-macosx-x64-Release-ICC2020.1-ISPC1.13.0-TBB2020.2-PACKAGE-ZIP: when: always expire_in: 2 mos -release-macosx-x64-Release-ICC2020.1-ISPC1.13.0-TBB-PACKAGE-PKG: - script: "scripts/test.py platform:x64 build:Release compiler:ICC2020.1 ispc:ispc1.13.0 isas:SSE2-SSE42-AVX-AVX2 tasking:TBB intensity:4 package:PKG" - tags: [mac] - only: [web, schedules] - artifacts: - name: "$CI_JOB_NAME" - paths: [build/*.pkg] - when: always - expire_in: 2 mos - -release-linux-x64-Release-ICC2020.1-ISPC1.13.0-TBB2020.2-PACKAGE-ZIP: +release-macosx-x64-Release-ICC2021.1.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP-manual: + extends: release-macosx-x64-Release-ICC2021.1.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP + only: [pushes] + when: manual + +release-linux-x64-Release-ICC2020.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP: + stage: release + needs: [] image: $DOCKER_REGISTRY/embree/centos:7.4 script: - - "scripts/test.py platform:x64 build:Release compiler:ICC2020.1 ispc:ispc1.13.0 isas:SSE2-SSE42-AVX-AVX2-AVX512SKX tasking:TBB2020.2 intensity:4 package:ZIP" + - "scripts/test.py configure platform:x64 build:Release compiler:ICC2020.1 ispc:ispc1.17.0 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.2.0 intensity:4 package:ZIP" + - "scripts/test.py build" + - "scripts/test.py test" - tar xzf build/embree-*.x86_64.linux.tar.gz - mv embree*.x86_64.linux embree - mkdir ospray_build @@ -520,10 +685,70 @@ release-linux-x64-Release-ICC2020.1-ISPC1.13.0-TBB2020.2-PACKAGE-ZIP: - cmake --build . - cd ospray/build - LD_LIBRARY_PATH="$CI_PROJECT_DIR/ospray_build/install/lib:$LD_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/ospray_build/ospray/build/:$PATH" ../src/ospray/scripts/tests/run_tests.sh "$CI_PROJECT_DIR/ospray_build/ospray/src/ospray" - tags: [docker, avx512vl] + tags: [embree, docker, avx512vl] only: [web, schedules] artifacts: name: "$CI_JOB_NAME" paths: [build/*.tar.gz] when: always expire_in: 2 mos + +release-linux-x64-Release-ICC2020.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP-manual: + extends: release-linux-x64-Release-ICC2020.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP + only: [pushes] + when: manual + + +##################################################################### +# Release binaries scans +#################################################################### + +scan-bdba-bin: + stage: scan + image: $DOCKER_REGISTRY/embree/centos:7.4 + tags: [docker] + needs: [release-windows-x64-Release-ICC19-VC141-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP, release-macosx-x64-Release-ICC2021.1.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP, release-linux-x64-Release-ICC2020.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP] + script: + - scripts/bdba.sh "build/embree-*" + - scripts/store_files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID bdba "embree-*.pdf" + - scripts/store_files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID bdba "embree-*.csv" + only: [web, schedules] + artifacts: + paths: + - embree-*.pdf + - embree-*.csv + +av: + stage: scan + tags: [docker] + image: $DOCKER_REGISTRY/clamav:ubuntu20.04 + needs: [release-windows-x64-Release-ICC19-VC141-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP, release-macosx-x64-Release-ICC2021.1.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP, release-linux-x64-Release-ICC2020.1-ISPC1.17.0-TBB2021.2.0-PACKAGE-ZIP] + script: + - freshclam | tee -a /tmp/av_scan.log + - clamscan -va --max-filesize=512M --max-scansize=2048M --alert-broken --alert-exceeds-max build/embree* | tee -a /tmp/av_scan.log + - scripts/store_files.sh $CI_PROJECT_NAME $CI_PIPELINE_ID av /tmp/av_scan.log + only: [web, schedules] + +##################################################################### +# Preliminary benchmark setup +#################################################################### +.benchmark: + stage: benchmark + tags: + - vis-perf-x8280-1 + script: + - "scripts/test.py configure platform:x64 build:Release compiler:GCC ispc:ispc1.17.0 isas:AVX512 tasking:TBB2021.2.0 intensity:0 --benchmark" + - "scripts/test.py build" + - "scripts/test.py test" + - "chmod +x scripts/run-benchmark.sh" + - "scripts/run-benchmark.sh" + needs: [] + +benchmark_nightly: + extends: .benchmark + only: [web, schedules] + +benchmark_manual: + extends: .benchmark + except: [schedules] + when: manual diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 48f87a1ddd..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "doc/intelstyle"] - path = doc/intelstyle - url = ../intelstyle.git diff --git a/CHANGELOG.md b/CHANGELOG.md index f820fdb548..e1b4942f8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,74 @@ Version History --------------- +### Embree 3.13.4 +- Using 8-wide BVH and double pumped NEON instructions on Apple M1 gives 8% performance boost. +- Fixed binning related crash in SAH BVH builder. +- Added EMBREE_TBB_COMPONENT cmake option to define the component/library name of Intel® TBB (default: tbb). +- Embree supports now Intel® oneAPI DPC++/C++ Compiler 2022.0.0 + +### Embree 3.13.3 +- Invalid multi segment motion blurred normal oriented curves are properly excluded from BVH build. +- Fixing issue with normal oriented curve construction when center curve curvature is very large. + Due to this change normal oriented curve shape changes slightly. +- Fixed crash caused by disabling a geometry and then detaching it from the scene. +- Bugfix in emulated ray packet intersection when EMBREE_RAY_PACKETS is turned off. +- Bugfix for linear quaternion interpolation fallback. +- Fixed issues with spaces in path to Embree build folder. +- Some fixes to compile Embree in SSE mode using WebAssembly. +- Bugfix for occlusion rays with grids and ray packets. +- We do no longer provide installers for Windows and macOS, please use the ZIP files instead. +- Upgrading to Intel® ISPC 1.17.0 for release build. +- Upgrading to Intel® oneTBB 2021.5.0 for release build. + +### Embree 3.13.2 +- Avoiding spatial split positions that are slightly out of geometry bounds. +- Introduced rtcGetGeometryThreadSafe function, which is a thread safe version of rtcGetGeometry. +- Using more accurate rcp implementation. +- Bugfix to rare corner case of high quality BVH builder. + +### Embree 3.13.1 +- Added support for Intel® ISPC ARM target. +- Releases upgrade to Intel® TBB 2021.3.0 and Intel® ISPC 1.16.1 + +### Embree 3.13.0 +- Added support for Apple M1 CPUs. +- RTC_SUBDIVISION_MODE_NO_BOUNDARY now works properly for non-manifold edges. +- CMake target 'uninstall' is not defined if it already exists. +- Embree no longer reads the .embree3 config files, thus all configuration has + to get passed through the config string to rtcNewDevice. +- Releases upgrade to Intel® TBB 2021.2.0 and Intel® ISPC 1.15.0 +- Intel® TBB dll is automatically copied into build folder after build on windows. + +### Embree 3.12.2 +- Fixed wrong uv and Ng for grid intersector in robust mode for AVX. +- Removed optimizations for Knights Landing. +- Upgrading release builds to use Intel® oneTBB 2021.1.1 + +### Embree 3.12.1 + +- Changed default frequency level to SIMD128 for Skylake, Cannon Lake, Comet Lake and Tiger Lake CPUs. + This change typically improves performance for renderers that just use SSE by maintaining higher + CPU frequencies. In case your renderer is AVX optimized you can get higher ray tracing performance + by configuring the frequency level to simd256 through passing frequency_level=simd256 to rtcNewDevice. + +### Embree 3.12.0 + +- Added linear cone curve geometry support. In this mode a real geometric surface for curves + with linear basis is rendered using capped cones. They are discontinuous at edge boundaries. +- Enabled fast two level builder for instances when low quality build is requested. +- Bugfix for BVH build when geometries got disabled. +- Added EMBREE_BACKFACE_CULLING_CURVES cmake option. This allows for a cheaper round + linear curve intersection when correct internal tracking and back hits are not required. + The new cmake option defaults to OFF. +- User geometries with invalid bounds with lower>upper in some dimension will be ignored. +- Increased robustness for grid interpolation code and fixed returned out of range u/v + coordinates for grid primitive. +- Fixed handling of motion blur time range for sphere, discs, and oriented disc geometries. +- Fixed missing model data in releases. +- Ensure compatibility to newer versions of Intel® oneTBB. +- Motion blur BVH nodes no longer store NaN values. + ### Embree 3.11.0 - Round linear curves now automatically check for the existence of left and right @@ -19,9 +87,9 @@ Version History - Added EMBREE_COMPACT_POLYS CMake option which enables double indexed triangle and quad leaves to reduce memory consumption in compact mode by an additional 40% at about 15% performance impact. This new mode is disabled by default. -- Compile fix for oneTBB 2021.1-beta05 -- Releases upgrade to TBB 2020.2 -- Compile fix for ISPC v1.13.0 +- Compile fix for Intel® oneTBB 2021.1-beta05 +- Releases upgrade to Intel® TBB 2020.2 +- Compile fix for Intel® ISPC v1.13.0 - Adding RPATH to libembree.so in releases - Increased required CMake version to 3.1.0 - Made instID member for array of pointers ray stream layout optional again. @@ -33,7 +101,7 @@ Version History the curve segments. - Added rtcGetSceneDevice API function, that returns the device a scene got created in. - Improved performance of round curve rendering by up to 1.8x. -- Bugfix to sphere intersection filter invokation for back hit. +- Bugfix to sphere intersection filter invocation for back hit. - Fixed wrong assertion that triggered for invalid curves which anyway get filtered out. - RelWithDebInfo mode no longer enables assertions. - Fixed an issue in FindTBB.cmake that caused compile error with Debug build under Linux. @@ -57,7 +125,7 @@ Version History instantiate a motion blurred scene. - In robust mode the depth test consistently uses tnear <= t <= tfar now in order to robustly continue traversal at a previous hit point - in a way that guarentees reaching all hits, even hits at the same place. + in a way that guarantees reaching all hits, even hits at the same place. - Fixed depth test in robust mode to be precise at tnear and tfar. - Added next_hit tutorial to demonstrate robustly collecting all hits along a ray using multiple ray queries. @@ -68,18 +136,18 @@ Version History for SAH heuristic were counted wrong due to some numerical issues. - Fixed an accuracy issue with rendering very short fat curves. - rtcCommitScene can now get called during rendering from multiple threads - to lazily build geometry. When TBB is used this causes a much lower overhead + to lazily build geometry. When Intel® TBB is used this causes a much lower overhead than using rtcJoinCommitScene. - Geometries can now get attached to multiple scenes at the same time, which simplifies mapping general scene graphs to API. -- Updated to TBB 2019.9 for release builds. +- Updated to Intel® TBB 2019.9 for release builds. - Fixed a bug in the BVH builder for Grid geometries. - Added macOS Catalina support to Embree releases. ### New Features in Embree 3.6.1 - Restored binary compatibility between Embree 3.6 and 3.5 when single-level instancing is used. - Fixed bug in subgrid intersector -- Removed point query alignment in ISPC header +- Removed point query alignment in Intel® ISPC header ### New Features in Embree 3.6 - Added Catmull-Rom curve types. @@ -89,7 +157,7 @@ Version History specified. - Fixed bug in external BVH builder when configured for dynamic build. - Added support for new config flag "user_threads=N" to device initialization - which sets the number of threads used by TBB but created by the user. + which sets the number of threads used by Intel® TBB but created by the user. - Fixed automatic vertex buffer padding when using rtcSetNewGeometry API function. ### New Features in Embree 3.5.2 @@ -123,7 +191,7 @@ Version History - Added point primitives (spheres, ray-oriented discs, normal-oriented discs). - Fixed crash triggered by scenes with only invalid primitives. - Improved robustness of quad/grid-based intersectors. -- Upgraded to TBB 2019.2 for release builds. +- Upgraded to Intel® TBB 2019.2 for release builds. ### New Features in Embree 3.3.0 - Added support for motion blur time range per geometry. This way geometries @@ -281,7 +349,7 @@ Version History by 5-15%. - Fixed tbb_debug.lib linking error under Windows. - Fast coherent ray stream and packet code paths now also work in robust mode. -- Using less agressive prefetching for large BVH nodes which +- Using less aggressive prefetching for large BVH nodes which results in 1-2% higher ray tracing performance. - Precompiled binaries have stack-protector enabled, except for traversal kernels. BVH builders can be slightly slower due to this @@ -292,7 +360,7 @@ Version History fixed, and one can enable only AVX2 and still get best performance by using an 8-wide BVH. - Fixed rtcOccluded1 and rtcOccluded1Ex API functions which were - broken in ISPC. + broken in Intel® ISPC. - Providing MSI installer for Windows. ### New Features in Embree 2.16.5 @@ -318,7 +386,7 @@ Version History cracks when using displacement mapping but reduces performance at irregular vertices. - Fixed a bug where subdivision geometry was not properly updated - when modifying only the tesselation rate and vertex array. + when modifying only the tessellation rate and vertex array. ### New Features in Embree 2.16.2 - Fixed bug that caused NULL intersection context in intersection @@ -481,14 +549,14 @@ Version History If you use Embree v2.11.0 please upgrade to Embree v2.12.0. - Reduced memory consumption for dynamic scenes containing small meshes. -- Added support to start and affinitize TBB worker threads by passing +- Added support to start and affinitize Intel® TBB worker threads by passing "`start_threads=1,set_affinity=1`" to `rtcNewDevice`. These settings are recommended on systems with a high thread count. - `rtcInterpolate2` can now be called within a displacement shader. - Added initial support for Microsoft's Parallel Pattern Library (PPL) - as tasking system alternative (for optimal performance TBB is + as tasking system alternative (for optimal performance Intel® TBB is highly recommended). -- Updated to TBB 2017 which is released under the Apache v2.0 license. +- Updated to Intel® TBB 2017 which is released under the Apache v2.0 license. - Dropped support for Visual Studio 2012 Win32 compiler. Visual Studio 2012 x64 is still supported. @@ -552,14 +620,14 @@ Version History - Added support for quad geometry (replaces triangle-pairs feature). - Added support for linear motion blur of user geometries. - Improved performance through AVX-512 optimizations. -- Improved performance of lazy scene build (when using TBB 4.4 update +- Improved performance of lazy scene build (when using Intel® TBB 4.4 update 2). - Improved performance through huge page support under linux. ### New Features in Embree 2.7.1 - Internal tasking system supports cancellation of build operations. -- ISPC mode for robust and compact scenes got significantly faster +- Intel® ISPC mode for robust and compact scenes got significantly faster (implemented hybrid traversal for bvh4.triangle4v and bvh4.triangle4i). - Hair rendering got faster as we fixed some issues with the SAH @@ -584,7 +652,7 @@ Version History - Added device concept to Embree to allow different components of an application to use Embree without interfering with each other. - Fixed memory leak in twolevel builder used for dynamic scenes. -- Fixed bug in tesselation cache that caused crashes for subdivision +- Fixed bug in tessellation cache that caused crashes for subdivision surfaces. - Fixed bug in internal task scheduler that caused deadlocks when using `rtcCommitThread`. @@ -658,10 +726,10 @@ Version History progress and cancel long build operations - BVH builders can be used to build user defined hierarchies inside the application (see tutorial [BVH Builder]) -- Switched to TBB as default tasking system on Xeon to get even faster +- Switched to Intel® TBB as default tasking system on Xeon to get even faster hierarchy build times and better integration for applications that - also use TBB -- `rtcCommit` can get called from multiple TBB threads to join the + also use Intel® TBB +- `rtcCommit` can get called from multiple Intel® TBB threads to join the hierarchy build operations ### New Features in Embree 2.4 @@ -749,7 +817,7 @@ Version History - Support for the Intel® Xeon Phi™ coprocessor platform - Support for high-performance "packet" kernels on SSE, AVX, and Xeon Phi -- Integration with the Intel® SPMD Program Compiler (ISPC) +- Integration with the Intel® Implicit SPMD Program Compiler (Intel® ISPC) - Instantiation and fast BVH reconstruction -- Example photo-realistic rendering engine for both C++ and ISPC +- Example photo-realistic rendering engine for both C++ and Intel® ISPC diff --git a/CMakeLists.txt b/CMakeLists.txt index 06f49a8671..ea5491a3ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,24 +1,28 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(EMBREE_VERSION_MAJOR 3) -SET(EMBREE_VERSION_MINOR 11) -SET(EMBREE_VERSION_PATCH 0) +SET(EMBREE_VERSION_MINOR 13) +SET(EMBREE_VERSION_PATCH 4) SET(EMBREE_VERSION_NOTE "") +unset(CMAKE_CXX_VISIBILITY_PRESET) +set_directory_properties(PROPERTIES COMPILE_OPTIONS "") +set_directory_properties(PROPERTIES COMPILE_DEFINITIONS "") + SET(EMBREE_VERSION ${EMBREE_VERSION_MAJOR}.${EMBREE_VERSION_MINOR}.${EMBREE_VERSION_PATCH}) MATH(EXPR EMBREE_VERSION_NUMBER "10000*${EMBREE_VERSION_MAJOR} + 100*${EMBREE_VERSION_MINOR} + ${EMBREE_VERSION_PATCH}") SET(CPACK_RPM_PACKAGE_RELEASE 1) PROJECT(embree${EMBREE_VERSION_MAJOR}) -CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0) +CMAKE_MINIMUM_REQUIRED(VERSION 3.5.0) # We use our own strip tool on macOS to sign during install. This is required as CMake modifies RPATH of the binary during install. IF (APPLE AND EMBREE_SIGN_FILE) SET(EMBREE_STRIP ${CMAKE_STRIP}) - SET(CMAKE_STRIP ${PROJECT_BINARY_DIR}/post_install_target.sh) - CONFIGURE_FILE(scripts/post_install_target.sh.in ${PROJECT_BINARY_DIR}/post_install_target.sh @ONLY) + SET(CMAKE_STRIP "${PROJECT_BINARY_DIR}/post_install_target.sh") + CONFIGURE_FILE(scripts/post_install_target.sh.in "${PROJECT_BINARY_DIR}/post_install_target.sh" @ONLY) ENDIF() MACRO (SIGN_TARGET target) @@ -31,7 +35,7 @@ MACRO (SIGN_TARGET target) # on MacOSX we strip and sign here for testing purposes but also during install, as CMake modifies binary during install ADD_CUSTOM_COMMAND(TARGET ${target} POST_BUILD COMMAND ${EMBREE_STRIP} -x $ - COMMAND ${EMBREE_SIGN_FILE} -o runtime -e ${CMAKE_SOURCE_DIR}/common/cmake/embree.entitlements $) + COMMAND ${EMBREE_SIGN_FILE} -o runtime -e "${CMAKE_SOURCE_DIR}/common/cmake/embree.entitlements" $) ELSE() # on Linux signing of binaries is not supported and stripping is done during install ENDIF() @@ -39,7 +43,7 @@ MACRO (SIGN_TARGET target) ENDMACRO() # find git version -IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) +IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") FIND_PACKAGE(Git) IF(GIT_FOUND) EXECUTE_PROCESS( @@ -61,7 +65,7 @@ IF(COMMAND cmake_policy) cmake_policy(SET CMP0042 NEW) endif() if(POLICY CMP0072) - cmake_policy(SET CMP0072 OLD) + cmake_policy(SET CMP0072 NEW) endif() if(POLICY CMP0022) cmake_policy(SET CMP0022 NEW) @@ -71,6 +75,14 @@ IF(COMMAND cmake_policy) endif() ENDIF(COMMAND cmake_policy) +if (APPLE) + # Silence ranlib warning "has no symbols" + set(CMAKE_C_ARCHIVE_CREATE " Scr ") + set(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + set(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + set(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") +endif() + MARK_AS_ADVANCED(CMAKE_BACKWARDS_COMPATIBILITY) MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH) MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH) @@ -80,12 +92,19 @@ MARK_AS_ADVANCED(CMAKE_OSX_DEPLOYMENT_TARGET) MARK_AS_ADVANCED(CMAKE_OSX_SYSROOT) MARK_AS_ADVANCED(CLEAR CMAKE_CXX_COMPILER) -SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/common/cmake ${CMAKE_MODULE_PATH}) +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake" ${CMAKE_MODULE_PATH}) IF (BUILD_TESTING) INCLUDE(test) ENDIF() +set(BUILD_DOC OFF CACHE INTERNAL "build documentation (internal only)") +IF (BUILD_DOC) + ADD_SUBDIRECTORY(doc) +ENDIF() + +OPTION(EMBREE_TUTORIALS "Enable to build Embree tutorials" ON) + ############################################################## # Embree configuration ############################################################## @@ -100,11 +119,16 @@ ELSE() ENDIF() IF (EMBREE_STATIC_LIB) SET(EMBREE_LIB_TYPE STATIC) + ADD_DEFINITIONS(-DEMBREE_STATIC_LIB) ELSE() SET(EMBREE_LIB_TYPE SHARED) ENDIF() OPTION(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." ON) +IF (EMSCRIPTEN) + SET(EMBREE_ISPC_SUPPORT OFF CACHE BOOL "Build Embree with support for ISPC applications." FORCE) +ENDIF() + SET(EMBREE_API_NAMESPACE "" CACHE STRING "C++ namespace to put API symbols into.") SET(EMBREE_LIBRARY_NAME "embree${EMBREE_VERSION_MAJOR}" CACHE STRING "Name of the embree library file (default is embree${EMBREE_VERSION_MAJOR})") @@ -144,7 +168,22 @@ SET(EMBREE_MAX_INSTANCE_LEVEL_COUNT 1 CACHE STRING "Maximum number of instance l SET(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR 2.0 CACHE STRING "Self intersection avoidance factor for flat curves. Specify floating point value in range 0 to inf.") OPTION(EMBREE_MIN_WIDTH "Enables min-width feature to enlarge curve and point thickness to pixel width." OFF) +############################################################## +# Platform detection and defaults +############################################################## + +# detect ARM compilation +IF (APPLE AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64")) + MESSAGE(STATUS "Building for Apple silicon") + SET(EMBREE_ARM ON) +ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + MESSAGE(STATUS "Building for AArch64") + SET(EMBREE_ARM ON) +ENDIF() + SET(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") +SET(EMBREE_TBB_COMPONENT "tbb" CACHE STRING "The TBB component/library name.") + IF (WIN32) SET_PROPERTY(CACHE EMBREE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL PPL) ELSE() @@ -184,16 +223,29 @@ IF (WIN32) ENDIF() SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON) - IF (${CMAKE_GENERATOR_TOOLSET} MATCHES "^LLVM" ) - MESSAGE("CLANG detected") + #message ("CMAKE_GENERATOR_TOOLSET: ${CMAKE_GENERATOR_TOOLSET}") + #message ("CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}") + #message ("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") + + IF (${CMAKE_CXX_COMPILER} MATCHES ".*dpcpp") + message(FATAL_ERROR "DPCPP compiler not supported on Windows yet. Use ICX instead.") + ENDIF() + + IF (${CMAKE_CXX_COMPILER_ID} MATCHES "IntelLLVM" OR + (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND ${CMAKE_CXX_COMPILER} MATCHES ".*icx")) + MESSAGE("-- DPCPP detected") + INCLUDE(dpcpp) + ELSEIF(${CMAKE_GENERATOR_TOOLSET} MATCHES "^LLVM") + MESSAGE("-- CLANG detected") INCLUDE(clang) ELSEIF(${CMAKE_GENERATOR_TOOLSET} MATCHES "^Intel") - MESSAGE("Intel Compiler detected") + MESSAGE("-- Intel Compiler detected") INCLUDE (intel) ELSE() - IF (EMBREE_ISA_AVX512KNL OR EMBREE_ISA_AVX512SKX) + IF (EMBREE_ISA_AVX512) MESSAGE(FATAL_ERROR "Microsoft Visual C++ Compiler does not support AVX512. Please use Intel Compiler or Clang.") ENDIF() + MESSAGE("-- MSVC detected") INCLUDE (msvc) ENDIF() @@ -201,8 +253,19 @@ ELSE (WIN32) IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv") INCLUDE (crayprgenv) ELSE() + GET_FILENAME_COMPONENT(CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME) + STRING(TOLOWER "${CMAKE_CXX_COMPILER_ID}" _LOWER_CXX_COMPILER_ID) STRING(REPLACE "appleclang" "clang" _LOWER_CXX_COMPILER_ID ${_LOWER_CXX_COMPILER_ID}) + STRING(REPLACE "intelllvm" "dpcpp" _LOWER_CXX_COMPILER_ID ${_LOWER_CXX_COMPILER_ID}) + IF(${_LOWER_CXX_COMPILER_ID} MATCHES "clang" AND ${CXX_COMPILER_NAME} MATCHES "icpx") + STRING(REPLACE "clang" "dpcpp" _LOWER_CXX_COMPILER_ID ${_LOWER_CXX_COMPILER_ID}) + ENDIF() + IF(${_LOWER_CXX_COMPILER_ID} MATCHES "clang" AND ${CXX_COMPILER_NAME} MATCHES "dpcpp") + STRING(REPLACE "clang" "dpcpp" _LOWER_CXX_COMPILER_ID ${_LOWER_CXX_COMPILER_ID}) + ENDIF() + STRING(TOUPPER "${_LOWER_CXX_COMPILER_ID}" _UPPER_CXX_COMPILER_ID) + MESSAGE("-- ${_UPPER_CXX_COMPILER_ID} detected") INCLUDE(${_LOWER_CXX_COMPILER_ID} OPTIONAL RESULT_VARIABLE COMPILER_FOUND) IF (NOT COMPILER_FOUND) MESSAGE(FATAL_ERROR "Unsupported compiler: " ${CMAKE_CXX_COMPILER_ID}) @@ -223,57 +286,92 @@ ENDIF (WIN32) # ISA configuration ############################################################## -IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv") +# just for compatibility with old naming +IF(DEFINED EMBREE_ISA_AVX512SKX) + UNSET(EMBREE_ISA_AVX512 CACHE) + SET(EMBREE_ISA_AVX512 ${EMBREE_ISA_AVX512SKX} CACHE BOOL "") +ENDIF() + +TRY_COMPILE(COMPILER_SUPPORTS_ARM_NEON "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_arm_neon.cpp") +IF (COMPILER_SUPPORTS_ARM_NEON) + SET(EMBREE_ARM ON) +ENDIF() + +IF (CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv") SET(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") +ELSEIF (EMSCRIPTEN) + SET(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") ELSE() SET(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.") ENDIF() -SET_PROPERTY(CACHE EMBREE_MAX_ISA PROPERTY STRINGS NONE SSE2 SSE4.2 AVX AVX2 AVX512KNL AVX512SKX DEFAULT) + +IF (EMBREE_ARM) + SET_PROPERTY(CACHE EMBREE_MAX_ISA PROPERTY STRINGS NONE NEON NEON2X) +ELSE() + SET_PROPERTY(CACHE EMBREE_MAX_ISA PROPERTY STRINGS NONE SSE2 SSE4.2 AVX AVX2 AVX512 DEFAULT) +ENDIF() IF (EMBREE_MAX_ISA STREQUAL "NONE") - TRY_COMPILE(COMPILER_SUPPORTS_AVX ${CMAKE_BINARY_DIR} ${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp COMPILE_DEFINITIONS ${FLAGS_AVX}) - TRY_COMPILE(COMPILER_SUPPORTS_AVX2 ${CMAKE_BINARY_DIR} ${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp COMPILE_DEFINITIONS ${FLAGS_AVX2}) - TRY_COMPILE(COMPILER_SUPPORTS_AVX512KNL ${CMAKE_BINARY_DIR} ${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp COMPILE_DEFINITIONS ${FLAGS_AVX512KNL}) - TRY_COMPILE(COMPILER_SUPPORTS_AVX512SKX ${CMAKE_BINARY_DIR} ${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp COMPILE_DEFINITIONS ${FLAGS_AVX512SKX}) - - OPTION(EMBREE_ISA_SSE2 "Enables SSE2 ISA." ON) - OPTION(EMBREE_ISA_SSE42 "Enables SSE4.2 ISA." ON) - OPTION(EMBREE_ISA_AVX "Enables AVX ISA." ${COMPILER_SUPPORTS_AVX}) - OPTION(EMBREE_ISA_AVX2 "Enables AVX2 ISA." ${COMPILER_SUPPORTS_AVX2}) - IF (WIN32 OR APPLE) - OPTION(EMBREE_ISA_AVX512KNL "Enables AVX512 ISA for Knights Landing." OFF) - OPTION(EMBREE_ISA_AVX512SKX "Enables AVX512 ISA for Skylake." OFF) + + IF (EMBREE_ARM) + IF (APPLE) + OPTION(EMBREE_ISA_NEON "Enables NEON ISA." OFF) + OPTION(EMBREE_ISA_NEON2X "Enables NEON ISA double pumped." ON) + ELSE() + OPTION(EMBREE_ISA_NEON "Enables NEON ISA." ON) + OPTION(EMBREE_ISA_NEON2X "Enables NEON ISA double pumped." OFF) + ENDIF() ELSE() - OPTION(EMBREE_ISA_AVX512KNL "Enables AVX512 ISA for Knights Landing." OFF) # compilation on GCC 8 broken - OPTION(EMBREE_ISA_AVX512SKX "Enables AVX512 ISA for Skylake." ${COMPILER_SUPPORTS_AVX512SKX}) + TRY_COMPILE(COMPILER_SUPPORTS_AVX "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp" COMPILE_DEFINITIONS ${FLAGS_AVX}) + TRY_COMPILE(COMPILER_SUPPORTS_AVX2 "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp" COMPILE_DEFINITIONS ${FLAGS_AVX2}) + TRY_COMPILE(COMPILER_SUPPORTS_AVX512 "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp" COMPILE_DEFINITIONS ${FLAGS_AVX512}) + + OPTION(EMBREE_ISA_SSE2 "Enables SSE2 ISA." ON) + OPTION(EMBREE_ISA_SSE42 "Enables SSE4.2 ISA." ON) + OPTION(EMBREE_ISA_AVX "Enables AVX ISA." ${COMPILER_SUPPORTS_AVX}) + OPTION(EMBREE_ISA_AVX2 "Enables AVX2 ISA." ${COMPILER_SUPPORTS_AVX2}) + IF (WIN32 OR APPLE) + OPTION(EMBREE_ISA_AVX512 "Enables AVX512 ISA." OFF) + ELSE() + OPTION(EMBREE_ISA_AVX512 "Enables AVX512 ISA." ${COMPILER_SUPPORTS_AVX512}) + ENDIF() ENDIF() + ELSEIF (EMBREE_MAX_ISA STREQUAL "DEFAULT") + UNSET(EMBREE_ISA_NEON CACHE) + UNSET(EMBREE_ISA_NEON2X CACHE) UNSET(EMBREE_ISA_SSE2 CACHE) UNSET(EMBREE_ISA_SSE42 CACHE) UNSET(EMBREE_ISA_AVX CACHE) UNSET(EMBREE_ISA_AVX2 CACHE) - UNSET(EMBREE_ISA_AVX512KNL CACHE) - UNSET(EMBREE_ISA_AVX512SKX CACHE) + UNSET(EMBREE_ISA_AVX512 CACHE) + SET(EMBREE_ISA_NEON OFF) + SET(EMBREE_ISA_NEON2X OFF) SET(EMBREE_ISA_SSE2 OFF) SET(EMBREE_ISA_SSE42 OFF) SET(EMBREE_ISA_AVX OFF) SET(EMBREE_ISA_AVX2 OFF) - SET(EMBREE_ISA_AVX512KNL OFF) - SET(EMBREE_ISA_AVX512SKX OFF) + SET(EMBREE_ISA_AVX512 OFF) MESSAGE(STATUS "Detecting default ISA...") INCLUDE(check_isa_default) CHECK_ISA_DEFAULT(EMBREE_ISA_DEFAULT) MESSAGE(STATUS "Detected default ISA: ${EMBREE_ISA_DEFAULT}") SET(EMBREE_ISA_${EMBREE_ISA_DEFAULT} ON) + ELSE() + UNSET(EMBREE_ISA_NEON CACHE) + UNSET(EMBREE_ISA_NEON2X CACHE) UNSET(EMBREE_ISA_SSE2 CACHE) UNSET(EMBREE_ISA_SSE42 CACHE) UNSET(EMBREE_ISA_AVX CACHE) UNSET(EMBREE_ISA_AVX2 CACHE) - UNSET(EMBREE_ISA_AVX512KNL CACHE) - UNSET(EMBREE_ISA_AVX512SKX CACHE) - - IF(EMBREE_MAX_ISA STREQUAL "SSE2") + UNSET(EMBREE_ISA_AVX512 CACHE) + + IF(EMBREE_MAX_ISA STREQUAL "NEON") + SET(ISA 1) + ELSEIF(EMBREE_MAX_ISA STREQUAL "NEON2X") + SET(ISA 2) + ELSEIF(EMBREE_MAX_ISA STREQUAL "SSE2") SET(ISA 1) ELSEIF(EMBREE_MAX_ISA STREQUAL "SSE4.2") SET(ISA 2) @@ -281,39 +379,46 @@ ELSE() SET(ISA 3) ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX2") SET(ISA 4) - ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512KNL") - SET(ISA 5) - ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512SKX") - SET(ISA 6) + ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512") + SET(ISA 5) + ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512SKX") # just for compatibility + SET(ISA 5) ELSE() MESSAGE(FATAL_ERROR "Unsupported ISA specified: " ${EMBREE_MAX_ISA}) ENDIF() + SET(EMBREE_ISA_NEON OFF) + SET(EMBREE_ISA_NEON2X OFF) SET(EMBREE_ISA_SSE2 OFF) SET(EMBREE_ISA_SSE42 OFF) SET(EMBREE_ISA_AVX OFF) SET(EMBREE_ISA_AVX2 OFF) - SET(EMBREE_ISA_AVX512KNL OFF) - SET(EMBREE_ISA_AVX512SKX OFF) + SET(EMBREE_ISA_AVX512 OFF) - IF (ISA GREATER 0) - SET(EMBREE_ISA_SSE2 ON) - ENDIF () - IF (ISA GREATER 1) - SET(EMBREE_ISA_SSE42 ON) - ENDIF () - IF (ISA GREATER 2) - SET(EMBREE_ISA_AVX ON) - ENDIF () - IF (ISA GREATER 3) - SET(EMBREE_ISA_AVX2 ON) - ENDIF () - IF (ISA GREATER 4) - SET(EMBREE_ISA_AVX512KNL ON) - ENDIF () - IF (ISA GREATER 5) - SET(EMBREE_ISA_AVX512SKX ON) - ENDIF () + IF (EMBREE_ARM) + IF (ISA GREATER 0) + SET(EMBREE_ISA_NEON ON) + ENDIF () + IF (ISA GREATER 1) + SET(EMBREE_ISA_NEON2X ON) + ENDIF () + ELSE() + IF (ISA GREATER 0) + SET(EMBREE_ISA_SSE2 ON) + ENDIF () + IF (ISA GREATER 1) + SET(EMBREE_ISA_SSE42 ON) + ENDIF () + IF (ISA GREATER 2) + SET(EMBREE_ISA_AVX ON) + ENDIF () + IF (ISA GREATER 3) + SET(EMBREE_ISA_AVX2 ON) + ENDIF () + IF (ISA GREATER 4) + SET(EMBREE_ISA_AVX512 ON) + ENDIF () + ENDIF() ENDIF() IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv") @@ -324,6 +429,12 @@ IF (APPLE AND EMBREE_STATIC_LIB) # count number of set ISAs SET(NUMISA 0) + IF (EMBREE_ISA_NEON) + MATH(EXPR NUMISA "${NUMISA}+1") + ENDIF() + IF (EMBREE_ISA_NEON2X) + MATH(EXPR NUMISA "${NUMISA}+1") + ENDIF() IF (EMBREE_ISA_SSE2) MATH(EXPR NUMISA "${NUMISA}+1") ENDIF() @@ -336,17 +447,14 @@ IF (APPLE AND EMBREE_STATIC_LIB) IF (EMBREE_ISA_AVX2) MATH(EXPR NUMISA "${NUMISA}+1") ENDIF() - IF (EMBREE_ISA_AVX512KNL) - MATH(EXPR NUMISA "${NUMISA}+1") - ENDIF() - IF (EMBREE_ISA_AVX512SKX) + IF (EMBREE_ISA_AVX512) MATH(EXPR NUMISA "${NUMISA}+1") ENDIF() IF (NUMISA GREATER 1) IF (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - IF (${CMAKE_CXX_COMPILER_VERSION} MATCHES "^9\\..*") - MESSAGE(FATAL_ERROR "Using Embree as static library is not supported with AppleClang 9.X when multiple ISAs are selected. Please either build a shared library or enable only one ISA.") + IF (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER "9.0.0" OR ${CMAKE_CXX_COMPILER_VERSION} VERSION_EQUAL "9.0.0") + MESSAGE(FATAL_ERROR "Using Embree as static library is not supported with AppleClang >= 9.0 when multiple ISAs are selected. Please either build a shared library or enable only one ISA.") ENDIF() ENDIF() ENDIF() @@ -360,15 +468,36 @@ SET(SSE2 0) SET(SSE42 1) SET(AVX 2) SET(AVX2 3) -SET(AVX512KNL 4) -SET(AVX512SKX 5) +SET(AVX512 4) UNSET(FLAGS_LOWEST) +SET(ISA_LOWEST -1) SET(ISA_LOWEST_AVX 2) +IF (EMBREE_ARM) + IF (EMBREE_ISA_NEON2X) + LIST(APPEND ISPC_TARGETS "neon-i32x8") + ELSEIF (EMBREE_ISA_NEON) + LIST(APPEND ISPC_TARGETS "neon-i32x4") + ENDIF() +ENDIF() + +IF (EMBREE_ISA_NEON) + SET(EMBREE_ISA_SSE2 ON) +ENDIF() + +IF (EMBREE_ISA_NEON2X) + SET(EMBREE_ISA_SSE2 OFF) + SET(EMBREE_ISA_SSE42 OFF) + SET(EMBREE_ISA_AVX OFF) + SET(EMBREE_ISA_AVX2 ON) +ENDIF() + IF (EMBREE_ISA_SSE2) ADD_DEFINITIONS(-DEMBREE_TARGET_SSE2) - LIST(APPEND ISPC_TARGETS "sse2") + IF (NOT EMBREE_ARM) + LIST(APPEND ISPC_TARGETS "sse2") + ENDIF() IF(NOT FLAGS_LOWEST) SET(ISA_LOWEST ${SSE2}) SET(FLAGS_LOWEST ${FLAGS_SSE2}) @@ -377,7 +506,9 @@ ENDIF() IF (EMBREE_ISA_SSE42) ADD_DEFINITIONS(-DEMBREE_TARGET_SSE42) - LIST(APPEND ISPC_TARGETS "sse4") + IF (NOT EMBREE_ARM) + LIST(APPEND ISPC_TARGETS "sse4") + ENDIF() IF(NOT FLAGS_LOWEST) SET(ISA_LOWEST ${SSE42}) SET(FLAGS_LOWEST ${FLAGS_SSE42}) @@ -386,7 +517,9 @@ ENDIF () IF (EMBREE_ISA_AVX) ADD_DEFINITIONS(-DEMBREE_TARGET_AVX) - LIST(APPEND ISPC_TARGETS "avx") + IF (NOT EMBREE_ARM) + LIST(APPEND ISPC_TARGETS "avx") + ENDIF() IF(NOT FLAGS_LOWEST) SET(ISA_LOWEST ${AVX}) SET(ISA_LOWEST_AVX ${AVX}) @@ -396,7 +529,9 @@ ENDIF () IF (EMBREE_ISA_AVX2) ADD_DEFINITIONS(-DEMBREE_TARGET_AVX2) - LIST(APPEND ISPC_TARGETS "avx2") + IF (NOT EMBREE_ARM) + LIST(APPEND ISPC_TARGETS "avx2") + ENDIF() IF(NOT FLAGS_LOWEST) SET(ISA_LOWEST ${AVX2}) SET(ISA_LOWEST_AVX ${AVX2}) @@ -404,26 +539,22 @@ IF (EMBREE_ISA_AVX2) ENDIF() ENDIF () -IF (EMBREE_ISA_AVX512KNL) - ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512KNL) - LIST(APPEND ISPC_TARGETS "avx512knl-i32x16") - IF(NOT FLAGS_LOWEST) - SET(ISA_LOWEST ${AVX512KNL}) - SET(ISA_LOWEST_AVX ${AVX512KNL}) - SET(FLAGS_LOWEST ${FLAGS_AVX512KNL}) +IF (EMBREE_ISA_AVX512) + ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512) + IF (NOT EMBREE_ARM) + LIST(APPEND ISPC_TARGETS "avx512skx-i32x16") ENDIF() -ENDIF () - -IF (EMBREE_ISA_AVX512SKX) - ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512SKX) - LIST(APPEND ISPC_TARGETS "avx512skx-i32x16") IF(NOT FLAGS_LOWEST) - SET(ISA_LOWEST ${AVX512SKX}) - SET(ISA_LOWEST_AVX ${AVX512SKX}) - SET(FLAGS_LOWEST ${FLAGS_AVX512SKX}) + SET(ISA_LOWEST ${AVX512}) + SET(ISA_LOWEST_AVX ${AVX512}) + SET(FLAGS_LOWEST ${FLAGS_AVX512}) ENDIF() ENDIF () +IF (ISA_LOWEST EQUAL -1) + MESSAGE(FATAL_ERROR "You have to enable at least one ISA!") +ENDIF() + INCLUDE (ispc) ############################################################## @@ -472,21 +603,25 @@ SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(kernels) -ADD_SUBDIRECTORY(tutorials) +IF (EMBREE_TUTORIALS) + ADD_SUBDIRECTORY(tutorials) +ENDIF() ############################################################## # Uninstall ############################################################## -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" - IMMEDIATE @ONLY) +IF (NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" + IMMEDIATE @ONLY) -add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake) + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake") -SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets) + SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets) +ENDIF() ############################################################## # Has to be last diff --git a/CTestConfig.cmake b/CTestConfig.cmake index e47e4d35c7..94e3539b2b 100644 --- a/CTestConfig.cmake +++ b/CTestConfig.cmake @@ -1,5 +1,5 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(CTEST_PROJECT_NAME "Embree") -set(TEST_MODELS_HASH 87ea28415d02a8586c7c6c5df43441231ae19453) +set(TEST_MODELS_HASH 27e887f955dc991b5b3369e663536792a2fc59c1) diff --git a/README.md b/README.md index af4b7af31f..f85a682648 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -% Embree: High Performance Ray Tracing Kernels 3.11.0 +% Embree: High Performance Ray Tracing Kernels 3.13.4 % Intel Corporation Embree Overview @@ -17,12 +17,12 @@ highest benefit from future improvements. Intel® Embree is released as Open Source under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). -Intel® Embree supports applications written with the Intel® SPMD Program -Compiler (ISPC, ) by also providing an ISPC +Intel® Embree supports applications written with the Intel® Implicit SPMD +Program Compiler (Intel® ISPC, ) by also providing an Intel® ISPC interface to the core ray tracing algorithms. This makes it possible -to write a renderer in ISPC that automatically vectorizes and -leverages SSE, AVX, AVX2, and AVX-512 instructions. ISPC also supports -runtime code selection, thus ISPC will select the best code path for +to write a renderer in Intel® ISPC that automatically vectorizes and +leverages SSE, AVX, AVX2, and AVX-512 instructions. Intel® ISPC also supports +runtime code selection, thus Intel® ISPC will select the best code path for your application. Intel® Embree contains algorithms optimized for incoherent workloads (e.g. @@ -48,8 +48,8 @@ Supported Platforms ------------------- Embree supports Windows (32-bit and 64-bit), Linux (64-bit), and macOS -(64-bit). The code compiles with the Intel® Compiler, GCC, Clang, -and the Microsoft Compiler. +(64-bit) both x86 and Apple M1 based. The code compiles with the Intel® +Compiler, GCC, Clang, and the Microsoft Compiler. Using the Intel® Compiler improves performance by approximately 10%. Performance also varies across different operating @@ -57,9 +57,8 @@ systems, with Linux typically performing best as it supports transparently transitioning to 2MB pages. Embree is optimized for Intel CPUs supporting SSE, AVX, AVX2, and -AVX-512 instructions, and requires at least a CPU with support for -SSE2. - +AVX-512 instructions. Embree requires at least an x86 CPU with support for +SSE2 or an Apple M1 CPU. Embree Support and Contact -------------------------- @@ -76,96 +75,44 @@ list](https://groups.google.com/d/forum/embree/). Installation of Embree ====================== -Windows MSI Installer ---------------------- - -You can install the Embree library using the Windows MSI installer -[embree-3.11.0-x64.vc12.msi](https://github.com/embree/embree/releases/download/v3.11.0/embree-3.11.0.x64.vc12.msi). This -will install the 64-bit Embree version by default in `Program -Files\Intel\Embree v3.11.0 x64`. - -You have to set the path to the `bin` folders manually to your `PATH` -environment variable for applications to find Embree. - -To compile applications with Embree using CMake, please have a look at -the `find_embree` tutorial. To compile this tutorial, you need to set -the `embree_DIR` CMake variable of this tutorial to `Program -Files\Intel\Embree v3.11.0 x64`. - -To uninstall Embree, open `Programs and Features` by clicking the -`Start button`, clicking `Control Panel`, clicking `Programs`, and -then clicking `Programs and Features`. Select `Embree -3.11.0 x64` and uninstall it. - Windows ZIP File ----------------- -Embree linked against Visual Studio 2013 -[embree-3.11.0.x64.vc12.windows.zip](https://github.com/embree/embree/releases/download/v3.11.0/embree-3.11.0.x64.vc12.windows.zip) -and Visual Studio 2015 -[embree-3.11.0.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v3.11.0/embree-3.11.0.x64.vc14.windows.zip) -are provided as a ZIP file. After unpacking this ZIP file, you should -set the path to the `lib` folder manually to your `PATH` environment -variable for applications to find Embree. To compile applications with -Embree, you also have to set the `Include Directories` path in Visual -Studio to the `include` folder of the Embree installation. - -If you plan to ship Embree with your application, best use the Embree -version from this ZIP file. +Embree linked against Visual Studio 2015 are provided as a ZIP file +[embree-3.13.4.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v3.13.4/embree-3.13.4.x64.vc14.windows.zip). After +unpacking this ZIP file, you should set the path to the `lib` folder +manually to your `PATH` environment variable for applications to find +Embree. Linux tar.gz Files ------------------ The Linux version of Embree is also delivered as a `tar.gz` file: -[embree-3.11.0.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v3.11.0/embree-3.11.0.x86_64.linux.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you -are using the bash shell) or `embree-vars.csh` (if you are using the -C shell) to set up the environment properly: - - tar xzf embree-3.11.0.x86_64.linux.tar.gz - source embree-3.11.0.x86_64.linux/embree-vars.sh +[embree-3.13.4.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v3.13.4/embree-3.13.4.x86_64.linux.tar.gz). Unpack +this file using `tar` and source the provided `embree-vars.sh` (if you +are using the bash shell) or `embree-vars.csh` (if you are using the C +shell) to set up the environment properly: -If you want to ship Embree with your application, best use the Embree -version provided in the `tar.gz` file. + tar xzf embree-3.13.4.x86_64.linux.tar.gz + source embree-3.13.4.x86_64.linux/embree-vars.sh We recommend adding a relative `RPATH` to your application that points to the location where Embree (and TBB) can be found, e.g. `$ORIGIN/../lib`. -macOS PKG Installer -------------------- - -To install the Embree library on your macOS system use the -provided package installer inside -[embree-3.11.0.x86_64.pkg](https://github.com/embree/embree/releases/download/v3.11.0/embree-3.11.0.x86_64.pkg). This -will install Embree by default into `/opt/local/lib` and -`/opt/local/include` directories. The Embree tutorials are installed -into the `/Applications/Embree3` directory. - -You also have to install the Intel® Threading Building Blocks (TBB) -using [MacPorts](http://www.macports.org/): - - sudo port install tbb - -Alternatively you can download the latest TBB version from -[https://www.threadingbuildingblocks.org/download](https://www.threadingbuildingblocks.org/download) -and set the `DYLD_LIBRARY_PATH` environment variable to point -to the TBB library. - -To uninstall Embree, execute the uninstaller script -`/Applications/Embree3/uninstall.command`. - -macOS tar.gz file +macOS ZIP file ----------------- -The macOS version of Embree is also delivered as a `tar.gz` file: -[embree-3.11.0.x86_64.macosx.tar.gz](https://github.com/embree/embree/releases/download/v3.11.0/embree-3.11.0.x86_64.macosx.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you -are using the bash shell) or `embree-vars.csh` (if you are using the -C shell) to set up the environment properly: +The macOS version of Embree is also delivered as a ZIP file: +[embree-3.13.4.x86_64.macosx.zip](https://github.com/embree/embree/releases/download/v3.13.4/embree-3.13.4.x86_64.macosx.zip). Unpack +this file using `tar` and source the provided `embree-vars.sh` (if you +are using the bash shell) or `embree-vars.csh` (if you are using the C +shell) to set up the environment properly: - tar xzf embree-3.11.0.x64.macosx.tar.gz - source embree-3.11.0.x64.macosx/embree-vars.sh + unzip embree-3.13.4.x64.macosx.zip + source embree-3.13.4.x64.macosx/embree-vars.sh If you want to ship Embree with your application, please use the Embree -library of the provided `tar.gz` file. The library name of that Embree +library of the provided ZIP file. The library name of that Embree library is of the form `@rpath/libembree.3.dylib` (and similar also for the included TBB library). This ensures that you can add a relative `RPATH` to your application that points to the location @@ -185,6 +132,7 @@ C++11. Embree is tested with the following compilers: Linux + - Intel® oneAPI DPC++/C++ Compiler 2022.0.0 - Intel® Compiler 2020 Update 1 - Intel® Compiler 2019 Update 4 - Intel® Compiler 2017 Update 1 @@ -192,33 +140,37 @@ Linux - Intel® Compiler 2015 Update 3 - Clang 5.0.0 - Clang 4.0.0 - - GCC 10.0.1 (Fedora 32) - - GCC 8.3.1 (Fedora 28) - - GCC 7.3.1 (Fedora 27) - - GCC 7.3.1 (Fedora 26) - - GCC 6.4.1 (Fedora 25) + - GCC 10.0.1 (Fedora 32) AVX512 support + - GCC 8.3.1 (Fedora 28) AVX512 support + - GCC 7.3.1 (Fedora 27) AVX2 support + - GCC 7.3.1 (Fedora 26) AVX2 support + - GCC 6.4.1 (Fedora 25) AVX2 support -macOS +macOS x86 - Intel® Compiler 2020 Update 1 - Intel® Compiler 2019 Update 4 - Apple LLVM 10.0.1 (macOS 10.14.6) +macOS M1 + + - Apple Clang 12.0.0 + Embree supports using the Intel® Threading Building Blocks (TBB) as the tasking system. For performance and flexibility reasons we recommend to use Embree with the Intel® Threading Building Blocks (TBB) and best also use TBB inside your application. Optionally you can disable TBB in Embree through the `EMBREE_TASKING_SYSTEM` CMake variable. -Embree supports the Intel® SPMD Program Compiler (ISPC), which allows +Embree supports the Intel® Implicit SPMD Program Compiler (Intel® ISPC), which allows straightforward parallelization of an entire renderer. If you do not -want to use ISPC then you can disable `EMBREE_ISPC_SUPPORT` in -CMake. Otherwise, download and install the ISPC binaries (we have -tested ISPC version 1.9.1) from +want to use Intel® ISPC then you can disable `EMBREE_ISPC_SUPPORT` in +CMake. Otherwise, download and install the Intel® ISPC binaries (we have +tested Intel® ISPC version 1.9.1) from [ispc.github.io](https://ispc.github.io/downloads.html). After installation, put the path to `ispc` permanently into your `PATH` environment variable or you need to correctly set the -`ISPC_EXECUTABLE` variable during CMake configuration. +`EMBREE_ISPC_EXECUTABLE` variable during CMake configuration. You additionally have to install CMake 3.1.0 or higher and the developer version of GLUT. @@ -301,6 +253,7 @@ Embree is tested using the following compilers under Windows: - Visual Studio 2019 - Visual Studio 2017 - Visual Studio 2015 (Update 1) + - Intel® oneAPI DPC++/C++ Compiler 2022.0.0 - Intel® Compiler 2019 Update 6 - Intel® Compiler 2017 Update 8 - LLVM Clang 9.0.0 @@ -316,22 +269,28 @@ in Embree through the `EMBREE_TASKING_SYSTEM` CMake variable. Embree will either find the Intel® Threading Building Blocks (TBB) installation that comes with the Intel® Compiler, or you can install the binary distribution of TBB directly from -[www.threadingbuildingblocks.org](https://www.threadingbuildingblocks.org/download) +[https://github.com/oneapi-src/oneTBB/releases](https://github.com/oneapi-src/oneTBB/releases) into a folder named `tbb` into your Embree root directory. You also have to make sure that the libraries `tbb.dll` and `tbb_malloc.dll` can be found when executing your Embree applications, e.g. by putting the path to these libraries into your `PATH` environment variable. -Embree supports the Intel® SPMD Program Compiler (ISPC), which allows +Embree supports the Intel® Implicit SPMD Program Compiler (Intel® ISPC), which allows straightforward parallelization of an entire renderer. When installing -ISPC, make sure to download an ISPC version from +Intel® ISPC, make sure to download an Intel® ISPC version from [ispc.github.io](https://ispc.github.io/downloads.html) that is compatible with your Visual Studio version. After installation, put the path to `ispc.exe` permanently into your `PATH` environment -variable or you need to correctly set the `ISPC_EXECUTABLE` variable -during CMake configuration. We have tested ISPC version 1.9.1. If you -do not want to use ISPC then you can disable `EMBREE_ISPC_SUPPORT` in -CMake. +variable or you need to correctly set the `EMBREE_ISPC_EXECUTABLE` variable +during CMake configuration. If you do not want to use Intel® ISPC then you +can disable `EMBREE_ISPC_SUPPORT` in CMake. + +We have tested Embree with the following Intel® ISPC versions: + + - Intel® ISPC 1.14.1 + - Intel® ISPC 1.13.0 + - Intel® ISPC 1.12.0 + - Intel® ISPC 1.9.2 You additionally have to install [CMake](http://www.cmake.org/download/) (version 2.8.11 or higher). Note that you need a native Windows CMake @@ -416,15 +375,14 @@ parameters that can be configured in CMake: + `EMBREE_STACK_PROTECTOR`: Enables protection of return address from buffer overwrites. This option is OFF by default. -+ `EMBREE_ISPC_SUPPORT`: Enables ISPC support of Embree. This option ++ `EMBREE_ISPC_SUPPORT`: Enables Intel® ISPC support of Embree. This option is ON by default. + `EMBREE_STATIC_LIB`: Builds Embree as a static library (OFF by default). Further multiple static libraries are generated for the different ISAs selected (e.g. `embree3.a`, `embree3_sse42.a`, - `embree3_avx.a`, `embree3_avx2.a`, `embree3_avx512knl.a`, - `embree3_avx512skx.a`). You have to link these libraries in exactly - this order of increasing ISA. + `embree3_avx.a`, `embree3_avx2.a`, `embree3_avx512.a`). You have + to link these libraries in exactly this order of increasing ISA. + `EMBREE_API_NAMESPACE`: Specifies a namespace name to put all Embree API symbols inside. By default no namespace is used and plain C symbols @@ -453,7 +411,7 @@ parameters that can be configured in CMake: + `EMBREE_RAY_PACKETS`: Enables ray packet traversal kernels. This feature is turned ON by default. When turned on packet traversal is used internally and packets passed to rtcIntersect4/8/16 are kept - intact in callbacks (when the ISA of appropiate width is enabled). + intact in callbacks (when the ISA of appropriate width is enabled). + `EMBREE_IGNORE_INVALID_RAYS`: Makes code robust against the risk of full-tree traversals caused by invalid rays (e.g. rays containing @@ -464,24 +422,28 @@ parameters that can be configured in CMake: only), or an internal tasking system (INTERNAL). By default TBB is used. -+ `EMBREE_TBB_ROOT`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_ROOT`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, search the library in this directory tree. -+ `EMBREE_TBB_POSTFIX`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_COMPONENT`: The component/libary name of Intel® Threading + Building Blocks (TBB). Embree searches for this library name (default: tbb) + when TBB is used as tasking system. + ++ `EMBREE_TBB_POSTFIX`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, link to tbb.(so,dll,lib). Defaults to the empty string. -+ `EMBREE_TBB_DEBUG_ROOT`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_DEBUG_ROOT`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, search the library in this directory tree in Debug mode. Defaults to `EMBREE_TBB_ROOT`. -+ `EMBREE_TBB_DEBUG_POSTFIX`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_DEBUG_POSTFIX`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, link to tbb.(so,dll,lib) in Debug mode. Defaults to "_debug". + `EMBREE_MAX_ISA`: Select highest supported ISA (SSE2, SSE4.2, AVX, - AVX2, AVX512KNL, AVX512SKX, or NONE). When set to NONE the + AVX2, AVX512, or NONE). When set to NONE the EMBREE_ISA_* variables can be used to enable ISAs individually. By default the option is set to AVX2. @@ -497,10 +459,7 @@ parameters that can be configured in CMake: + `EMBREE_ISA_AVX2`: Enables AVX2 when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF. -+ `EMBREE_ISA_AVX512KNL`: Enables AVX-512 for Xeon Phi when - EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF. - -+ `EMBREE_ISA_AVX512SKX`: Enables AVX-512 for Skylake when ++ `EMBREE_ISA_AVX512`: Enables AVX-512 for Skylake when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF. + `EMBREE_GEOMETRY_TRIANGLE`: Enables support for trianglegeometries @@ -550,12 +509,8 @@ CMake find Embree using the `FIND_PACKAGE` function inside your FIND_PACKAGE(embree 3.0 REQUIRED) -If you installed Embree using the Linux RPM or macOS PKG installer, -this will automatically find Embree. If you used the `zip` or `tar.gz` -files to extract Embree, you need to set the `embree_DIR` variable to -the folder you extracted Embree to. If you used the Windows MSI -installer, you need to set `embree_DIR` to point to the Embree install -location (e.g. `C:\Program Files\Intel\Embree3`). +To cmake to properly find Embree you need to set the `embree_DIR` +variable to the folder you extracted Embree to. The `FIND_PACKAGE` function will create an embree target that you can add to your target link libraries: @@ -575,13 +530,13 @@ construct 3D scenes and perform ray queries of different types inside these scenes. All API calls carry the prefix `rtc` (or `RTC` for types) which stands for **r**ay **t**racing **c**ore. -The API also exists in an ISPC version, which is almost identical but -contains additional functions that operate on ray packets with a size -of the native SIMD width used by ISPC. For simplicity this document -refers to the C99 version of the API functions. For changes when -upgrading from the Embree 2 to the current Embree 3 API see Section -[Upgrading from Embree 2 to Embree -3](#upgrading-from-embree-2-to-embree-3). +The API also exists in an Intel® Implicit SPMD Program Compiler (Intel® +ISPC) version, which is almost identical but contains additional +functions that operate on ray packets with a size of the native SIMD +width used by Intel® ISPC. For simplicity this document refers to the +C99 version of the API functions. For changes when upgrading from the +Embree 2 to the current Embree 3 API see Section [Upgrading from +Embree 2 to Embree 3]. The API supports scenes consisting of different geometry types such as triangle meshes, quad meshes (triangle pairs), grid meshes, flat @@ -596,13 +551,13 @@ functions) are both supported. The API supports queries for single rays, ray packets, and ray streams. See Section [Ray Queries](#ray-queries) for more information. -The API is designed in an object-oriented manner, e.g. it contains +The API is designed in an object-oriented manner, e.g. it contains device objects (`RTCDevice` type), scene objects (`RTCScene` type), geometry objects (`RTCGeometry` type), buffer objects (`RTCBuffer` type), and BVH objects (`RTCBVH` type). All objects are reference counted, and handles can be released by calling the appropriate release -function (e.g. `rtcReleaseDevice`) or retained by incrementing the -reference count (e.g. `rtcRetainDevice`). In general, API calls that +function (e.g. `rtcReleaseDevice`) or retained by incrementing the +reference count (e.g. `rtcRetainDevice`). In general, API calls that access the same object are not thread-safe, unless specified differently. However, attaching geometries to the same scene and performing ray queries in a scene is thread-safe. @@ -613,22 +568,20 @@ Device Object Embree supports a device concept, which allows different components of the application to use the Embree API without interfering with each other. An application typically first creates a device using the -[rtcNewDevice](#rtcnewdevice) function. This device can then be used to -construct further objects, such as scenes and geometries. Before the -application exits, it should release all devices by invoking -[rtcReleaseDevice](#rtcreleasedevice). An application typically creates -only a single device. If required differently, it should only use a -small number of devices at any given time. +[rtcNewDevice] function. This device can then be used to construct +further objects, such as scenes and geometries. Before the application +exits, it should release all devices by invoking [rtcReleaseDevice]. +An application typically creates only a single device. If required +differently, it should only use a small number of devices at any given +time. Each user thread has its own error flag per device. If an error occurs when invoking an API function, this flag is set to an error code (if it isn't already set by a previous error). See Section -[rtcGetDeviceError](#rtcgetdeviceerror) for information on how to read -the error code and Section -[rtcSetDeviceErrorFunction](#rtcsetdeviceerrorfunction) on how to -register a callback that is invoked for each error encountered. It is -recommended to always set a error callback function, to detect all -errors. +[rtcGetDeviceError] for information on how to read the error code and +Section [rtcSetDeviceErrorFunction] on how to register a callback +that is invoked for each error encountered. It is recommended to always +set a error callback function, to detect all errors. Scene Object ------------ @@ -645,8 +598,7 @@ geometries use the `rtcAttachGeometry` call, and to detach them use the scene description and trigger building of internal data structures. After the scene got committed, it is safe to perform ray queries (see Section [Ray Queries](#ray-queries)) or to query the scene bounding box -(see [rtcGetSceneBounds](#rtcgetscenebounds) and -[rtcGetSceneLinearBounds](#rtcgetscenelinearbounds)). +(see [rtcGetSceneBounds] and [rtcGetSceneLinearBounds]). If scene geometries get modified or attached or detached, the `rtcCommitScene` call must be invoked before performing any further ray @@ -654,18 +606,17 @@ queries for the scene; otherwise the effect of the ray query is undefined. The modification of a geometry, committing the scene, and tracing of rays must always happen sequentially, and never at the same time. Any API call that sets a property of the scene or geometries -contained in the scene count as scene modification, e.g. including +contained in the scene count as scene modification, e.g. including setting of intersection filter functions. Scene flags can be used to configure a scene to use less memory (`RTC_SCENE_FLAG_COMPACT`), use more robust traversal algorithms (`RTC_SCENE_FLAG_ROBUST`), and to optimize for dynamic content. See -Section [rtcSetSceneFlags](#rtcsetsceneflags) for more details. +Section [rtcSetSceneFlags] for more details. A build quality can be specified for a scene to balance between acceleration structure build performance and ray query performance. See -Section [rtcSetSceneBuildQuality](#rtcsetscenebuildquality) for more -details on build quality. +Section [rtcSetSceneBuildQuality] for more details on build quality. Geometry Object --------------- @@ -693,7 +644,7 @@ defined by linearly interpolating the geometries of neighboring time steps. To construct a motion blur geometry, first the number of time steps of the geometry must be specified using the `rtcSetGeometryTimeStepCount` function, and then a vertex buffer for -each time step must be bound, e.g. using the +each time step must be bound, e.g. using the `rtcSetSharedGeometryBuffer` function. Optionally, a time range defining the start (and end time) of the first (and last) time step can be set using the `rtcSetGeometryTimeRange` function. This feature will @@ -707,7 +658,7 @@ intersection found during the `rtcIntersect`-type or `rtcOccluded`-type calls. The former ones are called geometry intersection filter functions, the latter ones geometry occlusion filter functions. These filter functions are designed to be used to ignore intersections -outside of a user-defined silhouette of a primitive, e.g. to model tree +outside of a user-defined silhouette of a primitive, e.g. to model tree leaves using transparency textures. Ray Queries @@ -731,9 +682,8 @@ streams of ray packets (`rtcIntersectNM` and `rtcOccludedNM`), and large packet-like streams in structure of pointer layout (`rtcIntersectNp` and `rtcOccludedNp`). -See Sections [rtcIntersect1](#rtcintersect1) and -[rtcOccluded1](#rtcoccluded1) for a detailed description of how to set -up and trace a ray. +See Sections [rtcIntersect1] and [rtcOccluded1] for a detailed +description of how to set up and trace a ray. See tutorial [Triangle Geometry] for a complete example of how to trace single rays and ray packets. Also have a look at the tutorial @@ -760,11 +710,11 @@ scenes consisting only of user geometries. Embree only performs broadphase collision detection, the narrow phase detection can be performed through a callback function. -See Section [rtcCollide](#rtccollide) for a detailed description of how -to set up collision detection. +See Section [rtcCollide] for a detailed description of how to set up +collision detection. Seen tutorial [Collision Detection](#collision-detection) for a -complete example of collsion detection being used on a simple cloth +complete example of collision detection being used on a simple cloth solver. Miscellaneous @@ -772,7 +722,7 @@ Miscellaneous A context filter function, which can be set per ray query is supported (see `rtcInitIntersectContext`). This filter function is designed to -change the semantics of the ray query, e.g. to accumulate opacity for +change the semantics of the ray query, e.g. to accumulate opacity for transparent shadows, count the number of surfaces along a ray, collect all hits along a ray, etc. @@ -782,9 +732,7 @@ BVH in a user-specified format over user-specified primitives. See the documentation of the `rtcBuildBVH` call for more details. For getting the most performance out of Embree, see the Section -[Performance Recommendations](#performance-recommendations). - - +[Performance Recommendations]. Upgrading from Embree 2 to Embree 3 =================================== @@ -804,7 +752,7 @@ files: ./scripts/cpp-patch.py --patch embree2_to_embree3.patch --in infile.cpp --out outfile.cpp -When invoked for ISPC files, add the `--ispc` option: +When invoked for Intel® ISPC files, add the `--ispc` option: ./scripts/cpp-patch.py --ispc --patch embree2_to_embree3.patch --in infile.ispc --out outfile.ispc @@ -813,7 +761,7 @@ Apply the script to each source file of your project that contains Embree API calls or types. The input file and output file can also be identical to perform the patch in-place. Please always backup your original code before running the script, and inspect the code changes -done by the script using diff (e.g. `git diff`), to make sure no +done by the script using diff (e.g. `git diff`), to make sure no undesired code locations got changed. Grep the code for comments containing `EMBREE_FIXME` and perform the action described in the comment. @@ -841,10 +789,10 @@ Device Scene ----- -- The API no longer distinguishes between a static and a - dynamic scene. Some users had issues as they wanted to do minor - modifications to static scenes, but maintain high - traversal performance. +- The API no longer distinguishes between a static and a dynamic + scene. Some users had issues as they wanted to do minor + modifications to static scenes, but maintain high traversal + performance. The new approach gives more flexibility, as each scene is changeable, and build quality settings can be changed on a commit @@ -873,15 +821,15 @@ Geometry Operations like `rtcInterpolate` can now be performed on the geometry object directly without the need of a scene. Further, an application can choose to create its geometries independent of a - scene, e.g. each time a geometry node is added to its scene graph. + scene, e.g. each time a geometry node is added to its scene graph. This modification changed many API functions to get passed one `RTCGeometry` object instead of a `RTCScene` and `geomID`. The script does all required changed automatically. However, in some cases the script may introduce `rtcGetGeometry(scene, geomID)` calls to retrieve the geometry handle. Best store the geometry - handle inside your scene representation (and release it in - the destructor) and access the handle directly instead of calling + handle inside your scene representation (and release it in the + destructor) and access the handle directly instead of calling `rtcGetGeometry`. - Geometries are not included inside a scene anymore but can be @@ -894,8 +842,8 @@ Geometry earlier error checking and pre-calculating internal data per geometry object. - Such commit points were previously not required in the Embree - 2 API. The upgrade script attempts to insert the commits + Such commit points were previously not required in the Embree 2 + API. The upgrade script attempts to insert the commits automatically, but cannot do so properly under all circumstances. Thus please check if every `rtcCommitGeometry` call inserted by the script is properly placed, and if a `rtcCommitGeometry` call is @@ -969,7 +917,7 @@ Buffers `RTC_USER_VERTEX_BUFFER_TYPE` and additional `slot` specifies a vertex attribute. -Miscellaneous +Miscellaneous {#miscellaneous} ------------- - The header files for Embree 3 are now inside the `embree3` folder @@ -978,8 +926,8 @@ Miscellaneous by side. We made the headers C99 compliant. - All API objects are now reference counted with release functions to - decrement and retain functions to increment the reference count - (if required). + decrement and retain functions to increment the reference count (if + required). - Most callback functions no longer get different arguments as input, but a pointer to a structure containing all arguments. This results @@ -995,11 +943,11 @@ Miscellaneous function with a wrong type if the conversion did not detect some callbacks as such). If the script does not detect a callback function, make sure the argument types match exactly the types in - the header (e.g. write `const int` instead of `int const` or + the header (e.g. write `const int` instead of `int const` or convert the callback manually). -- An intersection context is now required for each ray - query invocation. The context should be initialized using the +- An intersection context is now required for each ray query + invocation. The context should be initialized using the `rtcInitIntersectContext` function. - The `rtcIntersect`-type functions get as input an `RTCRayHit` type, @@ -1031,13 +979,13 @@ Miscellaneous context with a pointer to that data. This change cannot be done by the script. Further, code will still - work if you extend the ray as the implementation did not - change yet. + work if you extend the ray as the implementation did not change + yet. -- The ray structure now contains an additional `id` and - `flags` field. The `id` can be used to store the index of the ray - with respect to a ray packet or ray stream. The `flags` is reserved - for future use, and currently must be set to 0. +- The ray structure now contains an additional `id` and `flags` + field. The `id` can be used to store the index of the ray with + respect to a ray packet or ray stream. The `flags` is reserved for + future use, and currently must be set to 0. - All previous intersection filter callback variants have been removed, except for the `RTCFilterFuncN` which gets a varying size @@ -1048,25 +996,27 @@ Miscellaneous We kept the guarantee that for `rtcIntersect1/4/8/16` and `rtcOccluded1/4/8/16` calls the packet size and ray order will not - change from the initial size and ordering when entering a - filter callback. + change from the initial size and ordering when entering a filter + callback. -- We no longer export ISPC-specific symbols. This has the advantage - that certain linking issues went away, e.g. it is now possible to - link an ISPC application compiled for any combination of ISAs, and - link this to an Embree library compiled with a different set - of ISAs. Previously the ISAs of the application had to be a subset - of the ISAs of Embree, and when the user enabled exactly one ISA, - they had to do this in Embree and the application. +- We no longer export Intel® ISPC-specific symbols. This has the + advantage that certain linking issues went away, e.g. it is now + possible to link an Intel® ISPC application compiled for any + combination of ISAs, and link this to an Embree library compiled + with a different set of ISAs. Previously the ISAs of the + application had to be a subset of the ISAs of Embree, and when the + user enabled exactly one ISA, they had to do this in Embree and the + application. -- We no longer export the ISPC tasking system, which means that the - application has the responsibility to implement the ISPC tasking - system itself. ISPC comes with example code on how to do this. This - change is not performed by the script and must be done manually. +- We no longer export the Intel® ISPC tasking system, which means + that the application has the responsibility to implement the Intel® + ISPC tasking system itself. Intel® ISPC comes with example code on + how to do this. This change is not performed by the script and must + be done manually. -- Fixed many naming inconsistencies, and changed names of further - API functions. All these renamings are properly done by the script - and need no further attention. +- Fixed many naming inconsistencies, and changed names of further API + functions. All these renamings are properly done by the script and + need no further attention. @@ -1105,19 +1055,6 @@ A configuration string (`config` argument) can be passed to the device construction. This configuration string can be `NULL` to use the default configuration. -When creating the device, Embree reads configurations for the device -from the following locations in order: - -1) `config` string passed to the `rtcNewDevice` function -2) `.embree3` file in the application folder -3) `.embree3` file in the home folder - -Settings performed later overwrite previous settings. This way the -configuration for the application can be changed globally (either -through the `rtcNewDevice` call or through the `.embree3` file in the -application folder), and each user has the option to modify the -configuration to fit their needs. - The following configuration is supported: - `threads=[int]`: Specifies a number of build threads to use. A @@ -1128,23 +1065,23 @@ The following configuration is supported: used to join and participate in a scene commit using `rtcJoinCommitScene`. The tasking system will only use threads-user\_threads many worker threads, thus if the app wants to - solely use its threads to commit scenes, just set threads equal - to user\_threads. This option only has effect with the Intel(R) + solely use its threads to commit scenes, just set threads equal to + user\_threads. This option only has effect with the Intel(R) Threading Building Blocks (TBB) tasking system. - `set_affinity=[0/1]`: When enabled, build threads are affinitized to hardware threads. This option is disabled by default on standard CPUs, and enabled by default on Xeon Phi Processors. -- `start_threads=[0/1]`: When enabled, the build threads are - started upfront. This can be useful for benchmarking to exclude - thread creation time. This option is disabled by default. +- `start_threads=[0/1]`: When enabled, the build threads are started + upfront. This can be useful for benchmarking to exclude thread + creation time. This option is disabled by default. -- `isa=[sse2,sse4.2,avx,avx2,avx512knl,avx512skx]`: Use - specified ISA. By default the ISA is selected automatically. +- `isa=[sse2,sse4.2,avx,avx2,avx512]`: Use specified ISA. By default + the ISA is selected automatically. -- `max_isa=[sse2,sse4.2,avx,avx2,avx512knl,avx512skx]`: Configures - the automated ISA selection to use maximally the specified ISA. +- `max_isa=[sse2,sse4.2,avx,avx2,avx512]`: Configures the automated + ISA selection to use maximally the specified ISA. - `hugepages=[0/1]`: Enables or disables usage of huge pages. Under Linux huge pages are used by default but under Windows and macOS @@ -1156,28 +1093,27 @@ The following configuration is supported: is ignored on other platforms. See Section [Huge Page Support] for more details. -- `ignore_config_files=[0/1]`: When set to 1, configuration files - are ignored. Default is 0. - - `verbose=[0,1,2,3]`: Sets the verbosity of the output. When set to 0, no output is printed by Embree, when set to a higher level more - output is printed. By default Embree does not print anything on - the console. + output is printed. By default Embree does not print anything on the + console. - `frequency_level=[simd128,simd256,simd512]`: Specifies the frequency level the application want to run on, which can be - either: a) simd128 for apps that do not use AVX instructions, b) - simd256 for apps that use heavy AVX instruction, c) simd512 for - apps that use heavy AVX-512 instructions. When some frequency level - is specified, Embree will avoid doing optimizations that may reduce - the frequency level below the level specified. E.g. if your app - does not use AVX instructions setting "frequency\_level=simd128" - will cause some CPUs to run at highest frequency, which may result - in higher application performance. However, this will prevent - Embree from using AVX optimizations to achieve higher ray tracing - performance, thus applications that trace many rays may still - perform better with the default setting of simd256, even though - this reduces frequency on some CPUs. + either: + a) simd128 to run at highest frequency + b) simd256 to run at AVX2-heavy frequency level + c) simd512 to run at heavy AVX512 frequency level. When some + frequency level is specified, Embree will avoid doing + optimizations that may reduce the frequency level below the + level specified. E.g. if your app does not use AVX instructions + setting "frequency\_level=simd128" will cause some CPUs to run + at highest frequency, which may result in higher application + performance if you do much shading. If you application heavily + uses AVX code, you should best set the frequency level to + simd256. Per default Embree tries to avoid reducing the + frequency of the CPU by setting the simd256 level only when the + CPU has no significant down clocking. Different configuration options should be separated by commas, e.g.: @@ -1286,9 +1222,9 @@ property is an integer of type `ssize_t`. Possible properties to query are: -- `RTC_DEVICE_PROPERTY_VERSION`: Queries the combined version - number (MAJOR.MINOR.PATCH) with two decimal digits per component. - E.g. for Embree 2.8.3 the integer 208003 is returned. +- `RTC_DEVICE_PROPERTY_VERSION`: Queries the combined version number + (MAJOR.MINOR.PATCH) with two decimal digits per component. E.g. for + Embree 2.8.3 the integer 208003 is returned. - `RTC_DEVICE_PROPERTY_VERSION_MAJOR`: Queries the major version number of Embree. @@ -1316,9 +1252,8 @@ Possible properties to query are: - `RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED`: Queries whether the `rtcIntersect16` and `rtcOccluded16` functions preserve packet size and ray order when invoking callback functions. This is only the - case if Embree is compiled with `EMBREE_RAY_PACKETS` and - `AVX512SKX` (or `AVX512KNL`) enabled, and if the machine it is - running on supports `AVX512SKX` (or `AVX512KNL`). + case if Embree is compiled with `EMBREE_RAY_PACKETS` and `AVX512` + enabled, and if the machine it is running on supports `AVX512`. - `RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED`: Queries whether `rtcIntersect1M`, `rtcIntersect1Mp`, `rtcIntersectNM`, @@ -1376,14 +1311,15 @@ Possible properties to query are: 0. internal tasking system 1. Intel Threading Building Blocks (TBB) 2. Parallel Patterns Library (PPL) -- `RTC_DEVICE_PROPERTY_COMMIT_JOIN_SUPPORTED`: Queries whether + +- `RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED`: Queries whether `rtcJoinCommitScene` is supported. This is not the case when Embree is compiled with PPL or older versions of TBB. - `RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED`: Queries whether - `rtcCommitScene` can get invoked from multiple TBB worker - threads concurrently. This feature is only supported starting with - TBB 2019 Update 9. + `rtcCommitScene` can get invoked from multiple TBB worker threads + concurrently. This feature is only supported starting with TBB 2019 + Update 9. #### EXIT STATUS {#exit-status} @@ -1557,15 +1493,15 @@ threads concurrently. The application can track the current memory usage of the Embree device by atomically accumulating the `bytes` input parameter provided to the -callback function. This parameter will be >0 for allocations and -<0 for deallocations. +callback function. This parameter will be \>0 for allocations and \<0 +for deallocations. Embree will continue its operation normally when returning `true` from the callback function. If `false` is returned, Embree will cancel the current operation with the `RTC_ERROR_OUT_OF_MEMORY` error code. Issuing multiple cancel requests from different threads is allowed. Canceling will only happen when the callback was called for allocations -(bytes > 0), otherwise the cancel request will be ignored. +(bytes \> 0), otherwise the cancel request will be ignored. If a callback to cancel was invoked before the allocation happens (`post == false`), then the `bytes` parameter should not be @@ -1735,9 +1671,9 @@ rtcAttachGeometry The `rtcAttachGeometry` function attaches a geometry (`geometry` argument) to a scene (`scene` argument) and assigns a geometry ID to that geometry. All geometries attached to a scene are defined to be -included inside the scene. A geometry can get attached to multiplee -scene. The geometry ID is unique for the scene, and is used to identify -the geometry when hit by a ray during ray queries. +included inside the scene. 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. This function is thread-safe, thus multiple threads can attach geometries to a scene in parallel. @@ -1868,12 +1804,16 @@ The `rtcGetGeometry` function returns the geometry that is bound to the specified geometry ID (`geomID` argument) for the specified scene (`scene` argument). This function just looks up the handle and does *not* increment the reference count. If you want to get ownership of -the handle, you need to additionally call `rtcRetainGeometry`. For this -reason, this function is fast and can be used during rendering. +the handle, you need to additionally call `rtcRetainGeometry`. + +This function is not thread safe and thus can be used during rendering. However, it is generally recommended to store the geometry handle inside the application's geometry representation and look up the geometry handle from that representation directly. +If you need a thread safe version of this function please use +[rtcGetGeometryThreadSafe]. + #### EXIT STATUS {#exit-status} On failure `NULL` is returned and an error code is set that can be @@ -1881,7 +1821,46 @@ queried using `rtcGetDeviceError`. #### SEE ALSO {#see-also} -[rtcAttachGeometry], [rtcAttachGeometryByID] +[rtcAttachGeometry], [rtcAttachGeometryByID], +[rtcGetGeometryThreadSafe] + + + +rtcGetGeometryThreadSafe +------------------------ + +#### NAME {#name} + + rtcGetGeometryThreadSafe - returns the geometry bound to + the specified geometry ID + +#### SYNOPSIS {#synopsis} + + #include + + RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID); + +#### DESCRIPTION {#description} + +The `rtcGetGeometryThreadSafe` function returns the geometry that is +bound to the specified geometry ID (`geomID` argument) for the +specified scene (`scene` argument). This function just looks up the +handle and does *not* increment the reference count. If you want to get +ownership of the handle, you need to additionally call +`rtcRetainGeometry`. + +This function is thread safe and should NOT get used during rendering. +If you need a fast non-thread safe version during rendering please use +the [rtcGetGeometry] function. + +#### EXIT STATUS {#exit-status} + +On failure `NULL` is returned and an error code is set that can be +queried using `rtcGetDeviceError`. + +#### SEE ALSO {#see-also} + +[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometry] @@ -1921,7 +1900,7 @@ queries for the scene; otherwise the effect of the ray query is undefined. The modification of a geometry, committing the scene, and tracing of rays must always happen sequentially, and never at the same time. Any API call that sets a property of the scene or geometries -contained in the scene count as scene modification, e.g. including +contained in the scene count as scene modification, e.g. including setting of intersection filter functions. The kind of acceleration structure built can be influenced using scene @@ -1929,10 +1908,10 @@ flags (see `rtcSetSceneFlags`), and the quality can be specified using the `rtcSetSceneBuildQuality` function. Embree silently ignores primitives during spatial acceleration -structure construction that would cause numerical issues, e.g. -primitives containing NaNs, INFs, or values greater than 1.844E18f (as -no reasonable calculations can be performed with such values without -causing overflows). +structure construction that would cause numerical issues, +e.g. primitives containing NaNs, INFs, or values greater than 1.844E18f +(as no reasonable calculations can be performed with such values +without causing overflows). #### EXIT STATUS {#exit-status} @@ -2109,11 +2088,11 @@ The `rtcSetSceneBuildQuality` function sets the build quality (`quality` argument) for the specified scene (`scene` argument). Possible values for the build quality are: -- `RTC_BUILD_QUALITY_LOW`: Create lower quality data structures, e.g. - for dynamic scenes. A two-level spatial index structure is built - when enabling this mode, which supports fast partial scene updates, - and allows for setting a per-geometry build quality through the - `rtcSetGeometryBuildQuality` function. +- `RTC_BUILD_QUALITY_LOW`: Create lower quality data structures, + e.g. for dynamic scenes. A two-level spatial index structure is + built when enabling this mode, which supports fast partial scene + updates, and allows for setting a per-geometry build quality + through the `rtcSetGeometryBuildQuality` function. - `RTC_BUILD_QUALITY_MEDIUM`: Default build quality for most usages. Gives a good compromise between build and render performance. @@ -2166,15 +2145,15 @@ for the specified scene (`scene` argument). Possible scene flags are: - `RTC_SCENE_FLAG_ROBUST`: Uses acceleration structures that allow for robust traversal, and avoids optimizations that reduce arithmetic accuracy. This mode is typically used for avoiding - artifacts caused by rays shooting through edges of - neighboring primitives. + artifacts caused by rays shooting through edges of neighboring + primitives. - `RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION`: Enables support for a filter function inside the intersection context for this scene. See Section [rtcInitIntersectContext] for more details. -Multiple flags can be enabled using an `or` operation, e.g. -`RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST`. +Multiple flags can be enabled using an `or` operation, +e.g. `RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST`. #### EXIT STATUS {#exit-status} @@ -2203,7 +2182,7 @@ rtcGetSceneFlags #### DESCRIPTION {#description} Queries the flags of a scene. This function can be useful when setting -individual flags, e.g. to just set the robust mode without changing +individual flags, e.g. to just set the robust mode without changing other flags the following way: RTCSceneFlags flags = rtcGetSceneFlags(scene); @@ -2337,6 +2316,7 @@ rtcNewGeometry RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE, + RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, @@ -2378,6 +2358,7 @@ bases (`RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE`, +`RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE`, @@ -2554,8 +2535,8 @@ over the quadrilateral the following way: Mixed triangle/quad meshes are supported by encoding a triangle as a quad, which can be achieved by replicating the last triangle vertex -(`v0,v1,v2` -> `v0,v1,v2,v2`). This way the second triangle is a -line (which can never get hit), and the parametrization of the first +(`v0,v1,v2` -\> `v0,v1,v2,v2`). 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. A quad whose vertices are laid out counter-clockwise has its geometry @@ -2621,9 +2602,9 @@ Each grid in the grid buffer is of the type `RTCGrid`: The `RTCGrid` structure describes a 2D grid of vertices (with respect to the vertex buffer of the grid mesh). The `width` and `height` -members specify the number of vertices in u and v direction, e.g. -setting both `width` and `height` to 3 sets up a 3×3 vertex grid. The -maximum allowed `width` and `height` is 32767. The `startVertexID` +members specify the number of vertices in u and v direction, +e.g. setting both `width` and `height` to 3 sets up a 3×3 vertex grid. +The maximum allowed `width` and `height` is 32767. The `startVertexID` specifies the ID of the top-left vertex in the vertex grid, while the `stride` parameter specifies a stride (in number of vertices) used to step to the next row. @@ -2813,7 +2794,7 @@ slot `j` can be assigned to use a topology for interpolation using the The face buffer (`RTC_BUFFER_TYPE_FACE` type) is shared between all topologies, which means that the `n`-th primitive always has the same -number of vertices (e.g. being a triangle or a quad) for each topology. +number of vertices (e.g. being a triangle or a quad) for each topology. However, the indices of the topologies themselves may be different. #### EXIT STATUS {#exit-status} @@ -2859,6 +2840,9 @@ RTC\_GEOMETRY\_TYPE\_CURVE 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_ROUND_LINEAR_CURVE - capped cone curve geometry with linear basis and spherical ending @@ -2887,6 +2871,7 @@ RTC\_GEOMETRY\_TYPE\_CURVE rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE); + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE); @@ -2906,6 +2891,7 @@ created by passing `RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BSPLINE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_HERMITE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_CATMULL_ROM_CURVE`, +`RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE`, @@ -2953,14 +2939,14 @@ neighbor bits are automatically calculated base on the index buffer segment exists if segment(id+1)-1 == segment(id)). A left neighbor segment is assumed to end at the start vertex of the -current segement, and to start at the previous vertex in the vertex +current segment, and to start at the previous vertex in the vertex buffer. Similarly, the right neighbor segment is assumed to start at the end vertex of the current segment, and to end at the next vertex in the vertex buffer. Only when the left and right bits are properly specified the current segment can properly attach to the left and/or right neighbor, -otherwise the touching area may not get rendererd properly. +otherwise the touching area may not get rendered properly. ##### Bézier Basis @@ -2979,9 +2965,9 @@ 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. 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 make this basis a good -choise to construct continuous multi-segment curves, as memory +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. ##### Hermite Basis @@ -2995,7 +2981,7 @@ 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 usig the Hermite basis, by calculating a proper tangent +constructed using the Hermite basis, by calculating a proper tangent buffer from the control points. ##### Catmull-Rom Basis @@ -3039,7 +3025,10 @@ product of the normal from the normal spline and tangent of the vertex spline. Note that this construction does not work when the provided normals are parallel to the curve direction. For this reason the provided normals should best be kept as perpendicular to the curve -direction as possible. +direction as possible. We further assume second order derivatives of +the center curve to be zero for this construction, as otherwise very +large curvatures occurring in corner cases, can thicken the constructed +curve significantly. ##### Round Curves @@ -3052,7 +3041,7 @@ 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 segment are clipped away (if that next segment exists). This way a curve is -closed on both ends and the interiour will render properly as long as +closed on both ends and the interior will render properly as long as only neighboring segments penetrate into a segment. For this to work properly it is important that the flags buffer is properly populated with neighbor information. @@ -3221,6 +3210,10 @@ Please have a look at the `rtcSetGeometryBoundsFunction`, `rtcSetGeometryIntersectFunction`, and `rtcSetGeometryOccludedFunction` functions on the implementation of the callback functions. +Primitives of a user geometry are ignored during rendering when their +bounds are empty, thus bounds have lower\>upper in at least one +dimension. + See tutorial [User Geometry] for an example of how to use the user-defined geometries. @@ -3319,8 +3312,8 @@ RTCCurveFlags #include -enum RTCCurveFlags { RTC\_CURVE\_FLAG\_NEIGHBOR\_LEFT = (1 << 0), -RTC\_CURVE\_FLAG\_NEIGHBOR\_RIGHT = (1 << 1) }; +enum RTCCurveFlags { RTC\_CURVE\_FLAG\_NEIGHBOR\_LEFT = (1 \<\< 0), +RTC\_CURVE\_FLAG\_NEIGHBOR\_RIGHT = (1 \<\< 1) }; #### DESCRIPTION {#description} @@ -3684,7 +3677,7 @@ This geometry mask is used together with the ray mask stored inside the `mask` field of the ray. The primitives of the geometry are hit by the ray only if the bitwise `and` operation of the geometry mask with the ray mask is not 0. This feature can be used to disable selected -geometries for specifically tagged rays, e.g. to disable shadow casting +geometries for specifically tagged rays, e.g. to disable shadow casting for certain geometries. Ray masks are disabled in Embree by default at compile time, and can be @@ -3731,8 +3724,8 @@ two-level acceleration structure is build, and geometries build a separate acceleration structure using the geometry build quality. The per-geometry build quality can be one of: -- `RTC_BUILD_QUALITY_LOW`: Creates lower quality data - structures, e.g. for dynamic scenes. +- `RTC_BUILD_QUALITY_LOW`: Creates lower quality data structures, + e.g. for dynamic scenes. - `RTC_BUILD_QUALITY_MEDIUM`: Default build quality for most usages. Gives a good compromise between build and render performance. @@ -3843,7 +3836,7 @@ elements (`byteStride` argument), the format of the buffer elements The start address (`byteOffset` argument) and stride (`byteStride` argument) must be both aligned to 4 bytes; otherwise the -`rtcSetGeometryBuffer` function will fail. +`rtcSetSharedGeometryBuffer` function will fail. When the buffer will be used as a vertex buffer (`RTC_BUFFER_TYPE_VERTEX` and `RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE`), the @@ -3858,8 +3851,8 @@ longer required. Sharing buffers can significantly reduce the memory required by the application, thus we recommend using this feature. When enabling the -`RTC_SCENE_COMPACT` scene flag, the spatial index structures index into -the vertex buffer, resulting in even higher memory savings. +`RTC_SCENE_FLAG_COMPACT` scene flag, the spatial index structures index +into the vertex buffer, resulting in even higher memory savings. #### EXIT STATUS {#exit-status} @@ -3975,12 +3968,12 @@ calls. The `RTC_FORMAT_UINT/2/3/4` format are used to specify that data buffers store unsigned integers, or unsigned integer vectors of size 2,3 or 4. This format has typically to get used when specifying index -buffers, e.g. `RTC_FORMAT_UINT3` for triangle meshes. +buffers, e.g. `RTC_FORMAT_UINT3` for triangle meshes. The `RTC_FORMAT_FLOAT/2/3/4...` format are used to specify that data buffers store single precision floating point values, or vectors there of (size 2,3,4, etc.). This format is typcally used to specify to -format of vertex buffers, e.g. the `RTC_FORMAT_FLOAT3` type for vertex +format of vertex buffers, e.g. the `RTC_FORMAT_FLOAT3` type for vertex buffers of triangle meshes. The `RTC_FORMAT_FLOAT3X4_ROW_MAJOR` and @@ -4866,7 +4859,7 @@ transformations are composed of translation, rotation and uniform scaling and if a matrix M defines a similarity transformation, there is a scaling factor D such that for all x,y: dist(Mx, My) = D \* dist(x, y). In this case the parameter `scalingFactor` is this scaling factor D -and otherwise it is 0. A valid similarity scale (`similarityScale` > +and otherwise it is 0. A valid similarity scale (`similarityScale` \> 0) allows to compute distance information in instance space and scale the distances into world space (for example, to update the query radius, see below) by dividing the instance space distance with the @@ -4880,17 +4873,17 @@ efficient. If there is no instance transform, the similarity scale is 1. The callback function will potentially be called for primitives outside -the query domain for two resons: First, the callback is invoked for all -primitives inside a BVH leaf node since no geometry data of primitives -is determined internally and therefore individual primitives are not -culled (only their (aggregated) bounding boxes). Second, in case non -similarity transformations are used, the resulting ellipsoidal query -domain (in instance space) is approximated by its axis aligned bounding -box internally and therefore inner nodes that do not intersect the -original domain might intersect the approximative bounding box which -results in unneccessary callbacks. In any case, the callbacks are -conservative, i.e. if a primitive is inside the query domain a callback -will be invoked but the reverse is not neccessarily true. +the query domain for two reasons: First, the callback is invoked for +all primitives inside a BVH leaf node since no geometry data of +primitives is determined internally and therefore individual primitives +are not culled (only their (aggregated) bounding boxes). Second, in +case non similarity transformations are used, the resulting ellipsoidal +query domain (in instance space) is approximated by its axis aligned +bounding box internally and therefore inner nodes that do not intersect +the original domain might intersect the approximative bounding box +which results in unnecessary callbacks. In any case, the callbacks are +conservative, i.e. if a primitive is inside the query domain a callback +will be invoked but the reverse is not necessarily true. For efficiency, the radius of the `query` object can be decreased (in world space) inside the callback function to improve culling of @@ -5969,10 +5962,10 @@ and `tfar` members). The ray direction does not have to be normalized, and only the parameter range specified by the `tnear`/`tfar` interval is considered valid. -The ray segment must be in the range $[0, ∞]$, thus ranges that start -behind the ray origin are not allowed, but ranges can reach to -infinity. For rays inside a ray stream, `tfar` < `tnear` identifies -an inactive ray. +The ray segment must be in the range $[0, \infty]$, thus ranges that +start behind the ray origin are not allowed, but ranges can reach to +infinity. For rays inside a ray stream, `tfar` \< `tnear` identifies an +inactive ray. The ray further contains a motion blur time in the range $[0, 1]$ (`time` member), a ray mask (`mask` member), a ray ID (`id` member), @@ -6115,7 +6108,7 @@ RTCRayN #### DESCRIPTION {#description} -When the ray packet size is not known at compile time (e.g. when Embree +When the ray packet size is not known at compile time (e.g. when Embree returns a ray packet in the `RTCFilterFuncN` callback function), Embree uses the `RTCRayN` type for ray packets. These ray packets can only have sizes of 1, 4, 8, or 16. No other packet size will be used. @@ -6127,7 +6120,7 @@ helper functions to access the ray packet components. These helper functions get a pointer to the ray packet (`ray` argument), the packet size (`N` argument), and returns a reference to a -component (e.g. x-component of origin) of the the i-th ray of the +component (e.g. x-component of origin) of the the i-th ray of the packet (`i` argument). #### EXIT STATUS {#exit-status} @@ -6164,7 +6157,7 @@ RTCHitN #### DESCRIPTION {#description} -When the hit packet size is not known at compile time (e.g. when Embree +When the hit packet size is not known at compile time (e.g. when Embree returns a hit packet in the `RTCFilterFuncN` callback function), Embree uses the `RTCHitN` type for hit packets. These hit packets can only have sizes of 1, 4, 8, or 16. No other packet size will be used. @@ -6176,7 +6169,7 @@ helper functions to access hit packet components. These helper functions get a pointer to the hit packet (`hit` argument), the packet size (`N` argument), and returns a reference to a -component (e.g. x component of `Ng`) of the the i-th hit of the packet +component (e.g. x component of `Ng`) of the the i-th hit of the packet (`i` argument). #### EXIT STATUS {#exit-status} @@ -6206,7 +6199,7 @@ RTCRayHitN #### DESCRIPTION {#description} When the packet size of a ray/hit structure is not known at compile -time (e.g. when Embree returns a ray/hit packet in the +time (e.g. when Embree returns a ray/hit packet in the `RTCIntersectFunctionN` callback function), Embree uses the `RTCRayHitN` type for ray packets. These ray/hit packets can only have sizes of 1, 4, 8, or 16. No other packet size will be used. @@ -6270,7 +6263,7 @@ A per ray-query intersection context (`RTCIntersectContext` type) is supported that can be used to configure intersection flags (`flags` member), specify a filter callback function (`filter` member), specify the chain of IDs of the current instance (`instID` and `instStackSize` -members), and to attach arbitrary data to the query (e.g. per ray +members), and to attach arbitrary data to the query (e.g. per ray data). The `rtcInitIntersectContext` function initializes the context to @@ -6282,14 +6275,14 @@ The intersection context flag can be used to tune the behavior of the traversal algorithm. Using the `RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT` flags uses an optimized traversal algorithm for incoherent rays (default), while `RTC_INTERSECT_CONTEXT_FLAG_COHERENT` uses an -optimized traversal algorithm for coherent rays (e.g. primary camera +optimized traversal algorithm for coherent rays (e.g. primary camera rays). Best primary ray performance can be obtained by using the ray stream API and setting the intersect context flag to `RTC_INTERSECT_CONTEXT_FLAG_COHERENT`. For secondary rays, it is typically better to use the `RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT` -flag, unless the rays are known to be very coherent too (e.g. for +flag, unless the rays are known to be very coherent too (e.g. for primary transparency rays). A filter function can be specified inside the context. This filter @@ -6359,9 +6352,9 @@ scene contains motion blur geometries, also the ray time (`time` ray member) must be initialized to a value in the range $[0, 1]$. If ray masks are enabled at compile time, the ray mask (`mask` ray member) must be initialized as well. The ray segment has to be in the range -$[0, ∞]$, thus ranges that start behind the ray origin are not valid, -but ranges can reach to infinity. See Section [RTCRay] for the ray -layout description. +$[0, \infty]$, thus ranges that start behind the ray origin are not +valid, but ranges can reach to infinity. See Section [RTCRay] for the +ray layout description. The geometry ID (`geomID` hit member) of the hit data must be initialized to `RTC_INVALID_GEOMETRY_ID` (-1). @@ -6449,9 +6442,9 @@ the scene contains motion blur geometries, also the ray time (`time` ray member) must be initialized to a value in the range $[0, 1]$. If ray masks are enabled at compile time, the ray mask (`mask` ray member) must be initialized as well. The ray segment must be in the range -$[0, ∞]$, thus ranges that start behind the ray origin are not valid, -but ranges can reach to infinity. See Section [RTCRay] for the ray -layout description. +$[0, \infty]$, thus ranges that start behind the ray origin are not +valid, but ranges can reach to infinity. See Section [RTCRay] for the +ray layout description. When no intersection is found, the ray data is not updated. In case a hit was found, the `tfar` component of the ray is set to `-inf`. @@ -6699,7 +6692,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -6759,7 +6752,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -6818,7 +6811,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -6877,7 +6870,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -6939,7 +6932,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -7002,7 +6995,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -7067,7 +7060,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -7130,7 +7123,7 @@ arbitrarily and re-pack rays into ray packets of different size. For this reason, callback functions may be invoked with an arbitrary packet size (of size 1, 4, 8, or 16) and different ordering as specified initially. For this reason, one may have to use the `rayID` component -of the ray to identify the original ray, e.g. to access a per-ray +of the ray to identify the original ray, e.g. to access a per-ray payload. A ray in a ray stream is considered inactive if its `tnear` value is @@ -7199,7 +7192,7 @@ instancing (see tutorial [ClosestPoint] for a reference implementation of point queries with user defined instancing). The context is an necessary argument to [rtcPointQuery] and Embree -internally uses the topmost instance tranformation of the stack to +internally uses the topmost instance transformation of the stack to transform the point query into instance space. #### EXIT STATUS {#exit-status} @@ -7211,7 +7204,9 @@ No error code is set by this function. [rtcPointQuery], [rtcSetGeometryPointQueryFunction] -\#\# rtcPointQuery + +rtcPointQuery +------------- #### NAME {#name} @@ -7249,8 +7244,8 @@ object (`query` argument) and calls a user defined callback function argument) that intersects the query domain. The user has to initialize the query location (`x`, `y` and `z` member) -and query radius in the range $[0, ∞]$. If the scene contains motion -blur geometries, also the query time (`time` member) must be +and query radius in the range $[0, \infty]$. If the scene contains +motion blur geometries, also the query time (`time` member) must be initialized to a value in the range $[0, 1]$. Further, a `RTCPointQueryContext` (`context` argument) must be created @@ -7265,7 +7260,7 @@ provided with the primID and geomID of the according primitive, however, the geometry information (e.g. triangle index and vertex data) has to be determined manually. The `userPtr` argument can be used to input geometry data of the scene or output results of the point query -(e.g. closest point currently found on surface geometry (see tutorial +(e.g. closest point currently found on surface geometry (see tutorial [ClosestPoint])). The parameter `queryFunc` is optional and can be NULL, in which case @@ -7290,7 +7285,7 @@ has to be taken when the instance transformation contains anisotropic scaling or sheering. In these cases distance computations have to be performed in world space to ensure correctness and the ellipsoidal query domain (in instance space) will be approximated with its axis -aligned bounding box interally. Therefore, the callback function might +aligned bounding box internally. Therefore, the callback function might be invoked even for primitives in inner BVH nodes that do not intersect the query domain. See [rtcSetGeometryPointQueryFunction] for details. @@ -7298,7 +7293,7 @@ The point query structure must be aligned to 16 bytes. #### SUPPORTED PRIMITIVES -Currenly, all primitive types are supported by the point query API +Currently, all primitive types are supported by the point query API except of points (see [RTC\_GEOMETRY\_TYPE\_POINT]), curves (see [RTC\_GEOMETRY\_TYPE\_CURVE]) and sudivision surfaces (see [RTC\_GEOMETRY\_SUBDIVISION]). @@ -7616,7 +7611,7 @@ build flags (`buildFlags` member), re-build performance for dynamic scenes is improved at the cost of higher memory requirements. To spatially split primitives in high quality mode, the builder needs -extra space at the end of the build primitive array to store splitted +extra space at the end of the build primitive array to store split primitives. The total capacity of the build primitive array is passed using the `primitiveArrayCapacity` member, and should be about twice the number of primitives when using spatial splits. @@ -7725,7 +7720,6 @@ $quaternion_r + quaternion_i  \mathbf{i} + quaternion_j  \mathbf{i} + quaterni where $\mathbf{i}$, $\mathbf{j}$ $\mathbf{k}$ are the imaginary quaternion units. The passed quaternion will be normalized internally. -\noindent The affine transformation matrix corresponding to a `RTCQuaternionDecomposition` is $TRS$ and a point $p = (p_x, p_y, p_z, 1)^T$ will be transformed as @@ -7814,7 +7808,7 @@ case you want to benchmark the scene build time, you should start the threads at application startup. You can let Embree start TBB threads by passing `start_threads=1` to the `cfg` parameter of `rtcNewDevice`. -On machines with a high thread count (e.g. dual-socket Xeon or Xeon Phi +On machines with a high thread count (e.g. dual-socket Xeon or Xeon Phi machines), affinitizing TBB worker threads increases build and rendering performance. You can let Embree affinitize TBB worker threads by passing `set_affinity=1` to the `cfg` parameter of `rtcNewDevice`. @@ -7832,7 +7826,7 @@ primary or hard shadow rays, it is recommended to use packets or streams of single rays/packets with setting the `RTC_INTERSECT_CONTEXT_FLAG_COHERENT` flag in the `RTCIntersectContext` passed to the `rtcIntersect`/`rtcOccluded` calls. The total number of -rays in a coherent stream of ray packets should be around 64, e.g. 8 +rays in a coherent stream of ray packets should be around 64, e.g. 8 times 8-wide packets, or 4 times 16-wide packets. The rays inside each packet should be grouped as coherent as possible. @@ -7887,9 +7881,9 @@ Linux](https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt). To use huge pages under Windows, the current user must have the "Lock pages in memory" (SeLockMemoryPrivilege) assigned. This can be configured through the "Local Security Policy" application, by adding a -user to "Local Policies" -> "User Rights Assignment" -> "Lock -pages in memory". You have to log out and in again for this change to -take effect. +user to "Local Policies" -\> "User Rights Assignment" -\> "Lock pages +in memory". You have to log out and in again for this change to take +effect. Further, your application must be executed as an elevated process ("Run as administrator") and the "SeLockMemoryPrivilege" must be explicitly @@ -7929,12 +7923,12 @@ Embree Tutorials Embree comes with a set of tutorials aimed at helping users understand how Embree can be used and extended. There is a very basic minimal that can be compiled as both C and C++, which should get new users started quickly. -All other tutorials exist in an ISPC and C++ version to demonstrate +All other tutorials exist in an Intel® ISPC and C++ version to demonstrate the two versions of the API. Look for files -named `tutorialname_device.ispc` for the ISPC implementation of the +named `tutorialname_device.ispc` for the Intel® ISPC implementation of the tutorial, and files named `tutorialname_device.cpp` for the single ray C++ version of the tutorial. To start the C++ version use the `tutorialname` -executables, to start the ISPC version use the `tutorialname_ispc` +executables, to start the Intel® ISPC version use the `tutorialname_ispc` executables. All tutorials can print available command line options using the `--help` command line parameter. @@ -8019,10 +8013,12 @@ It can be compiled as both C and C++. It demonstrates how to initialize a device and scene, and how to intersect rays with the scene. There is no image output to keep the tutorial as simple as possible. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/minimal/minimal.cpp) + Triangle Geometry ----------------- -![][imgTriangleGeometry] +[![][imgTriangleGeometry]](https://github.com/embree/embree/blob/master/tutorials/triangle_geometry/triangle_geometry_device.cpp) This tutorial demonstrates the creation of a static cube and ground plane using triangle meshes. It also demonstrates the use of the @@ -8030,10 +8026,12 @@ plane using triangle meshes. It also demonstrates the use of the and hard shadows. The cube sides are colored based on the ID of the hit primitive. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/triangle_geometry/triangle_geometry_device.cpp) + Dynamic Scene ------------- -![][imgDynamicScene] +[![][imgDynamicScene]](https://github.com/embree/embree/blob/master/tutorials/dynamic_scene/dynamic_scene_device.cpp) This tutorial demonstrates the creation of a dynamic scene, consisting of several deforming spheres. Half of the spheres use the @@ -8043,10 +8041,12 @@ to use a refitting strategy for these spheres, the other half uses the performance rebuild of their spatial data structure each frame. The spheres are colored based on the ID of the hit sphere geometry. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/dynamic_scene/dynamic_scene_device.cpp) + Multi Scene Geometry ------------- -![][imgDynamicScene] +[![][imgDynamicScene]](https://github.com/embree/embree/blob/master/tutorials/multiscene_geometry/multiscene_geometry_device.cpp) This tutorial demonstrates the creation of multiple scenes sharing the same geometry objects. Here, three scenes are built. One with all @@ -8054,10 +8054,12 @@ the dynamic spheres of the Dynamic Scene test and two others each with half. The ground plane is shared by all three scenes. The space bar is used to cycle the scene chosen for rendering. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/multiscene_geometry/multiscene_geometry_device.cpp) + User Geometry ------------- -![][imgUserGeometry] +[![][imgUserGeometry]](https://github.com/embree/embree/blob/master/tutorials/user_geometry/user_geometry_device.cpp) This tutorial shows the use of user-defined geometry, to re-implement instancing, and to add analytic spheres. A two-level scene is created, @@ -8067,10 +8069,12 @@ The spheres are colored using the instance ID and geometry ID of the hit sphere, to demonstrate how the same geometry instanced in different ways can be distinguished. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/user_geometry/user_geometry_device.cpp) + Viewer ------ -![][imgViewer] +[![][imgViewer]](https://github.com/embree/embree/blob/master/tutorials/viewer/viewer_device.cpp) This tutorial demonstrates a simple OBJ viewer that traces primary visibility rays only. A scene consisting of multiple meshes is created, @@ -8083,10 +8087,12 @@ work: ./viewer -i model.obj +[Source Code](https://github.com/embree/embree/blob/master/tutorials/viewer/viewer_device.cpp) + Stream Viewer ------------- -![][imgViewerStream] +[![][imgViewerStream]](https://github.com/embree/embree/blob/master/tutorials/viewer_stream/viewer_stream_device.cpp) This tutorial is a simple OBJ viewer that demonstrates the use of ray streams. You need to specify an OBJ file at the command line for this @@ -8094,10 +8100,12 @@ tutorial to work: ./viewer_stream -i model.obj +[Source Code](https://github.com/embree/embree/blob/master/tutorials/viewer_stream/viewer_stream_device.cpp) + Intersection Filter ------------------- -![][imgIntersectionFilter] +[![][imgIntersectionFilter]](https://github.com/embree/embree/blob/master/tutorials/intersection_filter/intersection_filter_device.cpp) This tutorial demonstrates the use of filter callback functions to efficiently implement transparent objects. The filter function used for @@ -8107,10 +8115,12 @@ properly, by potentially shooting secondary rays. The filter function used for shadow rays accumulates the transparency of all surfaces along the ray, and terminates traversal if an opaque occluder is hit. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/intersection_filter/intersection_filter_device.cpp) + Instanced Geometry ------------------ -![][imgInstancedGeometry] +[![][imgInstancedGeometry]](https://github.com/embree/embree/blob/master/tutorials/instanced_geometry/instanced_geometry_device.cpp) This tutorial demonstrates the in-build instancing feature of Embree, by instancing a number of other scenes built from triangulated spheres. The @@ -8118,10 +8128,12 @@ spheres are again colored using the instance ID and geometry ID of the hit sphere, to demonstrate how the same geometry instanced in different ways can be distinguished. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/instanced_geometry/instanced_geometry_device.cpp) + Multi Level Instancing ---------------------- -![][imgMultiLevelInstancing] +[![][imgMultiLevelInstancing]](https://github.com/embree/embree/blob/master/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp) This tutorial demonstrates multi-level instancing, i.e., nesting instances into instances. To enable the tutorial, set the compile-time variable @@ -8139,10 +8151,12 @@ During shading, the instance ID stack is used to accumulate normal transformation matrices for each hit. The tutorial visualizes transformed normals as colors. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp) + Path Tracer ----------- -![][imgPathtracer] +[![][imgPathtracer]](https://github.com/embree/embree/blob/master/tutorials/pathtracer/pathtracer_device.cpp) This tutorial is a simple path tracer, based on the viewer tutorial. @@ -8164,58 +8178,72 @@ To render these models execute the following: ./pathtracer -c crown/crown.ecs ./pathtracer -c asian_dragon/asian_dragon.ecs +[Source Code](https://github.com/embree/embree/blob/master/tutorials/pathtracer/pathtracer_device.cpp) + Hair ---- -![][imgHairGeometry] +[![][imgHairGeometry]](https://github.com/embree/embree/blob/master/tutorials/hair_geometry/hair_geometry_device.cpp) This tutorial demonstrates the use of the hair geometry to render a hairball. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/hair_geometry/hair_geometry_device.cpp) + Curve Geometry -------------- -![][imgCurveGeometry] +[![][imgCurveGeometry]](https://github.com/embree/embree/blob/master/tutorials/curve_geometry/curve_geometry_device.cpp) + +This tutorial demonstrates the use of the Linear Basis, B-Spline, and Catmull-Rom curve geometries. -This tutorial demonstrates the use of the B-Spline and Catmull-Rom curve geometries. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/curve_geometry/curve_geometry_device.cpp) Subdivision Geometry -------------------- -![][imgSubdivisionGeometry] +[![][imgSubdivisionGeometry]](https://github.com/embree/embree/blob/master/tutorials/subdivision_geometry/subdivision_geometry_device.cpp) This tutorial demonstrates the use of Catmull-Clark subdivision surfaces. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/subdivision_geometry/subdivision_geometry_device.cpp) + Displacement Geometry --------------------- -![][imgDisplacementGeometry] +[![][imgDisplacementGeometry]](https://github.com/embree/embree/blob/master/tutorials/displacement_geometry/displacement_geometry_device.cpp) This tutorial demonstrates the use of Catmull-Clark subdivision surfaces with procedural displacement mapping using a constant edge tessellation level. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/displacement_geometry/displacement_geometry_device.cpp) + Grid Geometry --------------------- -![][imgGridGeometry] +[![][imgGridGeometry]](https://github.com/embree/embree/tree/master/tutorials/grid_geometry) This tutorial demonstrates the use of the memory efficient grid primitive to handle highly tessellated and displaced geometry. +[Source Code](https://github.com/embree/embree/tree/master/tutorials/grid_geometry) + Point Geometry --------------------- -![][imgPointGeometry] +[![][imgPointGeometry]](https://github.com/embree/embree/blob/master/tutorials/point_geometry/point_geometry_device.cpp) This tutorial demonstrates the use of the three representations of point geometry. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/point_geometry/point_geometry_device.cpp) + Motion Blur Geometry -------------------- -![][imgMotionBlurGeometry] +[![][imgMotionBlurGeometry]](https://github.com/embree/embree/blob/master/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp) This tutorial demonstrates rendering of motion blur using the multi-segment motion blur feature. Shown is motion blur of a triangle mesh, @@ -8229,10 +8257,12 @@ The number of time steps used can be configured using the `--time-steps geometry can be rendered at a specific time using the the `--time ` command line parameter. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp) + Quaternion Motion Blur ---------------------- -![][imgQuaternionMotionBlur] +[![][imgQuaternionMotionBlur]](https://github.com/embree/embree/blob/master/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp) This tutorial demonstrates rendering of motion blur using quaternion interpolation. Shown is motion blur using spherical linear interpolation of @@ -8240,18 +8270,21 @@ the rotational component of the instance transformation on the left and simple linear interpolation of the instance transformation on the right. The number of time steps can be modified as well. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp) Interpolation ------------- -![][imgInterpolation] +[![][imgInterpolation]](https://github.com/embree/embree/blob/master/tutorials/interpolation/interpolation_device.cpp) This tutorial demonstrates interpolation of user-defined per-vertex data. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/interpolation/interpolation_device.cpp) + Closest Point ---------------------- -![][imgClosestPoint] +[![][imgClosestPoint]](https://github.com/embree/embree/blob/master/tutorials/closest_point/closest_point_device.cpp) This tutorial demonstrates a use-case of the point query API. The scene consists of a simple collection of objects that are instanced and for several @@ -8261,19 +8294,23 @@ implemented for Embree internal and for user-defined instancing. The tutorial also illustrates how to handle instance transformations that are not similarity transforms. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/closest_point/closest_point_device.cpp) + Voronoi ---------------------- -![][imgVoronoi] +[![][imgVoronoi]](https://github.com/embree/embree/blob/master/tutorials/voronoi/voronoi_device.cpp) This tutorial demonstrates how to implement nearest neighbour lookups using the point query API. Several colored points are located on a plane and the corresponding voroni regions are illustrated. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/voronoi/voronoi_device.cpp) + Collision Detection ---------------------- -![][imgCollision] +[![][imgCollision]](https://github.com/embree/embree/blob/master/tutorials/collide/collide_device.cpp) This tutorial demonstrates how to implement collision detection using the collide API. A simple cloth solver is setup to collide with a sphere. @@ -8281,6 +8318,8 @@ the collide API. A simple cloth solver is setup to collide with a sphere. The cloth can be reset with the `space` bar. The sim stepped once with `n` and continuous simulation started and paused with `p`. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/collide/collide_device.cpp) + BVH Builder ----------- @@ -8289,6 +8328,8 @@ of Embree to build a bounding volume hierarchy with a user-defined memory layout using a high-quality SAH builder using spatial splits, a standard SAH builder, and a very fast Morton builder. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/bvh_builder/bvh_builder_device.cpp) + BVH Access ----------- @@ -8296,6 +8337,8 @@ This tutorial demonstrates how to access the internal triangle acceleration structure build by Embree. Please be aware that the internal Embree data structures might change between Embree updates. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/bvh_access/bvh_access.cpp) + Find Embree ----------- @@ -8305,6 +8348,8 @@ the Embree installation automatically, under Windows the `embree_DIR` CMake variable must be set to the following folder of the Embree installation: `C:\Program Files\Intel\Embree3`. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/find_embree/CMakeLists.txt) + Next Hit ----------- @@ -8313,6 +8358,8 @@ the ray using multiple ray queries and an intersection filter function. To improve performance, the tutorial also supports collecting the next N hits in a single ray query. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/next_hit/next_hit_device.cpp) + [Embree API]: #embree-api diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..4639e7da22 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,14 @@ +Security Policy +=============== + +Intel is committed to rapidly addressing security vulnerabilities +affecting our customers and providing clear guidance on the solution, +impact, severity and mitigation. + +Reporting a Vulnerability +------------------------- + +Please [report any security vulnerabilities][guidelines] in this project +utilizing the [guidelines here][guidelines]. + +[guidelines]: https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html "Vulnerability Handling Guidelines" diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ffe44c7220..47868652d7 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,9 +1,8 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_SUBDIRECTORY(sys) ADD_SUBDIRECTORY(math) ADD_SUBDIRECTORY(simd) ADD_SUBDIRECTORY(lexers) -ADD_SUBDIRECTORY(tasking) -ADD_SUBDIRECTORY(algorithms) +ADD_SUBDIRECTORY(tasking) \ No newline at end of file diff --git a/common/algorithms/CMakeLists.txt b/common/algorithms/CMakeLists.txt deleted file mode 100644 index 5667d2bd34..0000000000 --- a/common/algorithms/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -## Copyright 2009-2020 Intel Corporation -## SPDX-License-Identifier: Apache-2.0 - -ADD_LIBRARY(algorithms OBJECT - parallel_for.cpp - parallel_reduce.cpp - parallel_prefix_sum.cpp - parallel_for_for.cpp - parallel_for_for_prefix_sum.cpp - parallel_partition.cpp - parallel_sort.cpp - parallel_set.cpp - parallel_map.cpp - parallel_filter.cpp -) - -SET_PROPERTY(TARGET algorithms PROPERTY FOLDER common) -SET_PROPERTY(TARGET algorithms APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - -# ideally we would use target_link_libraries to provide the algorithms target -# with the TBB include directory information. Howeve, this is only possible in -# very recent versions of TBB and therefore we use the target property instead -GET_TARGET_PROPERTY(tasking_include_dirs tasking INCLUDE_DIRECTORIES) -if (tasking_include_dirs) - TARGET_INCLUDE_DIRECTORIES(algorithms PUBLIC "${tasking_include_dirs}") - GET_TARGET_PROPERTY(algorithms_include_dirs algorithms INCLUDE_DIRECTORIES) -endif() diff --git a/common/algorithms/parallel_any_of.h b/common/algorithms/parallel_any_of.h index 248d5c65d7..a64e4a1889 100644 --- a/common/algorithms/parallel_any_of.h +++ b/common/algorithms/parallel_any_of.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,36 +8,48 @@ namespace embree { - - template + + template __forceinline bool parallel_any_of (Index first, Index last, UnaryPredicate pred) - { - bool ret = false; - + { + bool ret = false; + #if defined(TASKING_TBB) - tbb::parallel_for(tbb::blocked_range{first, last}, [&ret,pred](const tbb::blocked_range& r) { - if (tbb::task::self().is_cancelled()) return; - for (size_t i = r.begin(); i != r.end(); ++i) { - if (pred(i)) { - ret = true; - tbb::task::self().cancel_group_execution(); - } - } - }); +#if TBB_INTERFACE_VERSION >= 12002 + tbb::task_group_context context; + tbb::parallel_for(tbb::blocked_range{first, last}, [&ret,pred,&context](const tbb::blocked_range& r) { + if (context.is_group_execution_cancelled()) return; + for (size_t i = r.begin(); i != r.end(); ++i) { + if (pred(i)) { + ret = true; + context.cancel_group_execution(); + } + } + }); #else - ret = parallel_reduce (first, last, false, - [pred](const range& r)->bool { - bool localret = false; - for (auto i=r.begin(); i() - ); + tbb::parallel_for(tbb::blocked_range{first, last}, [&ret,pred](const tbb::blocked_range& r) { + if (tbb::task::self().is_cancelled()) return; + for (size_t i = r.begin(); i != r.end(); ++i) { + if (pred(i)) { + ret = true; + tbb::task::self().cancel_group_execution(); + } + } + }); #endif - - return ret; - } - +#else + ret = parallel_reduce (first, last, false, [pred](const range& r)->bool { + bool localret = false; + for (auto i=r.begin(); i() + ); +#endif + + return ret; + } + } // end namespace diff --git a/common/algorithms/parallel_filter.cpp b/common/algorithms/parallel_filter.cpp deleted file mode 100644 index acddc0ff81..0000000000 --- a/common/algorithms/parallel_filter.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "parallel_filter.h" -#include "../sys/regression.h" -#include - -namespace embree -{ - struct parallel_filter_regression_test : public RegressionTest - { - parallel_filter_regression_test(const char* name) : RegressionTest(name) { - registerRegressionTest(this); - } - - bool run () - { - bool passed = true; - auto pred = [&]( uint32_t v ) { return (v & 0x3) == 0; }; - - for (size_t N=10; N<1000000; N=size_t(2.1*N)) - { - size_t N0 = rand() % N; - - /* initialize array with random numbers */ - std::vector src(N); - std::map m; - for (size_t i=0; i sum1(0); - parallel_for( size_t(0), size_t(N), size_t(1024), [&](const range& r) - { - size_t s = 0; - for (size_t i=r.begin(); i= 12002 + tbb::task_group_context context; + tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { + func(i); + },context); + if (context.is_group_execution_cancelled()) + throw std::runtime_error("task cancelled"); + #else + tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { + func(i); }); if (tbb::task::self().is_cancelled()) throw std::runtime_error("task cancelled"); + #endif #elif defined(TASKING_PPL) concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) { @@ -51,11 +59,20 @@ namespace embree throw std::runtime_error("task cancelled"); #elif defined(TASKING_TBB) - tbb::parallel_for(tbb::blocked_range(first,last,minStepSize),[&](const tbb::blocked_range& r) { + #if TBB_INTERFACE_VERSION >= 12002 + tbb::task_group_context context; + tbb::parallel_for(tbb::blocked_range(first,last,minStepSize),[&](const tbb::blocked_range& r) { + func(range(r.begin(),r.end())); + },context); + if (context.is_group_execution_cancelled()) + throw std::runtime_error("task cancelled"); + #else + tbb::parallel_for(tbb::blocked_range(first,last,minStepSize),[&](const tbb::blocked_range& r) { func(range(r.begin(),r.end())); }); if (tbb::task::self().is_cancelled()) throw std::runtime_error("task cancelled"); + #endif #elif defined(TASKING_PPL) concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) { @@ -80,11 +97,20 @@ namespace embree template __forceinline void parallel_for_static( const Index N, const Func& func) { - tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { - func(i); - },tbb::simple_partitioner()); - if (tbb::task::self().is_cancelled()) - throw std::runtime_error("task cancelled"); + #if TBB_INTERFACE_VERSION >= 12002 + tbb::task_group_context context; + tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { + func(i); + },tbb::simple_partitioner(),context); + if (context.is_group_execution_cancelled()) + throw std::runtime_error("task cancelled"); + #else + tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { + func(i); + },tbb::simple_partitioner()); + if (tbb::task::self().is_cancelled()) + throw std::runtime_error("task cancelled"); + #endif } typedef tbb::affinity_partitioner affinity_partitioner; @@ -92,11 +118,20 @@ namespace embree template __forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap) { - tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { - func(i); - },ap); - if (tbb::task::self().is_cancelled()) - throw std::runtime_error("task cancelled"); + #if TBB_INTERFACE_VERSION >= 12002 + tbb::task_group_context context; + tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { + func(i); + },ap,context); + if (context.is_group_execution_cancelled()) + throw std::runtime_error("task cancelled"); + #else + tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { + func(i); + },ap); + if (tbb::task::self().is_cancelled()) + throw std::runtime_error("task cancelled"); + #endif } #else diff --git a/common/algorithms/parallel_for_for.cpp b/common/algorithms/parallel_for_for.cpp deleted file mode 100644 index 0337611b35..0000000000 --- a/common/algorithms/parallel_for_for.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "parallel_for_for.h" -#include "../sys/regression.h" - -namespace embree -{ - struct parallel_for_for_regression_test : public RegressionTest - { - parallel_for_for_regression_test(const char* name) : RegressionTest(name) { - registerRegressionTest(this); - } - - bool run () - { - bool passed = true; - - /* create vector with random numbers */ - size_t sum0 = 0; - size_t K = 0; - const size_t M = 1000; - std::vector* > array2(M); - for (size_t i=0; i(N); - for (size_t j=0; j> verify_k(K); - for (size_t i=0; i sum1(0); - parallel_for_for( array2, size_t(1), [&](std::vector* v, const range& r, size_t k) -> size_t - { - size_t s = 0; - for (size_t i=r.begin(); i __forceinline ParallelForForState (ArrayArray& array2, const size_t minStepSize) { init(array2,minStepSize); + } + + template + __forceinline ParallelForForState (const size_t numArrays, const SizeFunc& getSize, const size_t minStepSize) { + init(numArrays,getSize,minStepSize); } - template - __forceinline void init ( ArrayArray& array2, const size_t minStepSize ) + template + __forceinline void init ( const size_t numArrays, const SizeFunc& getSize, const size_t minStepSize ) { /* first calculate total number of elements */ size_t N = 0; - for (size_t i=0; isize() : 0; + for (size_t i=0; iN = N; @@ -54,8 +59,8 @@ namespace embree size_t k0 = (++taskIndex)*N/taskCount; for (size_t i=0, k=0; taskIndex < taskCount; i++) { - assert(isize() : 0; + assert(i= k0 && taskIndex < taskCount) { assert(taskIndex + __forceinline void init ( ArrayArray& array2, const size_t minStepSize ) + { + init(array2.size(),[&](size_t i) { return array2[i] ? array2[i]->size() : 0; },minStepSize); + } + __forceinline size_t size() const { return N; } diff --git a/common/algorithms/parallel_for_for_prefix_sum.cpp b/common/algorithms/parallel_for_for_prefix_sum.cpp deleted file mode 100644 index 0169d8e481..0000000000 --- a/common/algorithms/parallel_for_for_prefix_sum.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "parallel_for_for_prefix_sum.h" -#include "../sys/regression.h" - -namespace embree -{ - struct parallel_for_for_prefix_sum_regression_test : public RegressionTest - { - parallel_for_for_prefix_sum_regression_test(const char* name) : RegressionTest(name) { - registerRegressionTest(this); - } - - bool run () - { - bool passed = true; - - /* create vector with random numbers */ - const size_t M = 10; - std::vector> flattened; - typedef std::vector* > ArrayArray; - ArrayArray array2(M); - size_t K = 0; - for (size_t i=0; i(N); - for (size_t j=0; j> verify_k(K); - for (size_t i=0; i state(array2,size_t(1)); - - /* dry run only counts */ - size_t S = parallel_for_for_prefix_sum0( state, array2, size_t(0), [&](std::vector* v, const range& r, size_t k, size_t i) -> size_t - { - size_t s = 0; - for (size_t i=r.begin(); i* v, const range& r, size_t k, size_t i, const size_t base) -> size_t - { - size_t s = 0; - for (size_t i=r.begin(); i + __forceinline ParallelForForPrefixSumState (size_t numArrays, const SizeFunc& getSize, const size_t minStepSize) + : ParallelForForState(numArrays,getSize,minStepSize) {} + ParallelPrefixSumState prefix_state; }; - template - __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState& state, ArrayArray& array2, Index minStepSize, - const Value& identity, const Func& func, const Reduction& reduction) + template + __forceinline Value parallel_for_for_prefix_sum0_( ParallelForForPrefixSumState& state, Index minStepSize, + const SizeFunc& getSize, const Value& identity, const Func& func, const Reduction& reduction) { /* calculate number of tasks to use */ const size_t taskCount = state.taskCount; + /* perform parallel prefix sum */ parallel_for(taskCount, [&](const size_t taskIndex) { @@ -38,9 +43,9 @@ namespace embree size_t k=k0; Value N=identity; for (size_t i=i0; ksize() : 0; + const size_t size = getSize(i); const size_t r0 = j0, r1 = min(size,r0+k1-k); - if (r1 > r0) N = reduction(N, func(array2[i],range((Index)r0,(Index)r1),(Index)k,(Index)i)); + if (r1 > r0) N = reduction(N, func((Index)i,range((Index)r0,(Index)r1),(Index)k)); k+=r1-r0; j0 = 0; } state.prefix_state.counts[taskIndex] = N; @@ -58,9 +63,10 @@ namespace embree return sum; } - template - __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState& state, ArrayArray& array2, Index minStepSize, - const Value& identity, const Func& func, const Reduction& reduction) + template + __forceinline Value parallel_for_for_prefix_sum1_( ParallelForForPrefixSumState& state, Index minStepSize, + const SizeFunc& getSize, + const Value& identity, const Func& func, const Reduction& reduction) { /* calculate number of tasks to use */ const size_t taskCount = state.taskCount; @@ -76,9 +82,9 @@ namespace embree size_t k=k0; Value N=identity; for (size_t i=i0; ksize() : 0; + const size_t size = getSize(i); const size_t r0 = j0, r1 = min(size,r0+k1-k); - if (r1 > r0) N = reduction(N, func(array2[i],range((Index)r0,(Index)r1),(Index)k,(Index)i,reduction(state.prefix_state.sums[taskIndex],N))); + if (r1 > r0) N = reduction(N, func((Index)i,range((Index)r0,(Index)r1),(Index)k,reduction(state.prefix_state.sums[taskIndex],N))); k+=r1-r0; j0 = 0; } state.prefix_state.counts[taskIndex] = N; @@ -96,6 +102,30 @@ namespace embree return sum; } + template + __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState& state, + ArrayArray& array2, Index minStepSize, + const Value& identity, const Func& func, const Reduction& reduction) + { + return parallel_for_for_prefix_sum0_(state,minStepSize, + [&](Index i) { return array2[i] ? array2[i]->size() : 0; }, + identity, + [&](Index i, const range& r, Index k) { return func(array2[i], r, k, i); }, + reduction); + } + + template + __forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState& state, + ArrayArray& array2, Index minStepSize, + const Value& identity, const Func& func, const Reduction& reduction) + { + return parallel_for_for_prefix_sum1_(state,minStepSize, + [&](Index i) { return array2[i] ? array2[i]->size() : 0; }, + identity, + [&](Index i, const range& r, Index k, const Value& base) { return func(array2[i], r, k, i, base); }, + reduction); + } + template __forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState& state, ArrayArray& array2, const Value& identity, const Func& func, const Reduction& reduction) diff --git a/common/algorithms/parallel_map.cpp b/common/algorithms/parallel_map.cpp deleted file mode 100644 index 09dc303f81..0000000000 --- a/common/algorithms/parallel_map.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "parallel_map.h" -#include "../sys/regression.h" - -namespace embree -{ - struct parallel_map_regression_test : public RegressionTest - { - parallel_map_regression_test(const char* name) : RegressionTest(name) { - registerRegressionTest(this); - } - - bool run () - { - bool passed = true; - - /* create key/value vectors with random numbers */ - const size_t N = 10000; - std::vector keys(N); - std::vector vals(N); - for (size_t i=0; i map; - map.init(keys,vals); - - /* check that all keys are properly mapped */ - for (size_t i=0; i array(N); - for (unsigned i=0; i= split; - } - - return passed; - } - }; - - parallel_partition_regression_test parallel_partition_regression("parallel_partition_regression_test"); -} diff --git a/common/algorithms/parallel_partition.h b/common/algorithms/parallel_partition.h index 3b3ad7c854..98bb81818f 100644 --- a/common/algorithms/parallel_partition.h +++ b/common/algorithms/parallel_partition.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -177,6 +177,7 @@ namespace embree size_t numMisplacedRangesRight = 0; size_t numMisplacedItemsLeft = 0; size_t numMisplacedItemsRight = 0; + (void) numMisplacedItemsRight; for (size_t i=0; i src(N); - for (size_t i=0; i dst(N); - for (auto& v : dst) v = 0; - - for (size_t i=0; i()); - passed &= (sum0 == sum1); - } - - /* check if prefix sum is correct */ - for (size_t i=0, sum=0; i& r) -> size_t - { - size_t s = 0; - for (size_t i=r.begin(); i= 12002 + tbb::task_group_context context; + const Value v = tbb::parallel_reduce(tbb::blocked_range(first,last,minStepSize),identity, + [&](const tbb::blocked_range& r, const Value& start) { return reduction(start,func(range(r.begin(),r.end()))); }, + reduction,context); + if (context.is_group_execution_cancelled()) + throw std::runtime_error("task cancelled"); + return v; + #else const Value v = tbb::parallel_reduce(tbb::blocked_range(first,last,minStepSize),identity, [&](const tbb::blocked_range& r, const Value& start) { return reduction(start,func(range(r.begin(),r.end()))); }, reduction); if (tbb::task::self().is_cancelled()) throw std::runtime_error("task cancelled"); return v; + #endif #else // TASKING_PPL struct AlignedValue { diff --git a/common/algorithms/parallel_set.cpp b/common/algorithms/parallel_set.cpp deleted file mode 100644 index 20b639c1c9..0000000000 --- a/common/algorithms/parallel_set.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "parallel_set.h" -#include "../sys/regression.h" - -namespace embree -{ - struct parallel_set_regression_test : public RegressionTest - { - parallel_set_regression_test(const char* name) : RegressionTest(name) { - registerRegressionTest(this); - } - - bool run () - { - bool passed = true; - - /* create vector with random numbers */ - const size_t N = 10000; - std::vector unsorted(N); - for (size_t i=0; i sorted; - sorted.init(unsorted); - - /* check that all elements are in the set */ - for (size_t i=0; i - struct RadixSortRegressionTest : public RegressionTest - { - RadixSortRegressionTest(const char* name) : RegressionTest(name) { - registerRegressionTest(this); - } - - bool run () - { - bool passed = true; - const size_t M = 10; - - for (size_t N=10; N<1000000; N=size_t(2.1*N)) - { - std::vector src(N); memset(src.data(),0,N*sizeof(Key)); - std::vector tmp(N); memset(tmp.data(),0,N*sizeof(Key)); - for (size_t i=0; i(src.data(),tmp.data(),N); - } - - /* calculate checksum */ - Key sum1 = 0; for (size_t i=0; i test_u32("RadixSortRegressionTestU32"); - RadixSortRegressionTest test_u64("RadixSortRegressionTestU64"); -} diff --git a/common/algorithms/parallel_sort.h b/common/algorithms/parallel_sort.h index 5a33820793..30e56c2bfc 100644 --- a/common/algorithms/parallel_sort.h +++ b/common/algorithms/parallel_sort.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -320,7 +320,7 @@ namespace embree #pragma nounroll #endif for (size_t i=startID; i> (size_t)shift) & (size_t)mask; #else const Key index = ((Key)src[i] >> shift) & mask; @@ -382,7 +382,7 @@ namespace embree #endif for (size_t i=startID; i> (size_t)shift) & (size_t)mask; #else const size_t index = ((Key)src[i] >> shift) & mask; diff --git a/common/cmake/FindOpenImageIO.cmake b/common/cmake/FindOpenImageIO.cmake index 1d06d8801d..086b911836 100644 --- a/common/cmake/FindOpenImageIO.cmake +++ b/common/cmake/FindOpenImageIO.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (NOT OPENIMAGEIO_ROOT) @@ -36,7 +36,7 @@ FIND_PATH(OPENIMAGEIO_ROOT include/OpenImageIO/imageio.h DOC "Root of OpenImageIO installation" HINTS ${OPENIMAGEIO_ROOT} PATHS - ${PROJECT_SOURCE_DIR}/oiio + "${PROJECT_SOURCE_DIR}/oiio" /usr/local /usr / diff --git a/common/cmake/FindPNG.cmake b/common/cmake/FindPNG.cmake index 6f24f90f9c..aa99e04740 100644 --- a/common/cmake/FindPNG.cmake +++ b/common/cmake/FindPNG.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 FIND_PATH( PNG_INCLUDE_DIR NAMES png.h ) diff --git a/common/cmake/FindTBB.cmake b/common/cmake/FindTBB.cmake index 46d5744def..366c1eaef7 100644 --- a/common/cmake/FindTBB.cmake +++ b/common/cmake/FindTBB.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #=============================================================================== @@ -6,8 +6,8 @@ # # The user may specify a version and lists of required and optional components: # -# find_package(TBB 2017.0 EXACT REQUIRED -# tbb tbbmalloc +# find_package(TBB 2017.0 EXACT REQUIRED +# tbb tbbmalloc # OPTIONAL_COMPONENTS tbbmalloc_proxy # QUIET) # @@ -27,7 +27,7 @@ # component targets TBB::, e.g. TBB::tbbmalloc. # # The targets will attempt to link to release versions of TBB in release mode, -# and debug versions in debug mode. +# and debug versions in debug mode. # # In addition to the targets, the script defines: # @@ -39,18 +39,9 @@ # We use INTERFACE libraries, which are only supported in 3.x cmake_minimum_required(VERSION 3.1) - -# CMake before 3.12 used to ignore _ROOT, but we always use this -# variable. Avoid warning by setting the policy to new behaviour, which means -# the variables are used. -if(POLICY CMP0074) - cmake_policy(SET CMP0074 NEW) -endif() - # These two are used to automatically find the root and include directories. set(_TBB_INCLUDE_SUBDIR "include") set(_TBB_HEADER "tbb/tbb.h") -set(_TBB_VERSION_HEADER "tbb/tbb_stddef.h") # Initialize cache variable; but use existing non-cache variable as the default, # and fall back to the environment variable. @@ -145,7 +136,17 @@ endmacro() macro(rk_tbb_check_version) # Extract the version we found in our root. - file(READ ${TBB_INCLUDE_DIR}/${_TBB_VERSION_HEADER} VERSION_HEADER_CONTENT) + if(EXISTS "${TBB_INCLUDE_DIR}/oneapi/tbb/version.h") + set(_TBB_VERSION_HEADER "oneapi/tbb/version.h") + elseif(EXISTS "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h") + set(_TBB_VERSION_HEADER "tbb/tbb_stddef.h") + elseif(EXISTS "${TBB_INCLUDE_DIR}/tbb/version.h") + set(_TBB_VERSION_HEADER "tbb/version.h") + else() + rk_tbb_error("Missing TBB version information. Could not find" + "tbb/tbb_stddef.h or tbb/version.h in ${TBB_INCLUDE_DIR}") + endif() + file(READ "${TBB_INCLUDE_DIR}/${_TBB_VERSION_HEADER}" VERSION_HEADER_CONTENT) string(REGEX MATCH "#define TBB_VERSION_MAJOR ([0-9]+)" DUMMY "${VERSION_HEADER_CONTENT}") set(TBB_VERSION_MAJOR ${CMAKE_MATCH_1}) string(REGEX MATCH "#define TBB_VERSION_MINOR ([0-9]+)" DUMMY "${VERSION_HEADER_CONTENT}") @@ -194,7 +195,7 @@ macro(rk_tbb_reuse_existing_target_components) endif() find_path(TBB_INCLUDE_DIR - NAMES "${_TBB_VERSION_HEADER}" + NAMES "${_TBB_HEADER}" PATHS "${TBB_INCLUDE_DIRS}") # Extract TBB_ROOT from the include path so that rk_tbb_check_version @@ -212,7 +213,7 @@ macro(rk_tbb_reuse_existing_target_components) set(TBB_FOUND TRUE) set(TBB_INCLUDE_DIRS "${TBB_INCLUDE_DIR}") return() - elseif ((TARGET TBB) OR (NOT _TBB_AVAILABLE_COMPONENTS STREQUAL "")) + elseif ((TARGET TBB) OR (NOT _TBB_AVAILABLE_COMPONENTS STREQUAL "")) rk_tbb_error("Ignoring existing TBB targets because required components are missing: ${_TBB_MISSING_COMPONENTS}") endif() endmacro() @@ -314,16 +315,29 @@ function(rk_tbb_find_library COMPONENT_NAME BUILD_CONFIG) # On window, also search the DLL so that the client may install it. set(DLL_NAME "${LIB_NAME}.dll") - find_path(${BIN_DIR_VAR} - NAMES "${DLL_NAME}" - PATHS - ${TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER} - ${TBB_ROOT}/bin - ${TBB_ROOT}/../redist/${TBB_ARCH}/tbb/${TBB_VCVER} - ${TBB_ROOT}/../redist/${TBB_ARCH}_win/tbb/${TBB_VCVER} - NO_DEFAULT_PATH - ) - set(${DLL_VAR} "${${BIN_DIR_VAR}}/${DLL_NAME}" CACHE PATH "${COMPONENT_NAME} ${BUILD_CONFIG} dll path") + + # lib name with version suffix to handle oneTBB tbb12.dll + set(LIB_NAME_VERSION "") + if (${COMPONENT_NAME} STREQUAL "tbb") + if (BUILD_CONFIG STREQUAL "DEBUG") + set(LIB_NAME_VERSION "tbb12_debug") + else() + set(LIB_NAME_VERSION "tbb12") + endif() + endif() + set(DLL_NAME_VERSION "${LIB_NAME_VERSION}.dll") + + find_file(BIN_FILE + NAMES ${DLL_NAME} ${DLL_NAME_VERSION} + PATHS + "${TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER}" + "${TBB_ROOT}/bin" + "${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}" + "${TBB_ROOT}/../redist/${TBB_ARCH}/tbb/${TBB_VCVER}" + "${TBB_ROOT}/../redist/${TBB_ARCH}_win/tbb/${TBB_VCVER}" + NO_DEFAULT_PATH) + get_filename_component(${BIN_DIR_VAR} ${BIN_FILE} DIRECTORY) + set(${DLL_VAR} "${BIN_FILE}" CACHE PATH "${COMPONENT_NAME} ${BUILD_CONFIG} dll path") elseif(APPLE) set(LIB_PATHS ${TBB_ROOT}/lib) else() diff --git a/common/cmake/appleclang.cmake b/common/cmake/appleclang.cmake new file mode 120000 index 0000000000..614df88fcb --- /dev/null +++ b/common/cmake/appleclang.cmake @@ -0,0 +1 @@ +clang.cmake \ No newline at end of file diff --git a/common/cmake/check_arm_neon.cpp b/common/cmake/check_arm_neon.cpp new file mode 100644 index 0000000000..2e1ff862a8 --- /dev/null +++ b/common/cmake/check_arm_neon.cpp @@ -0,0 +1,13 @@ +// Copyright 2009-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#if !defined(__ARM_NEON) +#error "No ARM Neon support" +#endif + +#include + +int main() +{ + return vaddvq_s32(vdupq_n_s32(1)); +} diff --git a/common/cmake/check_globals.cmake b/common/cmake/check_globals.cmake index 5c194e6b61..103a7e3316 100644 --- a/common/cmake/check_globals.cmake +++ b/common/cmake/check_globals.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (WIN32 OR APPLE) @@ -12,7 +12,7 @@ foreach (line ${output}) if ("${line}" MATCHES "O .bss") if (NOT "${line}" MATCHES "std::__ioinit" AND # this is caused by iostream initialization and is likely also ok NOT "${line}" MATCHES "\\(\\)::" AND # this matches a static inside a function which is fine - NOT "${line}" MATCHES "function_local_static_" AND # static variable inside a function (explicitely named) + NOT "${line}" MATCHES "function_local_static_" AND # static variable inside a function (explicitly named) NOT "${line}" MATCHES "__\\$U") # ICC generated locks for static variable inside a function message(WARNING "\nProblematic global variable in non-SSE code:\n" ${line}) endif() diff --git a/common/cmake/check_isa.cpp b/common/cmake/check_isa.cpp index c1c124027b..a9879d2dc1 100644 --- a/common/cmake/check_isa.cpp +++ b/common/cmake/check_isa.cpp @@ -17,11 +17,7 @@ #if \ defined(__AVX512F__) && defined(__AVX512CD__) && \ defined(__AVX512DQ__) && defined(__AVX512BW__) && defined(__AVX512VL__) -char const *info_isa = "ISA" ":" "AVX512SKX"; -#elif \ - defined(__AVX512F__) && defined(__AVX512CD__) && \ - defined(__AVX512ER__) && defined(__AVX512PF__) -char const *info_isa = "ISA" ":" "AVX512KNL"; +char const *info_isa = "ISA" ":" "AVX512"; #elif defined(__AVX2__) char const *info_isa = "ISA" ":" "AVX2"; #elif defined(__AVX__) diff --git a/common/cmake/check_isa_default.cmake b/common/cmake/check_isa_default.cmake index b2b94dda86..7870d68321 100644 --- a/common/cmake/check_isa_default.cmake +++ b/common/cmake/check_isa_default.cmake @@ -14,19 +14,29 @@ ## limitations under the License. ## ## ======================================================================== ## -SET(CHECK_ISA_DIR ${CMAKE_CURRENT_LIST_DIR}) +SET(CHECK_ISA_DIR "${CMAKE_CURRENT_LIST_DIR}") FUNCTION(CHECK_ISA_DEFAULT OUTVAR) - SET(ISA_DEFAULT_BIN ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/check_isa_default.bin) - SET(SRC ${CHECK_ISA_DIR}/check_isa.cpp) + + TRY_COMPILE(COMPILER_SUPPORTS_ARM_NEON "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_arm_neon.cpp") + IF (COMPILER_SUPPORTS_ARM_NEON) + SET(ISA_DEFAULT "NEON") + SET(${OUTVAR} ${ISA_DEFAULT} PARENT_SCOPE) + RETURN() + ENDIF() + + SET(ISA_DEFAULT_BIN "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/check_isa_default.bin") + SET(SRC "${CHECK_ISA_DIR}/check_isa.cpp") TRY_COMPILE(ISA_DEFAULT_COMPILE - ${CMAKE_BINARY_DIR} - ${SRC} - COPY_FILE ${ISA_DEFAULT_BIN} + "${CMAKE_BINARY_DIR}" + "${SRC}" + COPY_FILE "${ISA_DEFAULT_BIN}" ) IF(NOT ISA_DEFAULT_COMPILE) SET(ISA_DEFAULT "SSE2") + SET(${OUTVAR} ${ISA_DEFAULT} PARENT_SCOPE) RETURN() ENDIF() + FILE(STRINGS ${ISA_DEFAULT_BIN} ISA_DEFAULT REGEX "^ISA:") STRING(REPLACE "ISA:" "" ISA_DEFAULT "${ISA_DEFAULT}") SET(${OUTVAR} ${ISA_DEFAULT} PARENT_SCOPE) diff --git a/common/cmake/check_stack_frame_size.cmake b/common/cmake/check_stack_frame_size.cmake index 1f80f731dd..fdbb665c61 100644 --- a/common/cmake/check_stack_frame_size.cmake +++ b/common/cmake/check_stack_frame_size.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (WIN32 OR APPLE) diff --git a/common/cmake/clang.cmake b/common/cmake/clang.cmake index f7f8d9c309..de554a70e5 100644 --- a/common/cmake/clang.cmake +++ b/common/cmake/clang.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 MACRO(_SET_IF_EMPTY VAR VALUE) @@ -7,12 +7,19 @@ MACRO(_SET_IF_EMPTY VAR VALUE) ENDIF() ENDMACRO() -_SET_IF_EMPTY(FLAGS_SSE2 "-msse2") -_SET_IF_EMPTY(FLAGS_SSE42 "-msse4.2") -_SET_IF_EMPTY(FLAGS_AVX "-mavx") -_SET_IF_EMPTY(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2") -_SET_IF_EMPTY(FLAGS_AVX512KNL "-march=knl") -_SET_IF_EMPTY(FLAGS_AVX512SKX "-march=skx") +IF (EMBREE_ARM) + SET(FLAGS_SSE2 "-D__SSE__ -D__SSE2__") + SET(FLAGS_SSE42 "-D__SSE4_2__ -D__SSE4_1__") + SET(FLAGS_AVX "-D__AVX__ -D__SSE4_2__ -D__SSE4_1__ -D__BMI__ -D__BMI2__ -D__LZCNT__") + SET(FLAGS_AVX2 "-D__AVX2__ -D__AVX__ -D__SSE4_2__ -D__SSE4_1__ -D__BMI__ -D__BMI2__ -D__LZCNT__") +ELSE () + # for `thread` keyword + _SET_IF_EMPTY(FLAGS_SSE2 "-msse -msse2 -mno-sse4.2") + _SET_IF_EMPTY(FLAGS_SSE42 "-msse4.2") + _SET_IF_EMPTY(FLAGS_AVX "-mavx") + _SET_IF_EMPTY(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2") + _SET_IF_EMPTY(FLAGS_AVX512 "-march=skx") +ENDIF () IF (WIN32) @@ -33,7 +40,7 @@ IF (WIN32) SET_SOURCE_FILES_PROPERTIES(${file} PROPERTIES COMPILE_FLAGS "/GS-") ENDIF() ENDMACRO() - + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DDEBUG") # enables assertions SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DTBB_USE_DEBUG") # configures TBB in debug mode @@ -45,13 +52,13 @@ IF (WIN32) SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions - + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information - + SET(SECURE_LINKER_FLAGS "") SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default) SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time @@ -62,7 +69,6 @@ IF (WIN32) SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}") INCLUDE(msvc_post) - ELSE() OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON) @@ -71,9 +77,11 @@ ELSE() SET(CMAKE_CXX_FLAGS "") ENDIF() - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char") # treat char as signed on all processors, including ARM + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable -Wno-unused-private-field") IF (NOT APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution ENDIF() @@ -98,6 +106,12 @@ ELSE() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-optimize-sibling-calls") ENDIF() + IF (EMSCRIPTEN) + 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() + SET(CMAKE_CXX_FLAGS_DEBUG "") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions @@ -119,11 +133,13 @@ ELSE() ELSE(APPLE) IF (NOT EMBREE_ADDRESS_SANITIZER) # for address sanitizer this causes link errors SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable + IF (NOT EMSCRIPTEN) + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack + ENDIF() ENDIF() ENDIF(APPLE) diff --git a/common/cmake/crayprgenv.cmake b/common/cmake/crayprgenv.cmake index 11cc275041..b0385743de 100644 --- a/common/cmake/crayprgenv.cmake +++ b/common/cmake/crayprgenv.cmake @@ -17,8 +17,7 @@ SET(FLAGS_SSE2 "-target-cpu=x86_64") SET(FLAGS_SSE42 "NOT_SUPPORTED") SET(FLAGS_AVX "-target-cpu=sandybridge") SET(FLAGS_AVX2 "-target-cpu=haswell") -SET(FLAGS_AVX512KNL "-target-cpu=mic-knl") -SET(FLAGS_AVX512SKX "-target-cpu=x86-skylake") +SET(FLAGS_AVX512 "-target-cpu=x86-skylake") STRING(TOLOWER "${CMAKE_CXX_COMPILER_ID}" _lower_compiler_id) INCLUDE("${CMAKE_CURRENT_LIST_DIR}/${_lower_compiler_id}.cmake" OPTIONAL) diff --git a/common/cmake/create_isa_dummy_file.cmake b/common/cmake/create_isa_dummy_file.cmake index 6c3157f865..fe25b60533 100644 --- a/common/cmake/create_isa_dummy_file.cmake +++ b/common/cmake/create_isa_dummy_file.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 file(WRITE ${dst} "#include \"${src}\"\n") diff --git a/common/cmake/dpcpp.cmake b/common/cmake/dpcpp.cmake new file mode 100644 index 0000000000..aecb35169d --- /dev/null +++ b/common/cmake/dpcpp.cmake @@ -0,0 +1,138 @@ +## Copyright 2009-2022 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +MACRO(_SET_IF_EMPTY VAR VALUE) + IF(NOT ${VAR}) + SET(${VAR} "${VALUE}") + ENDIF() +ENDMACRO() + +_SET_IF_EMPTY(FLAGS_SSE2 "-msse2") +_SET_IF_EMPTY(FLAGS_SSE42 "-msse4.2") +_SET_IF_EMPTY(FLAGS_AVX "-mavx") +_SET_IF_EMPTY(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2") +_SET_IF_EMPTY(FLAGS_AVX512 "-march=skx") + +IF (WIN32) + + SET(COMMON_CXX_FLAGS "") + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception +# SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default) + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -Xclang -fcxx-exceptions") # enable C++ exceptions in Clang + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /w") # disable all warnings + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Gy") # package individual functions + IF (EMBREE_STACK_PROTECTOR) + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides + ELSE() + SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides + ENDIF() + MACRO(DISABLE_STACK_PROTECTOR_FOR_FILE file) + IF (EMBREE_STACK_PROTECTOR) + SET_SOURCE_FILES_PROPERTIES(${file} PROPERTIES COMPILE_FLAGS "/GS-") + ENDIF() + ENDMACRO() + + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DDEBUG") # enables assertions + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DTBB_USE_DEBUG") # configures TBB in debug mode + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Ox") # enable full optimizations + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Oi") # inline intrinsic functions + SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information + SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information + + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions + + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information + SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information + + SET(SECURE_LINKER_FLAGS "") + SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default) + SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time + IF (CMAKE_SIZEOF_VOID_P EQUAL 4) + SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design) + ENDIF() + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}") + + INCLUDE(msvc_post) + + # workaround for file encoding problems of kernels/embree.rc found here https://gitlab.kitware.com/cmake/cmake/-/issues/18311 + set(CMAKE_NINJA_CMCLDEPS_RC OFF) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:precise") # dpcpp has fp-model fast as default + +ELSE() + + OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON) + OPTION(EMBREE_ADDRESS_SANITIZER "Enabled CLANG address sanitizer." OFF) + IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS) + SET(CMAKE_CXX_FLAGS "") + ENDIF() + + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char") # treat char as signed on all processors, including ARM + IF (NOT APPLE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution + ENDIF() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") # generate position independent code suitable for shared libraries + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") # disables strict aliasing rules + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable auto vectorizer + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls + IF (EMBREE_STACK_PROTECTOR) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides + ENDIF() + MACRO(DISABLE_STACK_PROTECTOR_FOR_FILE file) + IF (EMBREE_STACK_PROTECTOR) + SET_SOURCE_FILES_PROPERTIES(${file} PROPERTIES COMPILE_FLAGS "-fno-stack-protector") + ENDIF() + ENDMACRO() + + IF (EMBREE_ADDRESS_SANITIZER) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-optimize-sibling-calls") + ENDIF() + + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel") # links intel runtime statically + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-intel") # links intel runtime statically + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffp-model=precise") # dpcpp has fp-model fast as default + + SET(CMAKE_CXX_FLAGS_DEBUG "") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O3") # enable full optimizations + + SET(CMAKE_CXX_FLAGS_RELEASE "") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # enable full optimizations + + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "") + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG") # disable assertions + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # enable full optimizations + + IF (APPLE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features + ELSE(APPLE) + IF (NOT EMBREE_ADDRESS_SANITIZER) # for address sanitizer this causes link errors + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable + ENDIF() + ENDIF(APPLE) + +ENDIF() diff --git a/common/cmake/embree-config-builddir.cmake b/common/cmake/embree-config-builddir.cmake index d3e2624e59..b73b4b5fb6 100644 --- a/common/cmake/embree-config-builddir.cmake +++ b/common/cmake/embree-config-builddir.cmake @@ -1,8 +1,8 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # use default install config -INCLUDE(${CMAKE_CURRENT_LIST_DIR}/embree-config-install.cmake) +INCLUDE("${CMAKE_CURRENT_LIST_DIR}/embree-config-install.cmake") # and override path variables to match for build directory SET(EMBREE_INCLUDE_DIRS @PROJECT_SOURCE_DIR@/include) diff --git a/common/cmake/embree-config-version.cmake b/common/cmake/embree-config-version.cmake index 830422fe4c..7b2ddac71a 100644 --- a/common/cmake/embree-config-version.cmake +++ b/common/cmake/embree-config-version.cmake @@ -1,15 +1,16 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(PACKAGE_VERSION @EMBREE_VERSION@) -IF (${PACKAGE_FIND_VERSION_MAJOR} EQUAL @EMBREE_VERSION_MAJOR@) - IF (${PACKAGE_FIND_VERSION} VERSION_LESS @EMBREE_VERSION@) - SET(PACKAGE_VERSION_COMPATIBLE 1) - ENDIF() - IF (${PACKAGE_FIND_VERSION} VERSION_EQUAL @EMBREE_VERSION@) - SET(PACKAGE_VERSION_EXACT 1) - ENDIF() -ELSE() - SET(PACKAGE_VERSION_UNSUITABLE 1) +SET(PACKAGE_VERSION_EXACT 0) +SET(PACKAGE_VERSION_COMPATIBLE 0) + +IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) + SET(PACKAGE_VERSION_EXACT 1) + SET(PACKAGE_VERSION_COMPATIBLE 1) +ENDIF() + +IF (PACKAGE_FIND_VERSION_MAJOR EQUAL @EMBREE_VERSION_MAJOR@ AND PACKAGE_FIND_VERSION VERSION_LESS PACKAGE_VERSION) + SET(PACKAGE_VERSION_COMPATIBLE 1) ENDIF() diff --git a/common/cmake/embree-config.cmake b/common/cmake/embree-config.cmake index 9b7370ccd6..b4fc24e8cb 100644 --- a/common/cmake/embree-config.cmake +++ b/common/cmake/embree-config.cmake @@ -1,11 +1,11 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 -SET(EMBREE_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/@EMBREE_RELATIV_ROOT_DIR@) +SET(EMBREE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/@EMBREE_RELATIVE_ROOT_DIR@") GET_FILENAME_COMPONENT(EMBREE_ROOT_DIR "${EMBREE_ROOT_DIR}" ABSOLUTE) -SET(EMBREE_INCLUDE_DIRS ${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_INCLUDEDIR@) -SET(EMBREE_LIBRARY ${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_LIBDIR@/@EMBREE_LIBRARY_FULLNAME@) +SET(EMBREE_INCLUDE_DIRS "${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_INCLUDEDIR@") +SET(EMBREE_LIBRARY "${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_LIBDIR@/@EMBREE_LIBRARY_FULLNAME@") SET(EMBREE_LIBRARIES ${EMBREE_LIBRARY}) SET(EMBREE_VERSION @EMBREE_VERSION@) @@ -19,8 +19,9 @@ SET(EMBREE_ISA_SSE2 @EMBREE_ISA_SSE2@) SET(EMBREE_ISA_SSE42 @EMBREE_ISA_SSE42@) SET(EMBREE_ISA_AVX @EMBREE_ISA_AVX@) SET(EMBREE_ISA_AVX2 @EMBREE_ISA_AVX2@) -SET(EMBREE_ISA_AVX512KNL @EMBREE_ISA_AVX512KNL@) -SET(EMBREE_ISA_AVX512SKX @EMBREE_ISA_AVX512SKX@) +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_BUILD_TYPE @CMAKE_BUILD_TYPE@) SET(EMBREE_ISPC_SUPPORT @EMBREE_ISPC_SUPPORT@) @@ -33,6 +34,7 @@ SET(EMBREE_BACKFACE_CULLING @EMBREE_BACKFACE_CULLING@) SET(EMBREE_FILTER_FUNCTION @EMBREE_FILTER_FUNCTION@) SET(EMBREE_IGNORE_INVALID_RAYS @EMBREE_IGNORE_INVALID_RAYS@) SET(EMBREE_TASKING_SYSTEM @EMBREE_TASKING_SYSTEM@) +SET(EMBREE_TBB_COMPONENT @EMBREE_TBB_COMPONENT@) SET(EMBREE_COMPACT_POLYS @EMBREE_COMPACT_POLYS@) SET(EMBREE_GEOMETRY_TRIANGLE @EMBREE_GEOMETRY_TRIANGLE@) @@ -47,6 +49,10 @@ SET(EMBREE_MAX_INSTANCE_LEVEL_COUNT @EMBREE_MAX_INSTANCE_LEVEL_COUNT@) SET(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR @EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR@) SET(EMBREE_MIN_WIDTH @EMBREE_MIN_WIDTH@) +IF (EMBREE_TASKING_SYSTEM STREQUAL "TBB") + FIND_PACKAGE(TBB REQUIRED ${EMBREE_TBB_COMPONENT}) +ENDIF() + IF (EMBREE_STATIC_LIB) INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/sys-targets.cmake") INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/math-targets.cmake") @@ -54,11 +60,22 @@ IF (EMBREE_STATIC_LIB) INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/lexers-targets.cmake") INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/tasking-targets.cmake") - add_library(TBB::tbb SHARED IMPORTED) - set_target_properties(TBB::tbb PROPERTIES IMPORTED_LOCATION "${EMBREE_ROOT_DIR}/@EMBREE_INSTALLED_TBB@") - -ENDIF() + IF (EMBREE_ISA_SSE42) + INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree_sse42-targets.cmake") + ENDIF() -INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree-targets.cmake") + IF (EMBREE_ISA_AVX) + INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree_avx-targets.cmake") + ENDIF() + IF (EMBREE_ISA_AVX2) + INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree_avx2-targets.cmake") + ENDIF() + IF (EMBREE_ISA_AVX512) + INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree_avx512-targets.cmake") + ENDIF() + +ENDIF() + +INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree-targets.cmake") diff --git a/common/cmake/gnu.cmake b/common/cmake/gnu.cmake index 9ac9fbb2d2..c1ab9bc757 100644 --- a/common/cmake/gnu.cmake +++ b/common/cmake/gnu.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 MACRO(_SET_IF_EMPTY VAR VALUE) @@ -7,19 +7,31 @@ MACRO(_SET_IF_EMPTY VAR VALUE) ENDIF() ENDMACRO() -_SET_IF_EMPTY(FLAGS_SSE2 "-msse2") -_SET_IF_EMPTY(FLAGS_SSE42 "-msse4.2") -_SET_IF_EMPTY(FLAGS_AVX "-mavx") -_SET_IF_EMPTY(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2") -_SET_IF_EMPTY(FLAGS_AVX512KNL "-mavx512f -mavx512pf -mavx512er -mavx512cd -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2") -_SET_IF_EMPTY(FLAGS_AVX512SKX "-mavx512f -mavx512dq -mavx512cd -mavx512bw -mavx512vl -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mprefer-vector-width=256") +IF (EMBREE_ARM) + SET(FLAGS_SSE2 "-D__SSE__ -D__SSE2__") + SET(FLAGS_SSE42 "-D__SSE4_2__ -D__SSE4_1__") + SET(FLAGS_AVX "-D__AVX__ -D__SSE4_2__ -D__SSE4_1__ -D__BMI__ -D__BMI2__ -D__LZCNT__") + SET(FLAGS_AVX2 "-D__AVX2__ -D__AVX__ -D__SSE4_2__ -D__SSE4_1__ -D__BMI__ -D__BMI2__ -D__LZCNT__") +ELSE () + _SET_IF_EMPTY(FLAGS_SSE2 "-msse2") + _SET_IF_EMPTY(FLAGS_SSE42 "-msse4.2") + _SET_IF_EMPTY(FLAGS_AVX "-mavx") + _SET_IF_EMPTY(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2") + _SET_IF_EMPTY(FLAGS_AVX512 "-mavx512f -mavx512dq -mavx512cd -mavx512bw -mavx512vl -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mprefer-vector-width=256") +ENDIF () OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON) IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS) SET(CMAKE_CXX_FLAGS "") ENDIF() -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +IF (EMBREE_ARM) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char") # treat 'char' as 'signed char' + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flax-vector-conversions") # allow lax vector type conversions +ENDIF (EMBREE_ARM) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-class-memaccess") # disables clearing an object of type ‘XXX’ with no trivial copy-assignment; use assignment or value-initialization instead @@ -28,6 +40,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-class-memaccess") # disables SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-overflow") # assume that signed overflow occurs SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-delete-null-pointer-checks") # keep all checks for NULL pointers SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fwrapv") # this option instructs the compiler to assume that signed arithmetic overflow warps around. +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char") # treat char as signed on all processors, including ARM IF (NOT APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution @@ -50,23 +63,32 @@ MACRO(DISABLE_STACK_PROTECTOR_FOR_FILE file) ENDMACRO() SET(CMAKE_CXX_FLAGS_DEBUG "") +IF (EMBREE_ARM) + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsigned-char") # treat 'char' as 'signed char' +ENDIF (EMBREE_ARM) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O3") # enable full optimizations SET(CMAKE_CXX_FLAGS_RELEASE "") +IF (EMBREE_ARM) + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fsigned-char") # treat 'char' as 'signed char' +ENDIF (EMBREE_ARM) SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # enable full optimizations SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "") +IF (EMBREE_ARM) + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fsigned-char") # treat 'char' as 'signed char' +ENDIF (EMBREE_ARM) SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG") # disable assertions SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # enable full optimizations IF (APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features + # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features ELSE(APPLE) SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack diff --git a/common/cmake/installTBB.cmake b/common/cmake/installTBB.cmake index 3f45407b99..87a5c0df56 100644 --- a/common/cmake/installTBB.cmake +++ b/common/cmake/installTBB.cmake @@ -1,22 +1,24 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (EMBREE_STATIC_LIB) INSTALL(TARGETS TBB EXPORT TBB-targets) - INSTALL(EXPORT TBB-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(EXPORT TBB-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() IF (EMBREE_INSTALL_DEPENDENCIES) - IF (TARGET TBB::tbb) - GET_TARGET_PROPERTY(LIB_PATH TBB::tbb IMPORTED_LOCATION_RELEASE) + IF (TARGET TBB::${EMBREE_TBB_COMPONENT}) + GET_TARGET_PROPERTY(LIB_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_RELEASE) IF(WIN32) - INSTALL(FILES ${LIB_PATH} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) - GET_TARGET_PROPERTY(IMPLIB_PATH TBB::tbb IMPORTED_IMPLIB_RELEASE) - INSTALL(FILES ${IMPLIB_PATH} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib) + INSTALL(FILES "${LIB_PATH}" DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) + GET_TARGET_PROPERTY(IMPLIB_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_IMPLIB_RELEASE) + INSTALL(FILES "${IMPLIB_PATH}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib) ELSE() - INSTALL(FILES ${LIB_PATH} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib) + GET_FILENAME_COMPONENT(LIB_DIR "${LIB_PATH}" DIRECTORY) + FILE(GLOB LIB_FILES ${LIB_DIR}/libtbb.*) + INSTALL(FILES ${LIB_FILES} DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib) ENDIF() ELSE() - MESSAGE(SEND_ERROR "Target TBB::tbb not found during install.") + MESSAGE(SEND_ERROR "Target TBB::${EMBREE_TBB_COMPONENT} not found during install.") ENDIF() ENDIF() diff --git a/common/cmake/intel.cmake b/common/cmake/intel.cmake index f1f4eb882c..2c8e86e6c5 100644 --- a/common/cmake/intel.cmake +++ b/common/cmake/intel.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 MACRO(_SET_IF_EMPTY VAR VALUE) @@ -13,8 +13,7 @@ IF (WIN32) _SET_IF_EMPTY(FLAGS_SSE42 "/QxSSE4.2") _SET_IF_EMPTY(FLAGS_AVX "/arch:AVX") _SET_IF_EMPTY(FLAGS_AVX2 "/QxCORE-AVX2") - _SET_IF_EMPTY(FLAGS_AVX512KNL "/QxMIC-AVX512") - _SET_IF_EMPTY(FLAGS_AVX512SKX "/QxCORE-AVX512") + _SET_IF_EMPTY(FLAGS_AVX512 "/QxCORE-AVX512") SET(COMMON_CXX_FLAGS "") SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception @@ -99,8 +98,7 @@ ELSE() _SET_IF_EMPTY(FLAGS_SSE42 "-xsse4.2") _SET_IF_EMPTY(FLAGS_AVX "-xAVX") _SET_IF_EMPTY(FLAGS_AVX2 "-xCORE-AVX2") - _SET_IF_EMPTY(FLAGS_AVX512KNL "-xMIC-AVX512") - _SET_IF_EMPTY(FLAGS_AVX512SKX "-xCORE-AVX512") + _SET_IF_EMPTY(FLAGS_AVX512 "-xCORE-AVX512") OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON) IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS) diff --git a/common/cmake/ispc.cmake b/common/cmake/ispc.cmake index cfb21a5f8d..9ccd27f4c9 100644 --- a/common/cmake/ispc.cmake +++ b/common/cmake/ispc.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # ################################################################## @@ -12,7 +12,7 @@ ENDMACRO () IF (EMBREE_ISPC_SUPPORT) -# ISPC versions to look for, in decending order (newest first) +# ISPC versions to look for, in descending order (newest first) SET(ISPC_VERSION_WORKING "1.9.1" "1.9.0" "1.8.3" "1.8.2") LIST(GET ISPC_VERSION_WORKING -1 ISPC_VERSION_REQUIRED) @@ -32,7 +32,7 @@ IF (NOT EMBREE_ISPC_EXECUTABLE) ENDIF() FOREACH(ver ${ISPC_VERSION_WORKING}) FOREACH(suffix ${ISPC_DIR_SUFFIX}) - LIST(APPEND ISPC_DIR_HINT ${PROJECT_SOURCE_DIR}/../ispc-v${ver}-${suffix}) + LIST(APPEND ISPC_DIR_HINT "${PROJECT_SOURCE_DIR}/../ispc-v${ver}-${suffix}") ENDFOREACH() ENDFOREACH() @@ -73,12 +73,16 @@ MACRO (ISPC_COMPILE) STRING(REPLACE ";" "," ISPC_TARGET_ARGS "${ISPC_TARGETS}") IF (CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(ISPC_ARCHITECTURE "x86-64") + IF (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") + SET(ISPC_ARCHITECTURE "aarch64") + ELSE() + SET(ISPC_ARCHITECTURE "x86-64") + ENDIF() ELSE() SET(ISPC_ARCHITECTURE "x86") ENDIF() - SET(ISPC_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) + SET(ISPC_TARGET_DIR "${CMAKE_CURRENT_BINARY_DIR}") IF(ISPC_INCLUDE_DIR) STRING(REPLACE ";" ";-I;" ISPC_INCLUDE_DIR_PARMS "${ISPC_INCLUDE_DIR}") @@ -104,7 +108,7 @@ MACRO (ISPC_COMPILE) GET_FILENAME_COMPONENT(dir ${src} PATH) SET(outdir "${ISPC_TARGET_DIR}/${dir}") - SET(input ${CMAKE_CURRENT_SOURCE_DIR}/${src}) + SET(input "${CMAKE_CURRENT_SOURCE_DIR}/${src}") SET(deps "") IF (EXISTS ${outdir}/${fname}.dev.idep) @@ -125,10 +129,7 @@ MACRO (ISPC_COMPILE) LIST(LENGTH ISPC_TARGETS NUM_TARGETS) IF (NUM_TARGETS GREATER 1) FOREACH(target ${ISPC_TARGETS}) - # in v1.9.0 ISPC changed the ISA suffix of avx512knl-i32x16 to just 'avx512knl' - IF (${target} STREQUAL "avx512knl-i32x16" AND NOT ISPC_VERSION VERSION_LESS "1.9.0") - SET(target "avx512knl") - ELSEIF (${target} STREQUAL "avx512skx-i32x16") + IF (${target} STREQUAL "avx512skx-i32x16") SET(target "avx512skx") ENDIF() SET(results ${results} "${outdir}/${fname}.dev_${target}${ISPC_TARGET_EXT}") @@ -136,10 +137,10 @@ MACRO (ISPC_COMPILE) ENDIF() ADD_CUSTOM_COMMAND( - OUTPUT ${results} ${ISPC_TARGET_DIR}/${fname}_ispc.h + OUTPUT ${results} "${ISPC_TARGET_DIR}/${fname}_ispc.h" COMMAND ${CMAKE_COMMAND} -E make_directory ${outdir} COMMAND ${EMBREE_ISPC_EXECUTABLE} - -I ${CMAKE_CURRENT_SOURCE_DIR} + -I "${CMAKE_CURRENT_SOURCE_DIR}" ${ISPC_INCLUDE_DIR_PARMS} ${ISPC_DEFINITIONS} --arch=${ISPC_ARCHITECTURE} @@ -149,7 +150,7 @@ MACRO (ISPC_COMPILE) --woff --opt=fast-math ${ISPC_ADDITIONAL_ARGS} - -h ${ISPC_TARGET_DIR}/${fname}_ispc.h + -h "${ISPC_TARGET_DIR}/${fname}_ispc.h" -MMM ${outdir}/${fname}.dev.idep -o ${outdir}/${fname}.dev${ISPC_TARGET_EXT} ${input} diff --git a/common/cmake/msvc.cmake b/common/cmake/msvc.cmake index 1356d1eb63..82458a2fe8 100644 --- a/common/cmake/msvc.cmake +++ b/common/cmake/msvc.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(FLAGS_SSE2 "/D__SSE__ /D__SSE2__") diff --git a/common/cmake/msvc_post.cmake b/common/cmake/msvc_post.cmake index 8fccba2b38..d36d1d0ce3 100644 --- a/common/cmake/msvc_post.cmake +++ b/common/cmake/msvc_post.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # optionally use static runtime library diff --git a/common/cmake/package.cmake b/common/cmake/package.cmake index a4da0001a7..6d4dad73fc 100644 --- a/common/cmake/package.cmake +++ b/common/cmake/package.cmake @@ -1,16 +1,20 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 +INSTALL(DIRECTORY include/embree3 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel) + +# Wenzel, Sep 4, 2020 -- skip all of the other installation instructions for Mitsuba +return() + INCLUDE(GNUInstallDirs) IF (NOT EMBREE_ZIP_MODE AND NOT WIN32 AND NOT APPLE) - SET(CMAKE_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR}/embree${EMBREE_VERSION_MAJOR}) - SET(CMAKE_INSTALL_FULL_BINDIR ${CMAKE_INSTALL_FULL_BINDIR}/embree${EMBREE_VERSION_MAJOR}) + SET(CMAKE_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/embree${EMBREE_VERSION_MAJOR}") + SET(CMAKE_INSTALL_FULL_BINDIR "${CMAKE_INSTALL_FULL_BINDIR}/embree${EMBREE_VERSION_MAJOR}") ENDIF() # use full absolute path as install name IF (NOT EMBREE_ZIP_MODE) - SET(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") ELSE() IF(APPLE) @@ -28,16 +32,16 @@ IF (WIN32) SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) INCLUDE(InstallRequiredSystemLibraries) LIST(FILTER CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS INCLUDE REGEX ".*msvcp[0-9]+\.dll|.*vcruntime[0-9]+\.dll|.*vcruntime[0-9]+_[0-9]+\.dll") - INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT lib) + INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib) ENDIF() ############################################################## # Install Headers ############################################################## -INSTALL(DIRECTORY include/embree3 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel) +# INSTALL(DIRECTORY include/embree3 DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT devel) IF (NOT WIN32) - INSTALL(DIRECTORY man/man3 DESTINATION ${CMAKE_INSTALL_MANDIR} COMPONENT devel) + INSTALL(DIRECTORY man/man3 DESTINATION "${CMAKE_INSTALL_MANDIR}" COMPONENT devel) ENDIF() ############################################################## @@ -52,12 +56,12 @@ ENDIF() # Install Documentation ############################################################## -INSTALL(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) -INSTALL(FILES ${PROJECT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) -INSTALL(FILES ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) -INSTALL(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) -INSTALL(FILES ${PROJECT_SOURCE_DIR}/third-party-programs.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) -INSTALL(FILES ${PROJECT_SOURCE_DIR}/third-party-programs-TBB.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) +INSTALL(FILES "${PROJECT_SOURCE_DIR}/LICENSE.txt" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT lib) +INSTALL(FILES "${PROJECT_SOURCE_DIR}/CHANGELOG.md" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT lib) +INSTALL(FILES "${PROJECT_SOURCE_DIR}/README.md" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT lib) +INSTALL(FILES "${PROJECT_SOURCE_DIR}/readme.pdf" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT lib) +INSTALL(FILES "${PROJECT_SOURCE_DIR}/third-party-programs.txt" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT lib) +INSTALL(FILES "${PROJECT_SOURCE_DIR}/third-party-programs-TBB.txt" DESTINATION "${CMAKE_INSTALL_DOCDIR}" COMPONENT lib) ############################################################## # Install scripts to set embree paths @@ -66,15 +70,15 @@ INSTALL(FILES ${PROJECT_SOURCE_DIR}/third-party-programs-TBB.txt DESTINATION ${C IF (EMBREE_ZIP_MODE) IF (WIN32) ELSEIF(APPLE) - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.sh embree-vars.sh @ONLY) - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.csh embree-vars.csh @ONLY) - INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.sh DESTINATION "." COMPONENT lib) - INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.csh DESTINATION "." COMPONENT lib) + CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.sh" embree-vars.sh @ONLY) + CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.csh" embree-vars.csh @ONLY) + INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-vars.sh" DESTINATION "." COMPONENT lib) + INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-vars.csh" DESTINATION "." COMPONENT lib) ELSE() - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.sh embree-vars.sh @ONLY) - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.csh embree-vars.csh @ONLY) - INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.sh DESTINATION "." COMPONENT lib) - INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.csh DESTINATION "." COMPONENT lib) + CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.sh" embree-vars.sh @ONLY) + CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.csh" embree-vars.csh @ONLY) + INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-vars.sh" DESTINATION "." COMPONENT lib) + INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-vars.csh" DESTINATION "." COMPONENT lib) ENDIF() ENDIF() @@ -88,11 +92,6 @@ ELSE() SET(EMBREE_CONFIG_VERSION ${EMBREE_VERSION_MAJOR}) ENDIF() -IF (APPLE AND NOT EMBREE_ZIP_MODE) - CONFIGURE_FILE(scripts/install_macosx/uninstall.command uninstall.command @ONLY) - INSTALL(PROGRAMS "${PROJECT_BINARY_DIR}/uninstall.command" DESTINATION ${CMAKE_INSTALL_BINDIR}/.. COMPONENT lib) -ENDIF() - # why does this have to be so complicated... IF (EMBREE_STATIC_LIB) SET(EMBREE_LIBRARY_FULLNAME ${CMAKE_STATIC_LIBRARY_PREFIX}${EMBREE_LIBRARY_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}) @@ -106,26 +105,30 @@ ELSE() ENDIF() ENDIF() -IF (WIN32 OR EMBREE_ZIP_MODE) +#IF (WIN32 OR EMBREE_ZIP_MODE) # for local "installs" and on Windows we want the cmake config files placed # in the install root, such that users can point the CMake variable # embree_DIR just to the install folder - SET(EMBREE_CMAKECONFIG_DIR ".") - SET(EMBREE_CMAKEEXPORT_DIR "cmake") - SET(EMBREE_RELATIV_ROOT_DIR ".") +# SET(EMBREE_CMAKECONFIG_DIR ".") +# SET(EMBREE_CMAKEEXPORT_DIR "cmake") +# SET(EMBREE_RELATIVE_ROOT_DIR ".") +#ELSE() +SET(EMBREE_CMAKECONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/embree-${EMBREE_VERSION}") +SET(EMBREE_CMAKEEXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/embree-${EMBREE_VERSION}") +IF (WIN32) + SET(EMBREE_RELATIVE_ROOT_DIR "../../../") ELSE() - SET(EMBREE_CMAKECONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/embree-${EMBREE_VERSION}") - SET(EMBREE_CMAKEEXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/embree-${EMBREE_VERSION}") - FILE(RELATIVE_PATH EMBREE_RELATIV_ROOT_DIR "/${EMBREE_CMAKECONFIG_DIR}" "/") + FILE(RELATIVE_PATH EMBREE_RELATIVE_ROOT_DIR "/${EMBREE_CMAKECONFIG_DIR}" "/") ENDIF() +#ENDIF() CONFIGURE_FILE(common/cmake/embree-config.cmake embree-config-install.cmake @ONLY) CONFIGURE_FILE(common/cmake/embree-config-version.cmake embree-config-version.cmake @ONLY) # create a config file for the build directory CONFIGURE_FILE(common/cmake/embree-config-builddir.cmake embree-config.cmake @ONLY) -INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-install.cmake" DESTINATION ${EMBREE_CMAKECONFIG_DIR} RENAME "embree-config.cmake" COMPONENT devel) -INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION ${EMBREE_CMAKECONFIG_DIR} COMPONENT devel) +INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-install.cmake" DESTINATION "${EMBREE_CMAKECONFIG_DIR}" RENAME "embree-config.cmake" COMPONENT devel) +INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION "${EMBREE_CMAKECONFIG_DIR}" COMPONENT devel) ############################################################## # CPack specific stuff @@ -133,14 +136,14 @@ INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION ${ SET(CPACK_PACKAGE_NAME "Intel(R) Embree Ray Tracing Kernels") SET(CPACK_PACKAGE_FILE_NAME "embree-${EMBREE_VERSION}") -#SET(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/embree-doc/images/icon.png) +#SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/embree-doc/images/icon.png") #SET(CPACK_PACKAGE_RELOCATABLE TRUE) SET(CPACK_STRIP_FILES TRUE) SET(CPACK_PACKAGE_VERSION_MAJOR ${EMBREE_VERSION_MAJOR}) SET(CPACK_PACKAGE_VERSION_MINOR ${EMBREE_VERSION_MINOR}) SET(CPACK_PACKAGE_VERSION_PATCH ${EMBREE_VERSION_PATCH}) -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Intel(R) Embree implements high performance ray tracing kernels including accelertion structure construction and traversal.") +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Intel(R) Embree implements high performance ray tracing kernels including acceleration structure construction and traversal.") SET(CPACK_PACKAGE_VENDOR "Intel Corporation") SET(CPACK_PACKAGE_CONTACT embree_support@intel.com) @@ -159,8 +162,8 @@ SET(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Tutorials demonstrating how to use Emb #SET(CPACK_COMPONENT_LIB_REQUIRED ON) # always install the libs # point to readme and license files -SET(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md) -SET(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE.txt) +SET(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.md") +SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.txt") # Windows specific settings IF(WIN32) @@ -179,94 +182,26 @@ IF(WIN32) SET(VCVER vc14) ENDIF() - IF (NOT EMBREE_ZIP_MODE) - SET(CPACK_GENERATOR WIX) - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.${VCVER}") - SET(CPACK_PACKAGE_INSTALL_DIRECTORY "Intel\\\\Embree${EMBREE_VERSION_MAJOR}") - SET(CPACK_WIX_PRODUCT_GUID "331BD5A9-DAD6-486B-A435-18AAB80${EMBREE_VERSION_NUMBER}") - SET(CPACK_WIX_UPGRADE_GUID "331BD5A9-DAD6-486B-A435-18AAB80${EMBREE_VERSION_MAJOR}0000") # upgrade as long as major version is the same - SET(CPACK_WIX_CMAKE_PACKAGE_REGISTRY TRUE) - IF (EMBREE_TESTING_PACKAGE) - ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.msi ${EMBREE_SIGN_FILE}) - ENDIF() - ELSE() - SET(CPACK_GENERATOR ZIP) - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.${VCVER}.windows") - 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_win.bat ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.zip) - ENDIF() + SET(CPACK_GENERATOR ZIP) + SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.${VCVER}.windows") + 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_win.bat" ${CMAKE_BUILD_TYPE} "${CPACK_PACKAGE_FILE_NAME}.zip") ENDIF() # MacOSX specific settings ELSEIF(APPLE) CONFIGURE_FILE(README.md README.txt) - SET(CPACK_RESOURCE_FILE_README ${PROJECT_BINARY_DIR}/README.txt) - - IF (NOT EMBREE_ZIP_MODE) - SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - SET(CPACK_GENERATOR productbuild) - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64") - SET(CPACK_COMPONENTS_ALL lib devel examples) - #SET(CPACK_MONOLITHIC_INSTALL 1) - SET(CPACK_PACKAGE_NAME embree-${EMBREE_VERSION}) - SET(CPACK_PACKAGE_VENDOR "intel") # creates short name com.intel.embree3.xxx in pkgutil - SET(CPACK_OSX_PACKAGE_VERSION 10.7) - 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}.pkg ${EMBREE_SIGN_FILE}) - ENDIF() - ELSE() - SET(CPACK_GENERATOR ZIP) - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.macosx") - 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}) - ENDIF() - ENDIF() + SET(CPACK_RESOURCE_FILE_README "${PROJECT_BINARY_DIR}/README.txt") -# Linux specific settings -ELSE() - - IF (NOT EMBREE_ZIP_MODE) - - SET(CPACK_GENERATOR RPM) - SET(CPACK_RPM_PACKAGE_NAME "embree${EMBREE_VERSION_MAJOR}") - SET(CPACK_COMPONENTS_ALL devel lib examples) - SET(CPACK_RPM_COMPONENT_INSTALL ON) - SET(CPACK_RPM_FILE_NAME RPM-DEFAULT) - SET(CPACK_RPM_devel_PACKAGE_ARCHITECTURE noarch) - SET(CPACK_RPM_PACKAGE_LICENSE "ASL 2.0") # Apache Software License, Version 2.0 - SET(CPACK_RPM_PACKAGE_GROUP "Development/Libraries") - SET(CPACK_RPM_CHANGELOG_FILE ${CMAKE_BINARY_DIR}/rpm_changelog.txt) # ChangeLog of the RPM - IF (CMAKE_VERSION VERSION_LESS "3.7.0") - EXECUTE_PROCESS(COMMAND date "+%a %b %d %Y" OUTPUT_VARIABLE CHANGELOG_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) - ELSE() - STRING(TIMESTAMP CHANGELOG_DATE "%a %b %d %Y") - ENDIF() - SET(RPM_CHANGELOG "* ${CHANGELOG_DATE} Johannes Günther - ${EMBREE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n- First package") - FILE(WRITE ${CPACK_RPM_CHANGELOG_FILE} ${RPM_CHANGELOG}) - SET(CPACK_RPM_PACKAGE_URL http://embree.github.io/) - SET(CPACK_RPM_DEFAULT_DIR_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # otherwise cmake directory has wrong 775 permissions - - # post install and uninstall scripts - SET(CPACK_RPM_lib_POST_INSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh) - SET(CPACK_RPM_lib_POST_UNINSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh) - IF (EMBREE_TESTING_PACKAGE) - ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_linux.sh - ${EMBREE_ZIP_MODE} ${EMBREE_LIBRARY_NAME} ${EMBREE_VERSION} ${EMBREE_VERSION_MAJOR} ${EMBREE_SIGN_FILE}) - ENDIF() - ELSE() - - SET(CPACK_GENERATOR TGZ) - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.linux") - 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_linux.sh - ${EMBREE_ZIP_MODE} ${EMBREE_LIBRARY_NAME} ${EMBREE_VERSION} ${EMBREE_VERSION_MAJOR} ${EMBREE_SIGN_FILE}) - ENDIF() + SET(CPACK_GENERATOR ZIP) + SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.macosx") + 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}") ENDIF() - + ENDIF() IF (EMBREE_TESTING_PACKAGE) diff --git a/common/cmake/rpm_ldconfig.sh b/common/cmake/rpm_ldconfig.sh index 1652bbdb9d..140a24efa2 100644 --- a/common/cmake/rpm_ldconfig.sh +++ b/common/cmake/rpm_ldconfig.sh @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 /sbin/ldconfig diff --git a/common/cmake/test.cmake b/common/cmake/test.cmake index 08988daa67..7c7983781d 100644 --- a/common/cmake/test.cmake +++ b/common/cmake/test.cmake @@ -1,10 +1,14 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(CTest) IF (WIN32) - SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}") + IF(${CMAKE_CXX_COMPILER} MATCHES ".*icx") + SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") + ELSE() + SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}") + ENDIF() ELSE() SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") ENDIF() @@ -27,22 +31,22 @@ SET_PROPERTY(CACHE EMBREE_TESTING_SDE PROPERTY STRINGS OFF pnr nhm wsm snb ivb h SET(EMBREE_MODEL_DIR "none") IF (EMBREE_TESTING_MODEL_DIR) - SET(EMBREE_MODEL_DIR ${EMBREE_TESTING_MODEL_DIR}) + SET(EMBREE_MODEL_DIR "${EMBREE_TESTING_MODEL_DIR}") ENDIF() MACRO (ADD_EMBREE_NORMAL_CPP_TEST name reference executable args) IF (BUILD_TESTING) ADD_TEST(NAME ${name} - WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR} - COMMAND ${executable} --compare ${EMBREE_MODEL_DIR}/reference/${reference}.tga ${args}) + WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}" + COMMAND ${executable} --compare "${EMBREE_MODEL_DIR}/reference/${reference}.tga" ${args}) ENDIF() ENDMACRO() MACRO (ADD_EMBREE_NORMAL_ISPC_TEST name reference executable args) IF (BUILD_TESTING AND EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS) ADD_TEST(NAME ${name}_ispc - WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR} - COMMAND ${executable}_ispc --compare ${EMBREE_MODEL_DIR}/reference/${reference}.tga ${args}) + WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}" + COMMAND ${executable}_ispc --compare "${EMBREE_MODEL_DIR}/reference/${reference}.tga" ${args}) ENDIF() ENDMACRO() @@ -62,15 +66,15 @@ ENDMACRO() MACRO (ADD_EMBREE_MODEL_TEST name reference executable args model) IF (BUILD_TESTING) ADD_TEST(NAME ${name} - WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR} - COMMAND ${executable} -c ${EMBREE_MODEL_DIR}/${model} --compare ${EMBREE_MODEL_DIR}/reference/${reference}.tga ${args}) + WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}" + COMMAND ${executable} -c "${EMBREE_MODEL_DIR}/${model}" --compare "${EMBREE_MODEL_DIR}/reference/${reference}.tga" ${args}) ENDIF() IF (EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS) IF (BUILD_TESTING) ADD_TEST(NAME ${name}_ispc - WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR} - COMMAND COMMAND ${executable}_ispc -c ${EMBREE_MODEL_DIR}/${model} --compare ${EMBREE_MODEL_DIR}/reference/${reference}.tga ${args}) + WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}" + COMMAND COMMAND ${executable}_ispc -c "${EMBREE_MODEL_DIR}/${model}" --compare "${EMBREE_MODEL_DIR}/reference/${reference}.tga" ${args}) ENDIF() ENDIF() ENDMACRO() @@ -78,7 +82,7 @@ ENDMACRO() MACRO (ADD_EMBREE_MODELS_TEST model_list_file name reference executable) IF (BUILD_TESTING) - SET(full_model_list_file ${EMBREE_TESTING_MODEL_DIR}/${model_list_file}) + SET(full_model_list_file "${EMBREE_TESTING_MODEL_DIR}/${model_list_file}") IF(NOT EXISTS "${full_model_list_file}") MESSAGE(FATAL_ERROR "File ${EMBREE_TESTING_MODEL_DIR}/${model_list_file} does not exist!") @@ -88,7 +92,11 @@ MACRO (ADD_EMBREE_MODELS_TEST model_list_file name reference executable) STRING(REGEX REPLACE "\n" ";" models "${models}") FOREACH (model ${models}) - STRING(REGEX REPLACE "/" "_" modelname "${model}") + IF (model MATCHES "^#") + CONTINUE() + ENDIF() + STRING(REGEX REPLACE " .*" "" modelname "${model}") + STRING(REGEX REPLACE "/" "_" modelname "${modelname}") STRING(REGEX REPLACE ".ecs" "" modelname "${modelname}") ADD_EMBREE_MODEL_TEST(${name}_${modelname} ${reference}_${modelname} ${executable} "${ARGN}" ${model}) ENDFOREACH() @@ -97,8 +105,8 @@ 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) + 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() @@ -113,6 +121,6 @@ IF (EMBREE_TESTING_MEMCHECK) 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}) + add_test(NAME ${name} COMMAND ${memcheck_command} "${MY_PROJECT_BINARY_DIR}/${binary}" ${ARGN}) ENDFUNCTION() ENDIF() diff --git a/common/cmake/tutorial.cmake b/common/cmake/tutorial.cmake index f196823b20..25896a9cae 100644 --- a/common/cmake/tutorial.cmake +++ b/common/cmake/tutorial.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # additional parameters (beyond the name) are treated as additional dependencies @@ -9,7 +9,7 @@ MACRO (ADD_TUTORIAL TUTORIAL_NAME) TARGET_LINK_LIBRARIES(${TUTORIAL_NAME} embree image tutorial noise ${ADDITIONAL_LIBRARIES}) SET_PROPERTY(TARGET ${TUTORIAL_NAME} PROPERTY FOLDER tutorials/single) SET_PROPERTY(TARGET ${TUTORIAL_NAME} APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - INSTALL(TARGETS ${TUTORIAL_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) + INSTALL(TARGETS ${TUTORIAL_NAME} DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) SIGN_TARGET(${TUTORIAL_NAME}) ENDMACRO () @@ -19,7 +19,7 @@ MACRO (ADD_TUTORIAL_ISPC TUTORIAL_NAME) TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_ispc embree image tutorial_ispc noise noise_ispc) SET_PROPERTY(TARGET ${TUTORIAL_NAME}_ispc PROPERTY FOLDER tutorials/ispc) SET_PROPERTY(TARGET ${TUTORIAL_NAME}_ispc APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - INSTALL(TARGETS ${TUTORIAL_NAME}_ispc DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) + INSTALL(TARGETS ${TUTORIAL_NAME}_ispc DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) SIGN_TARGET(${TUTORIAL_NAME}_ispc) ENDIF() ENDMACRO () diff --git a/common/cmake/uninstall.cmake.in b/common/cmake/uninstall.cmake.in index b270e5dfeb..231ef0cbdd 100644 --- a/common/cmake/uninstall.cmake.in +++ b/common/cmake/uninstall.cmake.in @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") diff --git a/common/lexers/CMakeLists.txt b/common/lexers/CMakeLists.txt index 1e519fee9c..1e2452cd9f 100644 --- a/common/lexers/CMakeLists.txt +++ b/common/lexers/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(lexers STATIC @@ -10,8 +10,8 @@ SET_PROPERTY(TARGET lexers PROPERTY FOLDER common) SET_PROPERTY(TARGET lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS lexers EXPORT lexers-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT lexers-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT lexers-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git a/common/lexers/parsestream.h b/common/lexers/parsestream.h index db46dc114f..f65a52cb47 100644 --- a/common/lexers/parsestream.h +++ b/common/lexers/parsestream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/lexers/stream.h b/common/lexers/stream.h index 3f75677e68..a40c15f8eb 100644 --- a/common/lexers/stream.h +++ b/common/lexers/stream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/lexers/streamfilters.h b/common/lexers/streamfilters.h index 25580a77b8..3592b77b03 100644 --- a/common/lexers/streamfilters.h +++ b/common/lexers/streamfilters.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/lexers/stringstream.cpp b/common/lexers/stringstream.cpp index 7e7b9faef8..42ffb10176 100644 --- a/common/lexers/stringstream.cpp +++ b/common/lexers/stringstream.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stringstream.h" diff --git a/common/lexers/stringstream.h b/common/lexers/stringstream.h index e6dbd4aecc..6d9c27e3cd 100644 --- a/common/lexers/stringstream.h +++ b/common/lexers/stringstream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/lexers/tokenstream.cpp b/common/lexers/tokenstream.cpp index d05be65862..6ed6f2045a 100644 --- a/common/lexers/tokenstream.cpp +++ b/common/lexers/tokenstream.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "tokenstream.h" diff --git a/common/lexers/tokenstream.h b/common/lexers/tokenstream.h index 72a7b4f2f3..6e49dd0b39 100644 --- a/common/lexers/tokenstream.h +++ b/common/lexers/tokenstream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/CMakeLists.txt b/common/math/CMakeLists.txt index c9f251fab7..fcfa45598f 100644 --- a/common/math/CMakeLists.txt +++ b/common/math/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(math STATIC constants.cpp) @@ -6,7 +6,7 @@ SET_PROPERTY(TARGET math PROPERTY FOLDER common) SET_PROPERTY(TARGET math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS math EXPORT math-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT math-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT math-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git a/common/math/affinespace.h b/common/math/affinespace.h index 32452fbe72..9d4a0f0846 100644 --- a/common/math/affinespace.h +++ b/common/math/affinespace.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/bbox.h b/common/math/bbox.h index 800fd36544..e4eb3df9a4 100644 --- a/common/math/bbox.h +++ b/common/math/bbox.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -77,7 +77,7 @@ namespace embree return lower > upper; } -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) template<> __forceinline bool BBox::empty() const { return !all(le_mask(lower,upper)); } @@ -91,6 +91,11 @@ namespace embree return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE))); } + /*! tests if box is finite and non-empty*/ + __forceinline bool isvalid_non_empty( const BBox& v ) { + return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)) & le_mask(v.lower,v.upper)); + } + /*! tests if box has finite entries */ __forceinline bool is_finite( const BBox& b) { return is_finite(b.lower) && is_finite(b.upper); @@ -191,11 +196,11 @@ namespace embree } template<> __inline bool subset( const BBox& a, const BBox& b ) { - return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper)); + return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper)); } template<> __inline bool subset( const BBox& a, const BBox& b ) { - return all(ge_mask(a.lower,b.lower)) & all(le_mask(a.upper,b.upper)); + return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper)); } /*! blending */ @@ -223,11 +228,11 @@ namespace embree /// SSE / AVX / MIC specializations //////////////////////////////////////////////////////////////////////////////// -#if defined __SSE__ +#if defined (__SSE__) || defined(__ARM_NEON) #include "../simd/sse.h" #endif -#if defined __AVX__ +#if defined (__AVX__) #include "../simd/avx.h" #endif diff --git a/common/math/col3.h b/common/math/col3.h index 2a477ec131..3f50c04393 100644 --- a/common/math/col3.h +++ b/common/math/col3.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/col4.h b/common/math/col4.h index 27849840ec..788508516b 100644 --- a/common/math/col4.h +++ b/common/math/col4.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/color.h b/common/math/color.h index eae7b72ecf..e62e4ad2a4 100644 --- a/common/math/color.h +++ b/common/math/color.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -152,21 +152,38 @@ namespace embree } __forceinline const Color rcp ( const Color& a ) { +#if defined(__aarch64__) + __m128 reciprocal = _mm_rcp_ps(a.m128); + reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal); + reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal); + return (const Color)reciprocal; +#else #if defined(__AVX512VL__) const Color r = _mm_rcp14_ps(a.m128); #else const Color r = _mm_rcp_ps(a.m128); #endif - return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a)); + return _mm_add_ps(r,_mm_mul_ps(r, _mm_sub_ps(_mm_set1_ps(1.0f), _mm_mul_ps(a, r)))); // computes r + r * (1 - a * r) + +#endif //defined(__aarch64__) } __forceinline const Color rsqrt( const Color& a ) { +#if defined(__aarch64__) + __m128 r = _mm_rsqrt_ps(a.m128); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r)); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r)); + return r; +#else + #if defined(__AVX512VL__) __m128 r = _mm_rsqrt14_ps(a.m128); #else __m128 r = _mm_rsqrt_ps(a.m128); #endif return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); + +#endif //defined(__aarch64__) } __forceinline const Color sqrt ( const Color& a ) { return _mm_sqrt_ps(a.m128); } diff --git a/common/math/constants.cpp b/common/math/constants.cpp index 26968297d9..f51c642bfc 100644 --- a/common/math/constants.cpp +++ b/common/math/constants.cpp @@ -1,27 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "constants.h" namespace embree { - TrueTy True; - FalseTy False; - ZeroTy zero; - OneTy one; - NegInfTy neg_inf; - PosInfTy inf; - PosInfTy pos_inf; - NaNTy nan; - UlpTy ulp; - PiTy pi; - OneOverPiTy one_over_pi; - TwoPiTy two_pi; - OneOverTwoPiTy one_over_two_pi; - FourPiTy four_pi; - OneOverFourPiTy one_over_four_pi; - StepTy step; - ReverseStepTy reverse_step; - EmptyTy empty; - UndefinedTy undefined; } diff --git a/common/math/constants.h b/common/math/constants.h index 77c2b7aec2..07a1a868ba 100644 --- a/common/math/constants.h +++ b/common/math/constants.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -24,13 +24,13 @@ namespace embree __forceinline operator bool( ) const { return true; } }; - extern MAYBE_UNUSED TrueTy True; + const constexpr TrueTy True = TrueTy(); struct FalseTy { __forceinline operator bool( ) const { return false; } }; - extern MAYBE_UNUSED FalseTy False; + const constexpr FalseTy False = FalseTy(); struct ZeroTy { @@ -48,7 +48,7 @@ namespace embree __forceinline operator unsigned char ( ) const { return 0; } }; - extern MAYBE_UNUSED ZeroTy zero; + const constexpr ZeroTy zero = ZeroTy(); struct OneTy { @@ -66,7 +66,7 @@ namespace embree __forceinline operator unsigned char ( ) const { return 1; } }; - extern MAYBE_UNUSED OneTy one; + const constexpr OneTy one = OneTy(); struct NegInfTy { @@ -85,7 +85,7 @@ namespace embree }; - extern MAYBE_UNUSED NegInfTy neg_inf; + const constexpr NegInfTy neg_inf = NegInfTy(); struct PosInfTy { @@ -103,8 +103,8 @@ namespace embree __forceinline operator unsigned char ( ) const { return std::numeric_limits::max(); } }; - extern MAYBE_UNUSED PosInfTy inf; - extern MAYBE_UNUSED PosInfTy pos_inf; + const constexpr PosInfTy inf = PosInfTy(); + const constexpr PosInfTy pos_inf = PosInfTy(); struct NaNTy { @@ -112,15 +112,15 @@ namespace embree __forceinline operator float ( ) const { return std::numeric_limits::quiet_NaN(); } }; - extern MAYBE_UNUSED NaNTy nan; + const constexpr NaNTy nan = NaNTy(); struct UlpTy { __forceinline operator double( ) const { return std::numeric_limits::epsilon(); } __forceinline operator float ( ) const { return std::numeric_limits::epsilon(); } }; - - extern MAYBE_UNUSED UlpTy ulp; + + const constexpr UlpTy ulp = UlpTy(); struct PiTy { @@ -128,7 +128,7 @@ namespace embree __forceinline operator float ( ) const { return float(M_PI); } }; - extern MAYBE_UNUSED PiTy pi; + const constexpr PiTy pi = PiTy(); struct OneOverPiTy { @@ -136,7 +136,7 @@ namespace embree __forceinline operator float ( ) const { return float(M_1_PI); } }; - extern MAYBE_UNUSED OneOverPiTy one_over_pi; + const constexpr OneOverPiTy one_over_pi = OneOverPiTy(); struct TwoPiTy { @@ -144,7 +144,7 @@ namespace embree __forceinline operator float ( ) const { return float(2.0*M_PI); } }; - extern MAYBE_UNUSED TwoPiTy two_pi; + const constexpr TwoPiTy two_pi = TwoPiTy(); struct OneOverTwoPiTy { @@ -152,7 +152,7 @@ namespace embree __forceinline operator float ( ) const { return float(0.5*M_1_PI); } }; - extern MAYBE_UNUSED OneOverTwoPiTy one_over_two_pi; + const constexpr OneOverTwoPiTy one_over_two_pi = OneOverTwoPiTy(); struct FourPiTy { @@ -160,7 +160,7 @@ namespace embree __forceinline operator float ( ) const { return float(4.0*M_PI); } }; - extern MAYBE_UNUSED FourPiTy four_pi; + const constexpr FourPiTy four_pi = FourPiTy(); struct OneOverFourPiTy { @@ -168,30 +168,42 @@ namespace embree __forceinline operator float ( ) const { return float(0.25*M_1_PI); } }; - extern MAYBE_UNUSED OneOverFourPiTy one_over_four_pi; + const constexpr OneOverFourPiTy one_over_four_pi = OneOverFourPiTy(); struct StepTy { + __forceinline operator double ( ) const { return 0; } + __forceinline operator float ( ) const { return 0; } + __forceinline operator long long( ) const { return 0; } + __forceinline operator unsigned long long( ) const { return 0; } + __forceinline operator long ( ) const { return 0; } + __forceinline operator unsigned long ( ) const { return 0; } + __forceinline operator int ( ) const { return 0; } + __forceinline operator unsigned int ( ) const { return 0; } + __forceinline operator short ( ) const { return 0; } + __forceinline operator unsigned short ( ) const { return 0; } + __forceinline operator char ( ) const { return 0; } + __forceinline operator unsigned char ( ) const { return 0; } }; - extern MAYBE_UNUSED StepTy step; + const constexpr StepTy step = StepTy(); struct ReverseStepTy { }; - extern MAYBE_UNUSED ReverseStepTy reverse_step; + const constexpr ReverseStepTy reverse_step = ReverseStepTy(); struct EmptyTy { }; - extern MAYBE_UNUSED EmptyTy empty; + const constexpr EmptyTy empty = EmptyTy(); struct FullTy { }; - extern MAYBE_UNUSED FullTy full; + const constexpr FullTy full = FullTy(); struct UndefinedTy { }; - extern MAYBE_UNUSED UndefinedTy undefined; + const constexpr UndefinedTy undefined = UndefinedTy(); } diff --git a/common/math/interval.h b/common/math/interval.h index f06478e881..310add2129 100644 --- a/common/math/interval.h +++ b/common/math/interval.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/lbbox.h b/common/math/lbbox.h index 194831184e..2b397a05c8 100644 --- a/common/math/lbbox.h +++ b/common/math/lbbox.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -241,6 +241,11 @@ namespace embree __forceinline bool isvalid( const LBBox& v ) { return isvalid(v.bounds0) && isvalid(v.bounds1); } + + template + __forceinline bool isvalid_non_empty( const LBBox& v ) { + return isvalid_non_empty(v.bounds0) && isvalid_non_empty(v.bounds1); + } template __forceinline T expectedArea(const T& a0, const T& a1, const T& b0, const T& b1) diff --git a/common/math/linearspace2.h b/common/math/linearspace2.h index b9a382962c..184ee695fb 100644 --- a/common/math/linearspace2.h +++ b/common/math/linearspace2.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/linearspace3.h b/common/math/linearspace3.h index 12b5bb776b..9eaa2cc2bb 100644 --- a/common/math/linearspace3.h +++ b/common/math/linearspace3.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/math.h b/common/math/math.h index 5af0691a28..e3b3165774 100644 --- a/common/math/math.h +++ b/common/math/math.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -7,13 +7,18 @@ #include "../sys/intrinsics.h" #include "constants.h" #include +#include +#if defined(__ARM_NEON) +#include "../simd/arm/emulation.h" +#else #include #include #include +#endif #if defined(__WIN32__) -#if (__MSV_VER <= 1700) +#if defined(_MSC_VER) && (_MSC_VER <= 1700) namespace std { __forceinline bool isinf ( const float x ) { return _finite(x) == 0; } @@ -49,6 +54,16 @@ namespace embree __forceinline float rcp ( const float x ) { +#if defined(__aarch64__) + // Move scalar to vector register and do rcp. + __m128 a; + a[0] = x; + float32x4_t reciprocal = vrecpeq_f32(a); + reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal); + reciprocal = vmulq_f32(vrecpsq_f32(a, reciprocal), reciprocal); + return reciprocal[0]; +#else + const __m128 a = _mm_set_ss(x); #if defined(__AVX512VL__) @@ -62,31 +77,74 @@ namespace embree #else return _mm_cvtss_f32(_mm_mul_ss(r,_mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a)))); #endif + +#endif //defined(__aarch64__) } __forceinline float signmsk ( const float x ) { +#if defined(__aarch64__) + // FP and Neon shares same vector register in arm64 + __m128 a; + __m128i b; + a[0] = x; + b[0] = 0x80000000; + a = _mm_and_ps(a, vreinterpretq_f32_s32(b)); + return a[0]; +#else return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000)))); +#endif } __forceinline float xorf( const float x, const float y ) { +#if defined(__aarch64__) + // FP and Neon shares same vector register in arm64 + __m128 a; + __m128 b; + a[0] = x; + b[0] = y; + a = _mm_xor_ps(a, b); + return a[0]; +#else return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y))); +#endif } __forceinline float andf( const float x, const unsigned y ) { +#if defined(__aarch64__) + // FP and Neon shares same vector register in arm64 + __m128 a; + __m128i b; + a[0] = x; + b[0] = y; + a = _mm_and_ps(a, vreinterpretq_f32_s32(b)); + return a[0]; +#else return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y)))); +#endif } __forceinline float rsqrt( const float x ) { +#if defined(__aarch64__) + // FP and Neon shares same vector register in arm64 + __m128 a; + a[0] = x; + __m128 value = _mm_rsqrt_ps(a); + value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(a, value), value)); + value = vmulq_f32(value, vrsqrtsq_f32(vmulq_f32(a, value), value)); + return value[0]; +#else + const __m128 a = _mm_set_ss(x); #if defined(__AVX512VL__) - const __m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a); + __m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a); #else - const __m128 r = _mm_rsqrt_ss(a); + __m128 r = _mm_rsqrt_ss(a); #endif const __m128 c = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r), _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r))); return _mm_cvtss_f32(c); +#endif } -#if defined(__WIN32__) && (__MSC_VER <= 1700) +#if defined(__WIN32__) && defined(_MSC_VER) && (_MSC_VER <= 1700) __forceinline float nextafter(float x, float y) { if ((x0)) return x*(1.1f+float(ulp)); else return x*(0.9f-float(ulp)); } __forceinline double nextafter(double x, double y) { return _nextafter(x, y); } __forceinline int roundf(float f) { return (int)(f + 0.5f); } @@ -140,7 +198,17 @@ namespace embree __forceinline double floor( const double x ) { return ::floor (x); } __forceinline double ceil ( const double x ) { return ::ceil (x); } -#if defined(__SSE4_1__) +#if defined(__aarch64__) + __forceinline float mini(float a, float b) { + // FP and Neon shares same vector register in arm64 + __m128 x; + __m128 y; + x[0] = a; + y[0] = b; + x = _mm_min_ps(x, y); + return x[0]; + } +#elif defined(__SSE4_1__) __forceinline float mini(float a, float b) { const __m128i ai = _mm_castps_si128(_mm_set_ss(a)); const __m128i bi = _mm_castps_si128(_mm_set_ss(b)); @@ -149,7 +217,17 @@ namespace embree } #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) + __forceinline float maxi(float a, float b) { + // FP and Neon shares same vector register in arm64 + __m128 x; + __m128 y; + x[0] = a; + y[0] = b; + x = _mm_max_ps(x, y); + return x[0]; + } +#elif defined(__SSE4_1__) __forceinline float maxi(float a, float b) { const __m128i ai = _mm_castps_si128(_mm_set_ss(a)); const __m128i bi = _mm_castps_si128(_mm_set_ss(b)); @@ -166,9 +244,12 @@ namespace embree __forceinline int64_t min(int64_t a, int64_t b) { return a __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); } template __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); } @@ -183,9 +264,12 @@ namespace embree __forceinline int64_t max(int64_t a, int64_t b) { return a __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); } template __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); } @@ -225,6 +309,15 @@ namespace embree __forceinline float msub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); } __forceinline float nmadd ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmadd_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); } __forceinline float nmsub ( const float a, const float b, const float c) { return _mm_cvtss_f32(_mm_fnmsub_ss(_mm_set_ss(a),_mm_set_ss(b),_mm_set_ss(c))); } + +#elif defined (__aarch64__) && defined(__clang__) +#pragma clang fp contract(fast) +__forceinline float madd ( const float a, const float b, const float c) { return a*b + c; } +__forceinline float msub ( const float a, const float b, const float c) { return a*b - c; } +__forceinline float nmadd ( const float a, const float b, const float c) { return c - a*b; } +__forceinline float nmsub ( const float a, const float b, const float c) { return -(c + a*b); } +#pragma clang fp contract(on) + #else __forceinline float madd ( const float a, const float b, const float c) { return a*b+c; } __forceinline float msub ( const float a, const float b, const float c) { return a*b-c; } @@ -273,6 +366,17 @@ namespace embree /*! exchange */ template __forceinline void xchg ( T& a, T& b ) { const T tmp = a; a = b; b = tmp; } + /* load/store */ + template struct mem; + + template<> struct mem { + static __forceinline float load (bool mask, const void* ptr) { return mask ? *(float*)ptr : 0.0f; } + static __forceinline float loadu(bool mask, const void* ptr) { return mask ? *(float*)ptr : 0.0f; } + + static __forceinline void store (bool mask, void* ptr, const float v) { if (mask) *(float*)ptr = v; } + static __forceinline void storeu(bool mask, void* ptr, const float v) { if (mask) *(float*)ptr = v; } + }; + /*! bit reverse operation */ template __forceinline T bitReverse(const T& vin) @@ -309,7 +413,7 @@ namespace embree return x | (y << 1) | (z << 2); } -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) template<> __forceinline unsigned int bitInterleave(const unsigned int &xi, const unsigned int& yi, const unsigned int& zi) diff --git a/common/math/obbox.h b/common/math/obbox.h index 032b56904e..2fe8bbf071 100644 --- a/common/math/obbox.h +++ b/common/math/obbox.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/quaternion.h b/common/math/quaternion.h index 20c69bc62f..78efccda72 100644 --- a/common/math/quaternion.h +++ b/common/math/quaternion.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -242,13 +242,17 @@ namespace embree T cosTheta = dot(q0, q1_); QuaternionT q1 = select(cosTheta < 0.f, -q1_, q1_); cosTheta = select(cosTheta < 0.f, -cosTheta, cosTheta); - if (unlikely(all(cosTheta > 0.9995f))) { - return normalize(lerp(q0, q1, t)); - } + + // spherical linear interpolation const T phi = t * fastapprox::acos(cosTheta); T sinPhi, cosPhi; fastapprox::sincos(phi, sinPhi, cosPhi); QuaternionT qperp = sinPhi * normalize(msub(cosTheta, q0, q1)); - return msub(cosPhi, q0, qperp); + QuaternionT qslerp = msub(cosPhi, q0, qperp); + + // regular linear interpolation as fallback + QuaternionT qlerp = normalize(lerp(q0, q1, t)); + + return select(cosTheta > 0.9995f, qlerp, qslerp); } } diff --git a/common/math/range.h b/common/math/range.h index 762d9cd9ea..909fadb995 100644 --- a/common/math/range.h +++ b/common/math/range.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/transcendental.h b/common/math/transcendental.h index 6855d82b53..daf9dd96d2 100644 --- a/common/math/transcendental.h +++ b/common/math/transcendental.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -27,7 +27,7 @@ __forceinline T sin(const T &v) // Reduced range version of x auto x = v - kReal * piOverTwoVec; auto kMod4 = k & 3; - auto sinUseCos = (kMod4 == 1 | kMod4 == 3); + auto sinUseCos = (kMod4 == 1) | (kMod4 == 3); auto flipSign = (kMod4 > 1); // These coefficients are from sollya with fpminimax(sin(x)/x, [|0, 2, @@ -76,8 +76,8 @@ __forceinline T cos(const T &v) auto x = v - kReal * piOverTwoVec; auto kMod4 = k & 3; - auto cosUseCos = (kMod4 == 0 | kMod4 == 2); - auto flipSign = (kMod4 == 1 | kMod4 == 2); + auto cosUseCos = (kMod4 == 0) | (kMod4 == 2); + auto flipSign = (kMod4 == 1) | (kMod4 == 2); const float sinC2 = -0.16666667163372039794921875; const float sinC4 = +8.333347737789154052734375e-3; @@ -418,7 +418,7 @@ __forceinline void __rangeReduceLog(const T &input, } template struct ExponentType { }; -template struct ExponentType> { typedef vint Ty; }; +template struct ExponentType> { typedef vint Ty; }; template <> struct ExponentType { typedef int Ty; }; template diff --git a/common/math/vec2.h b/common/math/vec2.h index 0ecf8c6384..f6d98ffa0d 100644 --- a/common/math/vec2.h +++ b/common/math/vec2.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -144,7 +144,7 @@ namespace embree } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// template __forceinline T dot ( const Vec2& a, const Vec2& b ) { return madd(a.x,b.x,a.y*b.y); } @@ -205,11 +205,11 @@ namespace embree #include "vec2fa.h" -#if defined __SSE__ +#if defined(__SSE__) || defined(__ARM_NEON) #include "../simd/sse.h" #endif -#if defined __AVX__ +#if defined(__AVX__) #include "../simd/avx.h" #endif @@ -221,7 +221,7 @@ namespace embree { template<> __forceinline Vec2::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) template<> __forceinline Vec2::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} #endif diff --git a/common/math/vec2fa.h b/common/math/vec2fa.h index 6b1b6f33f2..4f222894c2 100644 --- a/common/math/vec2fa.h +++ b/common/math/vec2fa.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -97,6 +97,12 @@ namespace embree __forceinline Vec2fa rcp ( const Vec2fa& a ) { +#if defined(__aarch64__) + __m128 reciprocal = _mm_rcp_ps(a.m128); + reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal); + reciprocal = vmulq_f32(vrecpsq_f32(a.m128, reciprocal), reciprocal); + return (const Vec2fa)reciprocal; +#else #if defined(__AVX512VL__) const Vec2fa r = _mm_rcp14_ps(a.m128); #else @@ -104,13 +110,15 @@ namespace embree #endif #if defined(__AVX2__) - const Vec2fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f))); + const Vec2fa h_n = _mm_fnmadd_ps(a, r, vfloat4(1.0)); // First, compute 1 - a * r (which will be very close to 0) + const Vec2fa res = _mm_fmadd_ps(r, h_n, r); // Then compute r + r * h_n #else - const Vec2fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a))); - //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a)); + const Vec2fa h_n = _mm_sub_ps(vfloat4(1.0f), _mm_mul_ps(a, r)); // First, compute 1 - a * r (which will be very close to 0) + const Vec2fa res = _mm_add_ps(r,_mm_mul_ps(r, h_n)); // Then compute r + r * h_n #endif return res; +#endif //defined(__aarch64__) } __forceinline Vec2fa sqrt ( const Vec2fa& a ) { return _mm_sqrt_ps(a.m128); } @@ -118,12 +126,21 @@ namespace embree __forceinline Vec2fa rsqrt( const Vec2fa& a ) { +#if defined(__aarch64__) + __m128 r = _mm_rsqrt_ps(a.m128); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r)); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r)); + return r; +#else + #if defined(__AVX512VL__) __m128 r = _mm_rsqrt14_ps(a.m128); #else __m128 r = _mm_rsqrt_ps(a.m128); #endif return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); + +#endif } __forceinline Vec2fa zero_fix(const Vec2fa& a) { @@ -156,7 +173,7 @@ namespace embree __forceinline Vec2fa min( const Vec2fa& a, const Vec2fa& b ) { return _mm_min_ps(a.m128,b.m128); } __forceinline Vec2fa max( const Vec2fa& a, const Vec2fa& b ) { return _mm_max_ps(a.m128,b.m128); } -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec2fa mini(const Vec2fa& a, const Vec2fa& b) { const vint4 ai = _mm_castps_si128(a); const vint4 bi = _mm_castps_si128(b); @@ -165,7 +182,7 @@ namespace embree } #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec2fa maxi(const Vec2fa& a, const Vec2fa& b) { const vint4 ai = _mm_castps_si128(a); const vint4 bi = _mm_castps_si128(b); @@ -227,7 +244,7 @@ namespace embree __forceinline bool operator !=( const Vec2fa& a, const Vec2fa& b ) { return (_mm_movemask_ps(_mm_cmpneq_ps(a.m128, b.m128)) & 3) != 0; } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// #if defined(__SSE4_1__) @@ -275,7 +292,11 @@ namespace embree /// Rounding Functions //////////////////////////////////////////////////////////////////////////////// -#if defined (__SSE4_1__) +#if defined(__aarch64__) + //__forceinline Vec2fa trunc(const Vec2fa& a) { return vrndq_f32(a); } + __forceinline Vec2fa floor(const Vec2fa& a) { return vrndmq_f32(a); } + __forceinline Vec2fa ceil (const Vec2fa& a) { return vrndpq_f32(a); } +#elif defined (__SSE4_1__) //__forceinline Vec2fa trunc( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); } __forceinline Vec2fa floor( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); } __forceinline Vec2fa ceil ( const Vec2fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); } diff --git a/common/math/vec3.h b/common/math/vec3.h index ab4753545b..254f6c4011 100644 --- a/common/math/vec3.h +++ b/common/math/vec3.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -197,7 +197,7 @@ namespace embree template __forceinline Vec3 ge_mask( const Vec3& a, const Vec3& b ) { return Vec3(a.x>=b.x,a.y>=b.y,a.z>=b.z); } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// template __forceinline T sqr ( const Vec3& a ) { return dot(a,a); } @@ -207,7 +207,6 @@ namespace embree template __forceinline Vec3 normalize( const Vec3& a ) { return a*rsqrt(sqr(a)); } template __forceinline T distance ( const Vec3& a, const Vec3& b ) { return length(a-b); } template __forceinline Vec3 cross ( const Vec3& a, const Vec3& b ) { return Vec3(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x)); } - template __forceinline Vec3 stable_triangle_normal( const Vec3& a, const Vec3& b, const Vec3& c ) { const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x; @@ -266,11 +265,11 @@ namespace embree /// SSE / AVX / MIC specializations //////////////////////////////////////////////////////////////////////////////// -#if defined __SSE__ +#if defined(__SSE__) || defined(__ARM_NEON) #include "../simd/sse.h" #endif -#if defined __AVX__ +#if defined(__AVX__) #include "../simd/avx.h" #endif @@ -291,18 +290,14 @@ namespace embree template<> __forceinline Vec3::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; } -#elif defined(__SSE__) +#elif defined(__SSE__) || defined(__ARM_NEON) template<> __forceinline Vec3::Vec3(const Vec3fa& a) { const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); } #endif -#if defined(__SSE__) - __forceinline Vec3 broadcast4f(const Vec3& a, const size_t k) { - return Vec3(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k])); - } - +#if defined(__SSE__) || defined(__ARM_NEON) template<> __forceinline Vec3 broadcast(const Vec3& a, const size_t k) { return Vec3(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k])); @@ -319,15 +314,6 @@ namespace embree __forceinline Vec3::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; } - __forceinline Vec3 broadcast4f(const Vec3& a, const size_t k) { - return Vec3(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k])); - } - __forceinline Vec3 broadcast8f(const Vec3& a, const size_t k) { - return Vec3(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k])); - } - __forceinline Vec3 broadcast8f(const Vec3& a, const size_t k) { - return Vec3(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k])); - } template<> __forceinline Vec3 broadcast(const Vec3& a, const size_t k) { diff --git a/common/math/vec3ba.h b/common/math/vec3ba.h index 90f31739c2..a021b522dc 100644 --- a/common/math/vec3ba.h +++ b/common/math/vec3ba.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/math/vec3fa.h b/common/math/vec3fa.h index 6576a15b4f..8564cf6d10 100644 --- a/common/math/vec3fa.h +++ b/common/math/vec3fa.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -55,7 +55,13 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// static __forceinline Vec3fa load( const void* const a ) { +#if defined(__aarch64__) + __m128 t = _mm_load_ps((float*)a); + t[3] = 0.0f; + return Vec3fa(t); +#else return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1)))); +#endif } static __forceinline Vec3fa loadu( const void* const a ) { @@ -89,12 +95,20 @@ namespace embree __forceinline Vec3fa operator +( const Vec3fa& a ) { return a; } __forceinline Vec3fa operator -( const Vec3fa& a ) { +#if defined(__aarch64__) + return vnegq_f32(a.m128); +#else const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000)); return _mm_xor_ps(a.m128, mask); +#endif } __forceinline Vec3fa abs ( const Vec3fa& a ) { +#if defined(__aarch64__) + return _mm_abs_ps(a.m128); +#else const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)); return _mm_and_ps(a.m128, mask); +#endif } __forceinline Vec3fa sign ( const Vec3fa& a ) { return blendv_ps(Vec3fa(one).m128, (-Vec3fa(one)).m128, _mm_cmplt_ps (a.m128,Vec3fa(zero).m128)); @@ -102,6 +116,10 @@ namespace embree __forceinline Vec3fa rcp ( const Vec3fa& a ) { +#if defined(__aarch64__) + return vdivq_f32(vdupq_n_f32(1.0f),a.m128); +#else + #if defined(__AVX512VL__) const Vec3fa r = _mm_rcp14_ps(a.m128); #else @@ -109,13 +127,15 @@ namespace embree #endif #if defined(__AVX2__) - const Vec3fa res = _mm_mul_ps(r.m128,_mm_fnmadd_ps(r.m128, a.m128, vfloat4(2.0f))); + const Vec3fa h_n = _mm_fnmadd_ps(a.m128, r.m128, vfloat4(1.0)); // First, compute 1 - a * r (which will be very close to 0) + const Vec3fa res = _mm_fmadd_ps(r.m128, h_n.m128, r.m128); // Then compute r + r * h_n #else - const Vec3fa res = _mm_mul_ps(r.m128,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r.m128, a.m128))); - //return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a)); + const Vec3fa h_n = _mm_sub_ps(vfloat4(1.0f), _mm_mul_ps(a.m128, r.m128)); // First, compute 1 - a * r (which will be very close to 0) + const Vec3fa res = _mm_add_ps(r.m128,_mm_mul_ps(r.m128, h_n.m128)); // Then compute r + r * h_n #endif return res; +#endif //defined(__aarch64__) } __forceinline Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); } @@ -123,12 +143,20 @@ namespace embree __forceinline Vec3fa rsqrt( const Vec3fa& a ) { +#if defined(__aarch64__) + __m128 r = _mm_rsqrt_ps(a.m128); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r)); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a.m128, r), r)); + return r; +#else + #if defined(__AVX512VL__) __m128 r = _mm_rsqrt14_ps(a.m128); #else __m128 r = _mm_rsqrt_ps(a.m128); #endif return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a.m128, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); +#endif } __forceinline Vec3fa zero_fix(const Vec3fa& a) { @@ -161,7 +189,7 @@ namespace embree __forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); } __forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); } -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) { const vint4 ai = _mm_castps_si128(a.m128); const vint4 bi = _mm_castps_si128(b.m128); @@ -170,7 +198,7 @@ namespace embree } #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) { const vint4 ai = _mm_castps_si128(a.m128); const vint4 bi = _mm_castps_si128(b.m128); @@ -187,16 +215,16 @@ namespace embree /// Ternary Operators //////////////////////////////////////////////////////////////////////////////// -#if defined(__AVX2__) +#if defined(__AVX2__) || defined(__ARM_NEON) __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmadd_ps(a.m128,b.m128,c.m128); } __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fmsub_ps(a.m128,b.m128,c.m128); } __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmadd_ps(a.m128,b.m128,c.m128); } __forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return _mm_fnmsub_ps(a.m128,b.m128,c.m128); } #else __forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b+c; } - __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; } __forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b+c;} __forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; } + __forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; } #endif __forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); } @@ -218,8 +246,26 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// /// Reductions //////////////////////////////////////////////////////////////////////////////// +#if defined(__aarch64__) + __forceinline float reduce_add(const Vec3fa& v) { + float32x4_t t = v.m128; + t[3] = 0.0f; + return vaddvq_f32(t); + } - __forceinline float reduce_add(const Vec3fa& v) { + __forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; } + __forceinline float reduce_min(const Vec3fa& v) { + float32x4_t t = v.m128; + t[3] = t[2]; + return vminvq_f32(t); + } + __forceinline float reduce_max(const Vec3fa& v) { + float32x4_t t = v.m128; + t[3] = t[2]; + return vmaxvq_f32(t); + } +#else + __forceinline float reduce_add(const Vec3fa& v) { const vfloat4 a(v.m128); const vfloat4 b = shuffle<1>(a); const vfloat4 c = shuffle<2>(a); @@ -229,6 +275,7 @@ namespace embree __forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; } __forceinline float reduce_min(const Vec3fa& v) { return min(v.x,v.y,v.z); } __forceinline float reduce_max(const Vec3fa& v) { return max(v.x,v.y,v.z); } +#endif //////////////////////////////////////////////////////////////////////////////// /// Comparison Operators @@ -241,8 +288,13 @@ namespace embree __forceinline Vec3ba neq_mask(const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpneq_ps(a.m128, b.m128); } __forceinline Vec3ba lt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmplt_ps (a.m128, b.m128); } __forceinline Vec3ba le_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmple_ps (a.m128, b.m128); } - __forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnle_ps(a.m128, b.m128); } - __forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); } + #if defined(__aarch64__) + __forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpgt_ps (a.m128, b.m128); } + __forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpge_ps (a.m128, b.m128); } +#else + __forceinline Vec3ba gt_mask(const Vec3fa& a, const Vec3fa& b) { return _mm_cmpnle_ps(a.m128, b.m128); } + __forceinline Vec3ba ge_mask(const Vec3fa& a, const Vec3fa& b) { return _mm_cmpnlt_ps(a.m128, b.m128); } +#endif __forceinline bool isvalid ( const Vec3fa& v ) { return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE))); @@ -261,7 +313,7 @@ namespace embree } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// #if defined(__SSE4_1__) @@ -335,7 +387,11 @@ namespace embree /// Rounding Functions //////////////////////////////////////////////////////////////////////////////// -#if defined (__SSE4_1__) +#if defined(__aarch64__) + __forceinline Vec3fa floor(const Vec3fa& a) { return vrndmq_f32(a.m128); } + __forceinline Vec3fa ceil (const Vec3fa& a) { return vrndpq_f32(a.m128); } + __forceinline Vec3fa trunc(const Vec3fa& a) { return vrndq_f32(a.m128); } +#elif defined (__SSE4_1__) __forceinline Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); } __forceinline Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); } __forceinline Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); } @@ -393,8 +449,10 @@ namespace embree __forceinline Vec3fx( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; } __forceinline Vec3fx( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; } - __forceinline Vec3fx( const Vec3fa& other, const float w1) { -#if defined (__SSE4_1__) + __forceinline Vec3fx( const Vec3fa& other, const float w1) { +#if defined (__aarch64__) + m128 = other.m128; m128[3] = w1; +#elif defined (__SSE4_1__) m128 = _mm_insert_ps(other.m128, _mm_set_ss(w1),3 << 4); #else const vint4 mask(-1,-1,-1,0); @@ -526,7 +584,7 @@ namespace embree __forceinline Vec3fx min( const Vec3fx& a, const Vec3fx& b ) { return _mm_min_ps(a.m128,b.m128); } __forceinline Vec3fx max( const Vec3fx& a, const Vec3fx& b ) { return _mm_max_ps(a.m128,b.m128); } -#if defined(__SSE4_1__) +#if defined(__SSE4_1__) || defined(__aarch64__) __forceinline Vec3fx mini(const Vec3fx& a, const Vec3fx& b) { const vint4 ai = _mm_castps_si128(a.m128); const vint4 bi = _mm_castps_si128(b.m128); @@ -535,7 +593,7 @@ namespace embree } #endif -#if defined(__SSE4_1__) +#if defined(__SSE4_1__) || defined(__aarch64__) __forceinline Vec3fx maxi(const Vec3fx& a, const Vec3fx& b) { const vint4 ai = _mm_castps_si128(a.m128); const vint4 bi = _mm_castps_si128(b.m128); @@ -626,7 +684,7 @@ namespace embree } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// #if defined(__SSE4_1__) @@ -700,7 +758,11 @@ namespace embree /// Rounding Functions //////////////////////////////////////////////////////////////////////////////// -#if defined (__SSE4_1__) +#if defined(__aarch64__) + __forceinline Vec3fx trunc(const Vec3fx& a) { return vrndq_f32(a.m128); } + __forceinline Vec3fx floor(const Vec3fx& a) { return vrndmq_f32(a.m128); } + __forceinline Vec3fx ceil (const Vec3fx& a) { return vrndpq_f32(a.m128); } +#elif defined (__SSE4_1__) __forceinline Vec3fx trunc( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEAREST_INT); } __forceinline Vec3fx floor( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_NEG_INF ); } __forceinline Vec3fx ceil ( const Vec3fx& a ) { return _mm_round_ps(a.m128, _MM_FROUND_TO_POS_INF ); } diff --git a/common/math/vec3ia.h b/common/math/vec3ia.h index e1c9972994..d4cc3125cd 100644 --- a/common/math/vec3ia.h +++ b/common/math/vec3ia.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -65,7 +65,9 @@ namespace embree __forceinline Vec3ia operator +( const Vec3ia& a ) { return a; } __forceinline Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); } -#if defined(__SSSE3__) +#if (defined(__aarch64__)) + __forceinline Vec3ia abs ( const Vec3ia& a ) { return vabsq_s32(a.m128); } +#elif defined(__SSSE3__) __forceinline Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); } #endif @@ -81,7 +83,7 @@ namespace embree __forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); } __forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; } -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); } __forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); } __forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; } @@ -116,7 +118,7 @@ namespace embree __forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia& b ) { return a = a - b; } __forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; } -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia& b ) { return a = a * b; } __forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; } #endif @@ -127,18 +129,38 @@ namespace embree __forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia& b ) { return a = a | b; } __forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; } +#if !defined(__ARM_NEON) __forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; } __forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; } +#endif //////////////////////////////////////////////////////////////////////////////// - /// Reductions + /// Select //////////////////////////////////////////////////////////////////////////////// + __forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) { +#if defined(__aarch64__) || defined(__SSE4_1__) + return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m)); +#else + return _mm_or_si128(_mm_and_si128(_mm_castps_si128(m), t), _mm_andnot_si128(_mm_castps_si128(m), f)); +#endif + } + + //////////////////////////////////////////////////////////////////////////////// + /// Reductions + //////////////////////////////////////////////////////////////////////////////// +#if defined(__aarch64__) + __forceinline int reduce_add(const Vec3ia& v) { return vaddvq_s32(select(Vec3ba(1,1,1),v,Vec3ia(0))); } + __forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; } + __forceinline int reduce_min(const Vec3ia& v) { return vminvq_s32(select(Vec3ba(1,1,1),v,Vec3ia(0x7FFFFFFF))); } + __forceinline int reduce_max(const Vec3ia& v) { return vmaxvq_s32(select(Vec3ba(1,1,1),v,Vec3ia(0x80000000))); } +#else __forceinline int reduce_add(const Vec3ia& v) { return v.x+v.y+v.z; } __forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; } __forceinline int reduce_min(const Vec3ia& v) { return min(v.x,v.y,v.z); } __forceinline int reduce_max(const Vec3ia& v) { return max(v.x,v.y,v.z); } - +#endif + //////////////////////////////////////////////////////////////////////////////// /// Comparison Operators //////////////////////////////////////////////////////////////////////////////// @@ -156,19 +178,7 @@ namespace embree __forceinline Vec3ba lt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); } __forceinline Vec3ba gt_mask( const Vec3ia& a, const Vec3ia& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); } - //////////////////////////////////////////////////////////////////////////////// - /// Select - //////////////////////////////////////////////////////////////////////////////// - - __forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) { -#if defined(__SSE4_1__) - return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m)); -#else - return _mm_or_si128(_mm_and_si128(_mm_castps_si128(m), t), _mm_andnot_si128(_mm_castps_si128(m), f)); -#endif - } - -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); } __forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); } #else diff --git a/common/math/vec4.h b/common/math/vec4.h index 3354b44317..10c53f47b4 100644 --- a/common/math/vec4.h +++ b/common/math/vec4.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -149,7 +149,7 @@ namespace embree } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// template __forceinline T dot ( const Vec4& a, const Vec4& b ) { return madd(a.x,b.x,madd(a.y,b.y,madd(a.z,b.z,a.w*b.w))); } @@ -205,7 +205,7 @@ namespace embree /// SSE / AVX / MIC specializations //////////////////////////////////////////////////////////////////////////////// -#if defined __SSE__ +#if defined(__SSE__) || defined(__ARM_NEON) #include "../simd/sse.h" #endif @@ -225,31 +225,16 @@ namespace embree template<> __forceinline Vec4::Vec4( const Vec3fx& a ) { x = a.x; y = a.y; z = a.z; w = a.w; } -#elif defined(__SSE__) +#elif defined(__SSE__) || defined(__ARM_NEON) template<> __forceinline Vec4::Vec4( const Vec3fx& a ) { const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v); } #endif -#if defined(__SSE__) - __forceinline Vec4 broadcast4f( const Vec4& a, const size_t k ) { - return Vec4(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k])); - } -#endif - #if defined(__AVX__) template<> __forceinline Vec4::Vec4( const Vec3fx& a ) { x = a.x; y = a.y; z = a.z; w = a.w; } - __forceinline Vec4 broadcast4f( const Vec4& a, const size_t k ) { - return Vec4(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k])); - } - __forceinline Vec4 broadcast8f( const Vec4& a, const size_t k ) { - return Vec4(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k])); - } - __forceinline Vec4 broadcast8f( const Vec4& a, const size_t k ) { - return Vec4(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k])); - } #endif #if defined(__AVX512F__) diff --git a/common/simd/CMakeLists.txt b/common/simd/CMakeLists.txt index d4bbe390f3..989a00d6ef 100644 --- a/common/simd/CMakeLists.txt +++ b/common/simd/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(simd STATIC sse.cpp) @@ -6,6 +6,6 @@ SET_PROPERTY(TARGET simd PROPERTY FOLDER common) SET_PROPERTY(TARGET simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS simd EXPORT simd-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT simd-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT simd-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git a/common/simd/arm/avx2neon.h b/common/simd/arm/avx2neon.h new file mode 100644 index 0000000000..dd321d3d64 --- /dev/null +++ b/common/simd/arm/avx2neon.h @@ -0,0 +1,1196 @@ +#pragma once + +#if !defined(__aarch64__) +#error "avx2neon is only supported for AARCH64" +#endif + +#include "sse2neon.h" + +#define AVX2NEON_ABI static inline __attribute__((always_inline)) + + +struct __m256 { + __m128 lo,hi; + __m256() {} +}; + + + + +struct __m256i { + __m128i lo,hi; + explicit __m256i(const __m256 a) : lo(__m128i(a.lo)),hi(__m128i(a.hi)) {} + operator __m256() const {__m256 res; res.lo = __m128(lo);res.hi = __m128(hi); return res;} + __m256i() {} +}; + + + + +struct __m256d { + float64x2_t lo,hi; + __m256d() {} + __m256d(const __m256& a) : lo(float64x2_t(a.lo)),hi(float64x2_t(a.hi)) {} + __m256d(const __m256i& a) : lo(float64x2_t(a.lo)),hi(float64x2_t(a.hi)) {} +}; + +#define UNARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a) {type res;res.lo=basic_func(a.lo);res.hi=basic_func(a.hi);return res;} + + +#define BINARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a,const type& b) {type res;res.lo=basic_func(a.lo,b.lo);res.hi=basic_func(a.hi,b.hi);return res;} +#define BINARY_AVX_OP_CAST(type,func,basic_func,bdst,bsrc) AVX2NEON_ABI type func(const type& a,const type& b) {type res;res.lo=bdst(basic_func(bsrc(a.lo),bsrc(b.lo)));res.hi=bdst(basic_func(bsrc(a.hi),bsrc(b.hi)));return res;} + +#define TERNARY_AVX_OP(type,func,basic_func) AVX2NEON_ABI type func(const type& a,const type& b,const type& c) {type res;res.lo=basic_func(a.lo,b.lo,c.lo);res.hi=basic_func(a.hi,b.hi,c.hi);return res;} + + +#define CAST_SIMD_TYPE(to,name,from,basic_dst) AVX2NEON_ABI to name(const from& a) { to res; res.lo = basic_dst(a.lo); res.hi=basic_dst(a.hi); return res;} + + + +#define _mm_stream_load_si128 _mm_load_si128 +#define _mm256_stream_load_si256 _mm256_load_si256 + + +AVX2NEON_ABI +__m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8) +{ + __m128 af = _mm_castsi128_ps(a); + __m128 bf = _mm_castsi128_ps(b); + __m128 blendf = _mm_blend_ps(af, bf, imm8); + return _mm_castps_si128(blendf); +} + +AVX2NEON_ABI +int _mm_movemask_popcnt(__m128 a) +{ + return __builtin_popcount(_mm_movemask_ps(a)); +} + +AVX2NEON_ABI +__m128 _mm_maskload_ps (float const * mem_addr, __m128i mask) +{ + float32x4_t res; + uint32x4_t mask_u32 = vreinterpretq_u32_m128i(mask); + for (int i=0;i<4;i++) { + if (mask_u32[i] & 0x80000000) res[i] = mem_addr[i]; else res[i] = 0; + } + return vreinterpretq_m128_f32(res); +} + +AVX2NEON_ABI +void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a) +{ + float32x4_t a_f32 = vreinterpretq_f32_m128(a); + uint32x4_t mask_u32 = vreinterpretq_u32_m128i(mask); + for (int i=0;i<4;i++) { + if (mask_u32[i] & 0x80000000) mem_addr[i] = a_f32[i]; + } +} + +AVX2NEON_ABI +void _mm_maskstore_epi32 (int * mem_addr, __m128i mask, __m128i a) +{ + uint32x4_t mask_u32 = vreinterpretq_u32_m128i(mask); + int32x4_t a_s32 = vreinterpretq_s32_m128i(a); + for (int i=0;i<4;i++) { + if (mask_u32[i] & 0x80000000) mem_addr[i] = a_s32[i]; + } +} + + +#define _mm_fmadd_ss _mm_fmadd_ps +#define _mm_fmsub_ss _mm_fmsub_ps +#define _mm_fnmsub_ss _mm_fnmsub_ps +#define _mm_fnmadd_ss _mm_fnmadd_ps + +template +AVX2NEON_ABI float32x4_t dpps_neon(const float32x4_t& a,const float32x4_t& b) +{ + float v; + v = 0; + v += (code & 0x10) ? a[0]*b[0] : 0; + v += (code & 0x20) ? a[1]*b[1] : 0; + v += (code & 0x40) ? a[2]*b[2] : 0; + v += (code & 0x80) ? a[3]*b[3] : 0; + float32x4_t res; + res[0] = (code & 0x1) ? v : 0; + res[1] = (code & 0x2) ? v : 0; + res[2] = (code & 0x4) ? v : 0; + res[3] = (code & 0x8) ? v : 0; + return res; +} + +template<> +inline float32x4_t dpps_neon<0x7f>(const float32x4_t& a,const float32x4_t& b) +{ + float v; + float32x4_t m = _mm_mul_ps(a,b); + m[3] = 0; + v = vaddvq_f32(m); + return _mm_set1_ps(v); +} + +template<> +inline float32x4_t dpps_neon<0xff>(const float32x4_t& a,const float32x4_t& b) +{ + float v; + float32x4_t m = _mm_mul_ps(a,b); + v = vaddvq_f32(m); + return _mm_set1_ps(v); +} + +#define _mm_dp_ps(a,b,c) dpps_neon((a),(b)) + + +AVX2NEON_ABI +__m128 _mm_permutevar_ps (__m128 a, __m128i b) +{ + uint32x4_t b_u32 = vreinterpretq_u32_m128i(b); + float32x4_t x; + for (int i=0;i<4;i++) + { + x[i] = a[b_u32[i]]; + } + return vreinterpretq_m128_f32(x); +} + +AVX2NEON_ABI +__m256i _mm256_setzero_si256() +{ + __m256i res; + res.lo = res.hi = vdupq_n_s32(0); + return res; +} + +AVX2NEON_ABI +__m256 _mm256_setzero_ps() +{ + __m256 res; + res.lo = res.hi = vdupq_n_f32(0.0f); + return res; +} + +AVX2NEON_ABI +__m256i _mm256_undefined_si256() +{ + return _mm256_setzero_si256(); +} + +AVX2NEON_ABI +__m256 _mm256_undefined_ps() +{ + return _mm256_setzero_ps(); +} + +CAST_SIMD_TYPE(__m256d, _mm256_castps_pd, __m256, float64x2_t) +CAST_SIMD_TYPE(__m256i, _mm256_castps_si256, __m256, __m128i) +CAST_SIMD_TYPE(__m256, _mm256_castsi256_ps, __m256i, __m128) +CAST_SIMD_TYPE(__m256, _mm256_castpd_ps , __m256d, __m128) +CAST_SIMD_TYPE(__m256d, _mm256_castsi256_pd, __m256i, float64x2_t) +CAST_SIMD_TYPE(__m256i, _mm256_castpd_si256, __m256d, __m128i) + + + + +AVX2NEON_ABI +__m128 _mm256_castps256_ps128 (__m256 a) +{ + return a.lo; +} + +AVX2NEON_ABI +__m256i _mm256_castsi128_si256 (__m128i a) +{ + __m256i res; + res.lo = a ; + res.hi = vdupq_n_s32(0); + return res; +} + +AVX2NEON_ABI +__m128i _mm256_castsi256_si128 (__m256i a) +{ + return a.lo; +} + +AVX2NEON_ABI +__m256 _mm256_castps128_ps256 (__m128 a) +{ + __m256 res; + res.lo = a; + res.hi = vdupq_n_f32(0); + return res; +} + + +AVX2NEON_ABI +__m256 _mm256_broadcast_ss (float const * mem_addr) +{ + __m256 res; + res.lo = res.hi = vdupq_n_f32(*mem_addr); + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0) +{ + __m256i res; + res.lo = _mm_set_epi32(e3,e2,e1,e0); + res.hi = _mm_set_epi32(e7,e6,e5,e4); + return res; + +} + +AVX2NEON_ABI +__m256i _mm256_set1_epi32 (int a) +{ + __m256i res; + res.lo = res.hi = vdupq_n_s32(a); + return res; +} +AVX2NEON_ABI +__m256i _mm256_set1_epi8 (int a) +{ + __m256i res; + res.lo = res.hi = vdupq_n_s8(a); + return res; +} +AVX2NEON_ABI +__m256i _mm256_set1_epi16 (int a) +{ + __m256i res; + res.lo = res.hi = vdupq_n_s16(a); + return res; +} + + + + +AVX2NEON_ABI +int _mm256_movemask_ps(const __m256& v) +{ + return (_mm_movemask_ps(v.hi) << 4) | _mm_movemask_ps(v.lo); +} + +template +AVX2NEON_ABI +__m256 __mm256_permute_ps (const __m256& a) +{ + __m256 res; + res.lo = _mm_shuffle_ps(a.lo,a.lo,imm8); + res.hi = _mm_shuffle_ps(a.hi,a.hi,imm8); + return res; + +} + +#define _mm256_permute_ps(a,c) __mm256_permute_ps(a) + + +template +AVX2NEON_ABI +__m256 __mm256_shuffle_ps (const __m256 a,const __m256& b) +{ + __m256 res; + res.lo = _mm_shuffle_ps(a.lo,b.lo,imm8); + res.hi = _mm_shuffle_ps(a.hi,b.hi,imm8); + return res; + +} + +template +AVX2NEON_ABI +__m256i __mm256_shuffle_epi32 (const __m256i a) +{ + __m256i res; + res.lo = _mm_shuffle_epi32(a.lo,imm8); + res.hi = _mm_shuffle_epi32(a.hi,imm8); + return res; + +} + +template +AVX2NEON_ABI +__m256i __mm256_srli_si256 (__m256i a) +{ + __m256i res; + res.lo = _mm_srli_si128(a.lo,imm8); + res.hi = _mm_srli_si128(a.hi,imm8); + return res; +} + +template +AVX2NEON_ABI +__m256i __mm256_slli_si256 (__m256i a) +{ + __m256i res; + res.lo = _mm_slli_si128(a.lo,imm8); + res.hi = _mm_slli_si128(a.hi,imm8); + return res; +} + + +#define _mm256_srli_si256(a,b) __mm256_srli_si256(a) +#define _mm256_slli_si256(a,b) __mm256_slli_si256(a) + + + +#define _mm256_shuffle_ps(a,b,c) __mm256_shuffle_ps(a,b) +#define _mm256_shuffle_epi32(a,c) __mm256_shuffle_epi32(a) + + +AVX2NEON_ABI +__m256i _mm256_set1_epi64x (long long a) +{ + __m256i res; + int64x2_t t = vdupq_n_s64(a); + res.lo = res.hi = __m128i(t); + return res; +} + + +AVX2NEON_ABI +__m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8) +{ + __m256 res; + __m128 tmp; + switch (imm8 & 0x7) + { + case 0: tmp = a.lo; break; + case 1: tmp = a.hi; break; + case 2: tmp = b.lo; break; + case 3: tmp = b.hi; break; + } + if (imm8 & 0x8) + tmp = _mm_setzero_ps(); + + + + res.lo = tmp; + imm8 >>= 4; + + switch (imm8 & 0x7) + { + case 0: tmp = a.lo; break; + case 1: tmp = a.hi; break; + case 2: tmp = b.lo; break; + case 3: tmp = b.hi; break; + } + if (imm8 & 0x8) + tmp = _mm_setzero_ps(); + + res.hi = tmp; + + return res; +} + +AVX2NEON_ABI +__m256 _mm256_moveldup_ps (__m256 a) +{ + __m256 res; + res.lo = _mm_moveldup_ps(a.lo); + res.hi = _mm_moveldup_ps(a.hi); + return res; +} + +AVX2NEON_ABI +__m256 _mm256_movehdup_ps (__m256 a) +{ + __m256 res; + res.lo = _mm_movehdup_ps(a.lo); + res.hi = _mm_movehdup_ps(a.hi); + return res; +} + +AVX2NEON_ABI +__m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8) +{ + __m256 res = a; + if (imm8 & 1) res.hi = b; + else res.lo = b; + return res; +} + + +AVX2NEON_ABI +__m128 _mm256_extractf128_ps (__m256 a, const int imm8) +{ + if (imm8 & 1) return a.hi; + return a.lo; +} + + +AVX2NEON_ABI +__m256d _mm256_movedup_pd (__m256d a) +{ + __m256d res; + res.lo = _mm_movedup_pd(a.lo); + res.hi = _mm_movedup_pd(a.hi); + return res; +} + +AVX2NEON_ABI +__m256i _mm256_abs_epi32(__m256i a) +{ + __m256i res; + res.lo = vabsq_s32(a.lo); + res.hi = vabsq_s32(a.hi); + return res; +} + +UNARY_AVX_OP(__m256,_mm256_sqrt_ps,_mm_sqrt_ps) +UNARY_AVX_OP(__m256,_mm256_rsqrt_ps,_mm_rsqrt_ps) +UNARY_AVX_OP(__m256,_mm256_rcp_ps,_mm_rcp_ps) +UNARY_AVX_OP(__m256,_mm256_floor_ps,vrndmq_f32) +UNARY_AVX_OP(__m256,_mm256_ceil_ps,vrndpq_f32) +UNARY_AVX_OP(__m256i,_mm256_abs_epi16,_mm_abs_epi16) + + +BINARY_AVX_OP(__m256i,_mm256_add_epi8,_mm_add_epi8) +BINARY_AVX_OP(__m256i,_mm256_adds_epi8,_mm_adds_epi8) + +BINARY_AVX_OP(__m256i,_mm256_hadd_epi32,_mm_hadd_epi32) +BINARY_AVX_OP(__m256i,_mm256_add_epi32,_mm_add_epi32) +BINARY_AVX_OP(__m256i,_mm256_sub_epi32,_mm_sub_epi32) +BINARY_AVX_OP(__m256i,_mm256_mullo_epi32,_mm_mullo_epi32) + +BINARY_AVX_OP(__m256i,_mm256_min_epi32,_mm_min_epi32) +BINARY_AVX_OP(__m256i,_mm256_max_epi32,_mm_max_epi32) +BINARY_AVX_OP(__m256i,_mm256_min_epi16,_mm_min_epi16) +BINARY_AVX_OP(__m256i,_mm256_max_epi16,_mm_max_epi16) +BINARY_AVX_OP(__m256i,_mm256_min_epi8,_mm_min_epi8) +BINARY_AVX_OP(__m256i,_mm256_max_epi8,_mm_max_epi8) +BINARY_AVX_OP(__m256i,_mm256_min_epu16,_mm_min_epu16) +BINARY_AVX_OP(__m256i,_mm256_max_epu16,_mm_max_epu16) +BINARY_AVX_OP(__m256i,_mm256_min_epu8,_mm_min_epu8) +BINARY_AVX_OP(__m256i,_mm256_max_epu8,_mm_max_epu8) +BINARY_AVX_OP(__m256i,_mm256_sign_epi16,_mm_sign_epi16) + + +BINARY_AVX_OP_CAST(__m256i,_mm256_min_epu32,vminq_u32,__m128i,uint32x4_t) +BINARY_AVX_OP_CAST(__m256i,_mm256_max_epu32,vmaxq_u32,__m128i,uint32x4_t) + +BINARY_AVX_OP(__m256,_mm256_min_ps,_mm_min_ps) +BINARY_AVX_OP(__m256,_mm256_max_ps,_mm_max_ps) + +BINARY_AVX_OP(__m256,_mm256_add_ps,_mm_add_ps) +BINARY_AVX_OP(__m256,_mm256_mul_ps,_mm_mul_ps) +BINARY_AVX_OP(__m256,_mm256_sub_ps,_mm_sub_ps) +BINARY_AVX_OP(__m256,_mm256_div_ps,_mm_div_ps) + +BINARY_AVX_OP(__m256,_mm256_and_ps,_mm_and_ps) +BINARY_AVX_OP(__m256,_mm256_andnot_ps,_mm_andnot_ps) +BINARY_AVX_OP(__m256,_mm256_or_ps,_mm_or_ps) +BINARY_AVX_OP(__m256,_mm256_xor_ps,_mm_xor_ps) + +BINARY_AVX_OP_CAST(__m256d,_mm256_and_pd,vandq_s64,float64x2_t,int64x2_t) +BINARY_AVX_OP_CAST(__m256d,_mm256_or_pd,vorrq_s64,float64x2_t,int64x2_t) +BINARY_AVX_OP_CAST(__m256d,_mm256_xor_pd,veorq_s64,float64x2_t,int64x2_t) + + + +BINARY_AVX_OP(__m256i,_mm256_and_si256,_mm_and_si128) +BINARY_AVX_OP(__m256i,_mm256_andnot_si256,_mm_andnot_si128) +BINARY_AVX_OP(__m256i,_mm256_or_si256,_mm_or_si128) +BINARY_AVX_OP(__m256i,_mm256_xor_si256,_mm_xor_si128) + + +BINARY_AVX_OP(__m256,_mm256_unpackhi_ps,_mm_unpackhi_ps) +BINARY_AVX_OP(__m256,_mm256_unpacklo_ps,_mm_unpacklo_ps) +TERNARY_AVX_OP(__m256,_mm256_blendv_ps,_mm_blendv_ps) +TERNARY_AVX_OP(__m256i,_mm256_blendv_epi8,_mm_blendv_epi8) + + +TERNARY_AVX_OP(__m256,_mm256_fmadd_ps,_mm_fmadd_ps) +TERNARY_AVX_OP(__m256,_mm256_fnmadd_ps,_mm_fnmadd_ps) +TERNARY_AVX_OP(__m256,_mm256_fmsub_ps,_mm_fmsub_ps) +TERNARY_AVX_OP(__m256,_mm256_fnmsub_ps,_mm_fnmsub_ps) + + + +BINARY_AVX_OP(__m256i,_mm256_packs_epi32,_mm_packs_epi32) +BINARY_AVX_OP(__m256i,_mm256_packs_epi16,_mm_packs_epi16) +BINARY_AVX_OP(__m256i,_mm256_packus_epi32,_mm_packus_epi32) +BINARY_AVX_OP(__m256i,_mm256_packus_epi16,_mm_packus_epi16) + + +BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi64,_mm_unpackhi_epi64) +BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi32,_mm_unpackhi_epi32) +BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi16,_mm_unpackhi_epi16) +BINARY_AVX_OP(__m256i,_mm256_unpackhi_epi8,_mm_unpackhi_epi8) + +BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi64,_mm_unpacklo_epi64) +BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi32,_mm_unpacklo_epi32) +BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi16,_mm_unpacklo_epi16) +BINARY_AVX_OP(__m256i,_mm256_unpacklo_epi8,_mm_unpacklo_epi8) + +BINARY_AVX_OP(__m256i,_mm256_mulhrs_epi16,_mm_mulhrs_epi16) +BINARY_AVX_OP(__m256i,_mm256_mulhi_epu16,_mm_mulhi_epu16) +BINARY_AVX_OP(__m256i,_mm256_mulhi_epi16,_mm_mulhi_epi16) +//BINARY_AVX_OP(__m256i,_mm256_mullo_epu16,_mm_mullo_epu16) +BINARY_AVX_OP(__m256i,_mm256_mullo_epi16,_mm_mullo_epi16) + +BINARY_AVX_OP(__m256i,_mm256_subs_epu16,_mm_subs_epu16) +BINARY_AVX_OP(__m256i,_mm256_adds_epu16,_mm_adds_epu16) +BINARY_AVX_OP(__m256i,_mm256_subs_epi16,_mm_subs_epi16) +BINARY_AVX_OP(__m256i,_mm256_adds_epi16,_mm_adds_epi16) +BINARY_AVX_OP(__m256i,_mm256_sub_epi16,_mm_sub_epi16) +BINARY_AVX_OP(__m256i,_mm256_add_epi16,_mm_add_epi16) +BINARY_AVX_OP(__m256i,_mm256_sub_epi8,_mm_sub_epi8) + + +BINARY_AVX_OP(__m256i,_mm256_hadd_epi16,_mm_hadd_epi16) +BINARY_AVX_OP(__m256i,_mm256_hadds_epi16,_mm_hadds_epi16) + + + + +BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi32,_mm_cmpeq_epi32) +BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi32,_mm_cmpgt_epi32) + +BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi8,_mm_cmpeq_epi8) +BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi8,_mm_cmpgt_epi8) + +BINARY_AVX_OP(__m256i,_mm256_cmpeq_epi16,_mm_cmpeq_epi16) +BINARY_AVX_OP(__m256i,_mm256_cmpgt_epi16,_mm_cmpgt_epi16) + + +BINARY_AVX_OP(__m256i,_mm256_shuffle_epi8,_mm_shuffle_epi8) + + +BINARY_AVX_OP(__m256,_mm256_cmpeq_ps,_mm_cmpeq_ps) +BINARY_AVX_OP(__m256,_mm256_cmpneq_ps,_mm_cmpneq_ps) +BINARY_AVX_OP(__m256,_mm256_cmpnlt_ps,_mm_cmpnlt_ps) +BINARY_AVX_OP(__m256,_mm256_cmpngt_ps,_mm_cmpngt_ps) +BINARY_AVX_OP(__m256,_mm256_cmpge_ps,_mm_cmpge_ps) +BINARY_AVX_OP(__m256,_mm256_cmpnge_ps,_mm_cmpnge_ps) +BINARY_AVX_OP(__m256,_mm256_cmplt_ps,_mm_cmplt_ps) +BINARY_AVX_OP(__m256,_mm256_cmple_ps,_mm_cmple_ps) +BINARY_AVX_OP(__m256,_mm256_cmpgt_ps,_mm_cmpgt_ps) +BINARY_AVX_OP(__m256,_mm256_cmpnle_ps,_mm_cmpnle_ps) + + +AVX2NEON_ABI +__m256i _mm256_cvtps_epi32 (__m256 a) +{ + __m256i res; + res.lo = _mm_cvtps_epi32(a.lo); + res.hi = _mm_cvtps_epi32(a.hi); + return res; + +} + +AVX2NEON_ABI +__m256i _mm256_cvttps_epi32 (__m256 a) +{ + __m256i res; + res.lo = _mm_cvttps_epi32(a.lo); + res.hi = _mm_cvttps_epi32(a.hi); + return res; + +} + +AVX2NEON_ABI +__m256 _mm256_loadu_ps (float const * mem_addr) +{ + __m256 res; + res.lo = *(__m128 *)(mem_addr + 0); + res.hi = *(__m128 *)(mem_addr + 4); + return res; +} +#define _mm256_load_ps _mm256_loadu_ps + + +AVX2NEON_ABI +int _mm256_testz_ps (const __m256& a, const __m256& b) +{ + __m256 t = a; + if (&a != &b) + t = _mm256_and_ps(a,b); + + int32x4_t l = vshrq_n_s32(vreinterpretq_s32_m128(t.lo),31); + int32x4_t h = vshrq_n_s32(vreinterpretq_s32_m128(t.hi),31); + return vaddvq_s32(vaddq_s32(l,h)) == 0; +} + + +AVX2NEON_ABI +__m256i _mm256_set_epi64x (int64_t e3, int64_t e2, int64_t e1, int64_t e0) +{ + __m256i res; + int64x2_t t0 = {e0,e1}; + int64x2_t t1 = {e2,e3}; + res.lo = __m128i(t0); + res.hi = __m128i(t1); + return res; +} +AVX2NEON_ABI +__m256i _mm256_setr_epi64x (int64_t e0, int64_t e1, int64_t e2, int64_t e3) +{ + __m256i res; + int64x2_t t0 = {e0,e1}; + int64x2_t t1 = {e2,e3}; + res.lo = __m128i(t0); + res.hi = __m128i(t1); + return res; +} + + + +AVX2NEON_ABI +__m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0) +{ + int8x16_t lo = {e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15}; + int8x16_t hi = {e16,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31}; + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + +AVX2NEON_ABI +__m256i _mm256_setr_epi8 (char e0, char e1, char e2, char e3, char e4, char e5, char e6, char e7, char e8, char e9, char e10, char e11, char e12, char e13, char e14, char e15, char e16, char e17, char e18, char e19, char e20, char e21, char e22, char e23, char e24, char e25, char e26, char e27, char e28, char e29, char e30, char e31) +{ + int8x16_t lo = {e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15}; + int8x16_t hi = {e16,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31}; + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) +{ + int16x8_t lo = {e0,e1,e2,e3,e4,e5,e6,e7}; + int16x8_t hi = {e8,e9,e10,e11,e12,e13,e14,e15}; + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + +AVX2NEON_ABI +__m256i _mm256_setr_epi16 (short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7, short e8, short e9, short e10, short e11, short e12, short e13, short e14, short e15) +{ + int16x8_t lo = {e0,e1,e2,e3,e4,e5,e6,e7}; + int16x8_t hi = {e8,e9,e10,e11,e12,e13,e14,e15}; + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + + + +AVX2NEON_ABI +int _mm256_movemask_epi8(const __m256i& a) +{ + return (_mm_movemask_epi8(a.hi) << 16) | _mm_movemask_epi8(a.lo); +} + + +AVX2NEON_ABI +int _mm256_testz_si256(const __m256i& a,const __m256i& b) +{ + uint32x4_t lo = vandq_u32(a.lo,b.lo); + uint32x4_t hi = vandq_u32(a.hi,b.hi); + + return (vaddvq_u32(lo) + vaddvq_u32(hi)) == 0; +} + +AVX2NEON_ABI +__m256d _mm256_setzero_pd () +{ + __m256d res; + res.lo = res.hi = vdupq_n_f64(0); + return res; +} + +AVX2NEON_ABI +int _mm256_movemask_pd (__m256d a) +{ + return (_mm_movemask_pd(a.hi) << 2) | _mm_movemask_pd(a.lo); +} + +AVX2NEON_ABI +__m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b) +{ + __m256i res; + res.lo = _mm_cmpeq_epi64(a.lo, b.lo); + res.hi = _mm_cmpeq_epi64(a.hi, b.hi); + return res; +} + +AVX2NEON_ABI +__m256d _mm256_cmpeq_pd (__m256d a, __m256d b) +{ + __m256d res; + res.lo = _mm_cmpeq_pd(a.lo, b.lo); + res.hi = _mm_cmpeq_pd(a.hi, b.hi); + return res; +} + + +AVX2NEON_ABI +int _mm256_testz_pd (const __m256d& a, const __m256d& b) +{ + __m256d t = a; + + if (&a != &b) + t = _mm256_and_pd(a,b); + + return _mm256_movemask_pd(t) == 0; +} + +AVX2NEON_ABI +__m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask) +{ + __m256d res; + res.lo = _mm_blendv_pd(a.lo, b.lo, mask.lo); + res.hi = _mm_blendv_pd(a.hi, b.hi, mask.hi); + return res; +} + +template +AVX2NEON_ABI +__m256 __mm256_dp_ps (__m256 a, __m256 b) +{ + __m256 res; + res.lo = _mm_dp_ps(a.lo, b.lo, imm8); + res.hi = _mm_dp_ps(a.hi, b.hi, imm8); + return res; +} + +#define _mm256_dp_ps(a,b,c) __mm256_dp_ps(a,b) + +AVX2NEON_ABI +double _mm256_permute4x64_pd_select(__m256d a, const int imm8) +{ + switch (imm8 & 3) { + case 0: + return ((float64x2_t)a.lo)[0]; + case 1: + return ((float64x2_t)a.lo)[1]; + case 2: + return ((float64x2_t)a.hi)[0]; + case 3: + return ((float64x2_t)a.hi)[1]; + } + __builtin_unreachable(); + return 0; +} + +AVX2NEON_ABI +__m256d _mm256_permute4x64_pd (__m256d a, const int imm8) +{ + float64x2_t lo,hi; + lo[0] = _mm256_permute4x64_pd_select(a,imm8 >> 0); + lo[1] = _mm256_permute4x64_pd_select(a,imm8 >> 2); + hi[0] = _mm256_permute4x64_pd_select(a,imm8 >> 4); + hi[1] = _mm256_permute4x64_pd_select(a,imm8 >> 6); + + __m256d res; + res.lo = lo; res.hi = hi; + return res; +} + +AVX2NEON_ABI +__m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8) +{ + return __m256i(_mm256_insertf128_ps((__m256)a,(__m128)b,imm8)); +} + + +AVX2NEON_ABI +__m256i _mm256_loadu_si256 (__m256i const * mem_addr) +{ + __m256i res; + res.lo = *(__m128i *)((int32_t *)mem_addr + 0); + res.hi = *(__m128i *)((int32_t *)mem_addr + 4); + return res; +} + +#define _mm256_load_si256 _mm256_loadu_si256 + +AVX2NEON_ABI +void _mm256_storeu_ps (float * mem_addr, __m256 a) +{ + *(__m128 *)(mem_addr + 0) = a.lo; + *(__m128 *)(mem_addr + 4) = a.hi; +} + +#define _mm256_store_ps _mm256_storeu_ps +#define _mm256_stream_ps _mm256_storeu_ps + + +AVX2NEON_ABI +void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a) +{ + *(__m128i *)((int32_t *)mem_addr + 0) = a.lo; + *(__m128i *)((int32_t *)mem_addr + 4) = a.hi; +} + +#define _mm256_store_si256 _mm256_storeu_si256 + + + +AVX2NEON_ABI +__m256i _mm256_permute4x64_epi64 (const __m256i a, const int imm8) +{ + uint8x16x2_t tbl = {a.lo, a.hi}; + + uint8_t sz = sizeof(uint64_t); + uint8_t u64[4] = { + (uint8_t)(((imm8 >> 0) & 0x3) * sz), + (uint8_t)(((imm8 >> 2) & 0x3) * sz), + (uint8_t)(((imm8 >> 4) & 0x3) * sz), + (uint8_t)(((imm8 >> 6) & 0x3) * sz), + }; + + uint8x16_t idx_lo = { + // lo[0] bytes + (uint8_t)(u64[0]+0), (uint8_t)(u64[0]+1), (uint8_t)(u64[0]+2), (uint8_t)(u64[0]+3), + (uint8_t)(u64[0]+4), (uint8_t)(u64[0]+5), (uint8_t)(u64[0]+6), (uint8_t)(u64[0]+7), + + // lo[1] bytes + (uint8_t)(u64[1]+0), (uint8_t)(u64[1]+1), (uint8_t)(u64[1]+2), (uint8_t)(u64[1]+3), + (uint8_t)(u64[1]+4), (uint8_t)(u64[1]+5), (uint8_t)(u64[1]+6), (uint8_t)(u64[1]+7), + }; + uint8x16_t idx_hi = { + // hi[0] bytes + (uint8_t)(u64[2]+0), (uint8_t)(u64[2]+1), (uint8_t)(u64[2]+2), (uint8_t)(u64[2]+3), + (uint8_t)(u64[2]+4), (uint8_t)(u64[2]+5), (uint8_t)(u64[2]+6), (uint8_t)(u64[2]+7), + + // hi[1] bytes + (uint8_t)(u64[3]+0), (uint8_t)(u64[3]+1), (uint8_t)(u64[3]+2), (uint8_t)(u64[3]+3), + (uint8_t)(u64[3]+4), (uint8_t)(u64[3]+5), (uint8_t)(u64[3]+6), (uint8_t)(u64[3]+7), + }; + + uint8x16_t lo = vqtbl2q_u8(tbl, idx_lo); + uint8x16_t hi = vqtbl2q_u8(tbl, idx_hi); + + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_permute2x128_si256(const __m256i a,const __m256i b, const int imm8) +{ + return __m256i(_mm256_permute2f128_ps(__m256(a),__m256(b),imm8)); +} + + + +AVX2NEON_ABI +__m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask) +{ + __m256 res; + res.lo = _mm_maskload_ps(mem_addr,mask.lo); + res.hi = _mm_maskload_ps(mem_addr + 4,mask.hi); + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_cvtepu8_epi32 (__m128i a) +{ + uint8x16_t a_u8 = vreinterpretq_u8_m128i(a); // xxxx xxxx xxxx xxxx HHGG FFEE DDCC BBAA + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(a_u8)); // 00HH 00GG 00FF 00EE 00DD 00CC 00BB 00AA + uint32x4_t lo = vmovl_u16(vget_low_u16(u16x8)); // 0000 00DD 0000 00CC 0000 00BB 0000 00AA + uint32x4_t hi = vmovl_high_u16(u16x8); // 0000 00HH 0000 00GG 0000 00FF 0000 00EE + + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_cvtepi8_epi32 (__m128i a) +{ + int8x16_t a_s8 = vreinterpretq_s8_m128i(a); // xxxx xxxx xxxx xxxx HHGG FFEE DDCC BBAA + int16x8_t s16x8 = vmovl_s8(vget_low_s8(a_s8)); // ssHH ssGG ssFF ssEE ssDD ssCC ssBB ssAA + int32x4_t lo = vmovl_s16(vget_low_s16(s16x8)); // ssss ssDD ssss ssCC ssss ssBB ssss ssAA + int32x4_t hi = vmovl_high_s16(s16x8); // ssss ssHH ssss ssGG ssss ssFF ssss ssEE + + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_cvtepi16_epi32 (__m128i a) +{ + int16x8_t a_s16 = vreinterpretq_s16_m128i(a); // HHHH GGGG FFFF EEEE DDDD CCCC BBBB AAAA + int32x4_t lo = vmovl_s16(vget_low_s16(a_s16)); // ssss DDDD ssss CCCC ssss BBBB ssss AAAA + int32x4_t hi = vmovl_high_s16(a_s16); // ssss HHHH ssss GGGG ssss FFFF ssss EEEE + + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + + +AVX2NEON_ABI +void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a) +{ + _mm_maskstore_epi32(mem_addr,mask.lo,a.lo); + _mm_maskstore_epi32(mem_addr + 4,mask.hi,a.hi); +} + +AVX2NEON_ABI +__m256i _mm256_slli_epi64 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_slli_epi64(a.lo,imm8); + res.hi = _mm_slli_epi64(a.hi,imm8); + return res; +} + +AVX2NEON_ABI +__m256i _mm256_slli_epi32 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_slli_epi32(a.lo,imm8); + res.hi = _mm_slli_epi32(a.hi,imm8); + return res; +} + + +AVX2NEON_ABI +__m256i __mm256_slli_epi16 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_slli_epi16(a.lo,imm8); + res.hi = _mm_slli_epi16(a.hi,imm8); + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_srli_epi32 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_srli_epi32(a.lo,imm8); + res.hi = _mm_srli_epi32(a.hi,imm8); + return res; +} + +AVX2NEON_ABI +__m256i __mm256_srli_epi16 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_srli_epi16(a.lo,imm8); + res.hi = _mm_srli_epi16(a.hi,imm8); + return res; +} + +AVX2NEON_ABI +__m256i _mm256_cvtepu16_epi32(__m128i a) +{ + __m256i res; + res.lo = vmovl_u16(vget_low_u16(a)); + res.hi = vmovl_high_u16(a); + return res; +} + +AVX2NEON_ABI +__m256i _mm256_cvtepu8_epi16(__m128i a) +{ + __m256i res; + res.lo = vmovl_u8(vget_low_u8(a)); + res.hi = vmovl_high_u8(a); + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_srai_epi32 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_srai_epi32(a.lo,imm8); + res.hi = _mm_srai_epi32(a.hi,imm8); + return res; +} + +AVX2NEON_ABI +__m256i _mm256_srai_epi16 (__m256i a, int imm8) +{ + __m256i res; + res.lo = _mm_srai_epi16(a.lo,imm8); + res.hi = _mm_srai_epi16(a.hi,imm8); + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_sllv_epi32 (__m256i a, __m256i count) +{ + __m256i res; + res.lo = vshlq_s32(a.lo,count.lo); + res.hi = vshlq_s32(a.hi,count.hi); + return res; + +} + + +AVX2NEON_ABI +__m256i _mm256_srav_epi32 (__m256i a, __m256i count) +{ + __m256i res; + res.lo = vshlq_s32(a.lo,vnegq_s32(count.lo)); + res.hi = vshlq_s32(a.hi,vnegq_s32(count.hi)); + return res; + +} + +AVX2NEON_ABI +__m256i _mm256_srlv_epi32 (__m256i a, __m256i count) +{ + __m256i res; + res.lo = __m128i(vshlq_u32(uint32x4_t(a.lo),vnegq_s32(count.lo))); + res.hi = __m128i(vshlq_u32(uint32x4_t(a.hi),vnegq_s32(count.hi))); + return res; + +} + + +AVX2NEON_ABI +__m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8) +{ + return __m256i(_mm256_permute2f128_ps(__m256(a),__m256(b),imm8)); +} + + +AVX2NEON_ABI +__m128i _mm256_extractf128_si256 (__m256i a, const int imm8) +{ + if (imm8 & 1) return a.hi; + return a.lo; +} + +AVX2NEON_ABI +__m256 _mm256_set1_ps(float x) +{ + __m256 res; + res.lo = res.hi = vdupq_n_f32(x); + return res; +} + +AVX2NEON_ABI +__m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0) +{ + __m256 res; + res.lo = _mm_set_ps(e3,e2,e1,e0); + res.hi = _mm_set_ps(e7,e6,e5,e4); + return res; +} + +AVX2NEON_ABI +__m256 _mm256_broadcast_ps (__m128 const * mem_addr) +{ + __m256 res; + res.lo = res.hi = *mem_addr; + return res; +} + +AVX2NEON_ABI +__m256 _mm256_cvtepi32_ps (__m256i a) +{ + __m256 res; + res.lo = _mm_cvtepi32_ps(a.lo); + res.hi = _mm_cvtepi32_ps(a.hi); + return res; +} +AVX2NEON_ABI +void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a) +{ + uint32x4_t mask_lo = mask.lo; + uint32x4_t mask_hi = mask.hi; + float32x4_t a_lo = a.lo; + float32x4_t a_hi = a.hi; + + for (int i=0;i<4;i++) { + if (mask_lo[i] & 0x80000000) mem_addr[i] = a_lo[i]; + if (mask_hi[i] & 0x80000000) mem_addr[i+4] = a_hi[i]; + } +} + +AVX2NEON_ABI +__m256d _mm256_andnot_pd (__m256d a, __m256d b) +{ + __m256d res; + res.lo = float64x2_t(_mm_andnot_ps(__m128(a.lo),__m128(b.lo))); + res.hi = float64x2_t(_mm_andnot_ps(__m128(a.hi),__m128(b.hi))); + return res; +} + +AVX2NEON_ABI +__m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8) +{ + __m256 res; + res.lo = _mm_blend_ps(a.lo,b.lo,imm8 & 0xf); + res.hi = _mm_blend_ps(a.hi,b.hi,imm8 >> 4); + return res; + +} + + +AVX2NEON_ABI +__m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8) +{ + return __m256i(_mm256_blend_ps(__m256(a),__m256(b),imm8)); + +} + +AVX2NEON_ABI +__m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8) +{ + __m256i res; + res.lo = _mm_blend_epi16(a.lo,b.lo,imm8); + res.hi = _mm_blend_epi16(a.hi,b.hi,imm8); + return res; +} + + + +AVX2NEON_ABI +__m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale) +{ + int32x4_t vindex_lo = vindex.lo; + int32x4_t vindex_hi = vindex.hi; + int32x4_t lo,hi; + for (int i=0;i<4;i++) + { + lo[i] = *(int32_t *)((char *) base_addr + (vindex_lo[i]*scale)); + hi[i] = *(int32_t *)((char *) base_addr + (vindex_hi[i]*scale)); + } + + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} + + +AVX2NEON_ABI +__m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale) +{ + uint32x4_t mask_lo = mask.lo; + uint32x4_t mask_hi = mask.hi; + int32x4_t vindex_lo = vindex.lo; + int32x4_t vindex_hi = vindex.hi; + int32x4_t lo,hi; + lo = hi = _mm_setzero_si128(); + for (int i=0;i<4;i++) + { + if (mask_lo[i] >> 31) lo[i] = *(int32_t *)((char *) base_addr + (vindex_lo[i]*scale)); + if (mask_hi[i] >> 31) hi[i] = *(int32_t *)((char *) base_addr + (vindex_hi[i]*scale)); + } + + __m256i res; + res.lo = lo; res.hi = hi; + return res; +} diff --git a/common/simd/arm/emulation.h b/common/simd/arm/emulation.h new file mode 100644 index 0000000000..4327298019 --- /dev/null +++ b/common/simd/arm/emulation.h @@ -0,0 +1,85 @@ +// Copyright 2009-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +/* Make precision match SSE, at the cost of some performance */ +#if !defined(__aarch64__) +# define SSE2NEON_PRECISE_DIV 1 +# define SSE2NEON_PRECISE_SQRT 1 +#endif + +#include "sse2neon.h" + +__forceinline __m128 _mm_abs_ps(__m128 a) { return vabsq_f32(a); } + +__forceinline __m128 _mm_fmadd_ps (__m128 a, __m128 b, __m128 c) { return vfmaq_f32(c, a, b); } +__forceinline __m128 _mm_fnmadd_ps(__m128 a, __m128 b, __m128 c) { return vfmsq_f32(c, a, b); } +__forceinline __m128 _mm_fnmsub_ps(__m128 a, __m128 b, __m128 c) { return vnegq_f32(vfmaq_f32(c, a, b)); } +__forceinline __m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c) { return vnegq_f32(vfmsq_f32(c, a, b)); } + +__forceinline __m128 _mm_broadcast_ss (float const * mem_addr) +{ + return vdupq_n_f32(*mem_addr); +} + +// AVX2 emulation leverages Intel FMA defs above. Include after them. +#include "avx2neon.h" + +/* Dummy defines for floating point control */ +#define _MM_MASK_MASK 0x1f80 +#define _MM_MASK_DIV_ZERO 0x200 +// #define _MM_FLUSH_ZERO_ON 0x8000 +#define _MM_MASK_DENORM 0x100 +#define _MM_SET_EXCEPTION_MASK(x) +// #define _MM_SET_FLUSH_ZERO_MODE(x) + +__forceinline int _mm_getcsr() +{ + return 0; +} + +__forceinline void _mm_mfence() +{ + __sync_synchronize(); +} + +__forceinline __m128i _mm_load4epu8_epi32(__m128i *ptr) +{ + uint8x8_t t0 = vld1_u8((uint8_t*)ptr); + uint16x8_t t1 = vmovl_u8(t0); + uint32x4_t t2 = vmovl_u16(vget_low_u16(t1)); + return vreinterpretq_s32_u32(t2); +} + +__forceinline __m128i _mm_load4epu16_epi32(__m128i *ptr) +{ + uint16x8_t t0 = vld1q_u16((uint16_t*)ptr); + uint32x4_t t1 = vmovl_u16(vget_low_u16(t0)); + return vreinterpretq_s32_u32(t1); +} + +__forceinline __m128i _mm_load4epi8_f32(__m128i *ptr) +{ + int8x8_t t0 = vld1_s8((int8_t*)ptr); + int16x8_t t1 = vmovl_s8(t0); + int32x4_t t2 = vmovl_s16(vget_low_s16(t1)); + float32x4_t t3 = vcvtq_f32_s32(t2); + return vreinterpretq_s32_f32(t3); +} + +__forceinline __m128i _mm_load4epu8_f32(__m128i *ptr) +{ + uint8x8_t t0 = vld1_u8((uint8_t*)ptr); + uint16x8_t t1 = vmovl_u8(t0); + uint32x4_t t2 = vmovl_u16(vget_low_u16(t1)); + return vreinterpretq_s32_u32(t2); +} + +__forceinline __m128i _mm_load4epi16_f32(__m128i *ptr) +{ + int16x8_t t0 = vld1q_s16((int16_t*)ptr); + int32x4_t t1 = vmovl_s16(vget_low_s16(t0)); + float32x4_t t2 = vcvtq_f32_s32(t1); + return vreinterpretq_s32_f32(t2); +} diff --git a/common/simd/arm/sse2neon.h b/common/simd/arm/sse2neon.h new file mode 100644 index 0000000000..43416662d7 --- /dev/null +++ b/common/simd/arm/sse2neon.h @@ -0,0 +1,8743 @@ +#ifndef SSE2NEON_H +#define SSE2NEON_H + +// This header file provides a simple API translation layer +// between SSE intrinsics to their corresponding Arm/Aarch64 NEON versions +// +// This header file does not yet translate all of the SSE intrinsics. +// +// Contributors to this work are: +// John W. Ratcliff +// Brandon Rowlett +// Ken Fast +// Eric van Beurden +// Alexander Potylitsin +// Hasindu Gamaarachchi +// Jim Huang +// Mark Cheng +// Malcolm James MacLeod +// Devin Hussey (easyaspi314) +// Sebastian Pop +// Developer Ecosystem Engineering +// Danila Kutenin +// François Turban (JishinMaster) +// Pei-Hsuan Hung +// Yang-Hao Yuan +// Syoyo Fujita +// Brecht Van Lommel + +/* + * sse2neon is freely redistributable under the MIT License. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* Tunable configurations */ + +/* Enable precise implementation of math operations + * This would slow down the computation a bit, but gives consistent result with + * x86 SSE. (e.g. would solve a hole or NaN pixel in the rendering result) + */ +/* _mm_min_ps and _mm_max_ps */ +#ifndef SSE2NEON_PRECISE_MINMAX +#define SSE2NEON_PRECISE_MINMAX (0) +#endif +/* _mm_rcp_ps and _mm_div_ps */ +#ifndef SSE2NEON_PRECISE_DIV +#define SSE2NEON_PRECISE_DIV (0) +#endif +/* _mm_sqrt_ps and _mm_rsqrt_ps */ +#ifndef SSE2NEON_PRECISE_SQRT +#define SSE2NEON_PRECISE_SQRT (0) +#endif +/* _mm_dp_pd */ +#ifndef SSE2NEON_PRECISE_DP +#define SSE2NEON_PRECISE_DP (0) +#endif + +/* compiler specific definitions */ +#if defined(__GNUC__) || defined(__clang__) +#pragma push_macro("FORCE_INLINE") +#pragma push_macro("ALIGN_STRUCT") +#define FORCE_INLINE static inline __attribute__((always_inline)) +#define ALIGN_STRUCT(x) __attribute__((aligned(x))) +#define _sse2neon_likely(x) __builtin_expect(!!(x), 1) +#define _sse2neon_unlikely(x) __builtin_expect(!!(x), 0) +#else /* non-GNU / non-clang compilers */ +#warning "Macro name collisions may happen with unsupported compiler." +#ifndef FORCE_INLINE +#define FORCE_INLINE static inline +#endif +#ifndef ALIGN_STRUCT +#define ALIGN_STRUCT(x) __declspec(align(x)) +#endif +#define _sse2neon_likely(x) (x) +#define _sse2neon_unlikely(x) (x) +#endif + +#include +#include + +/* Architecture-specific build options */ +/* FIXME: #pragma GCC push_options is only available on GCC */ +#if defined(__GNUC__) +#if defined(__arm__) && __ARM_ARCH == 7 +/* According to ARM C Language Extensions Architecture specification, + * __ARM_NEON is defined to a value indicating the Advanced SIMD (NEON) + * architecture supported. + */ +#if !defined(__ARM_NEON) || !defined(__ARM_NEON__) +#error "You must enable NEON instructions (e.g. -mfpu=neon) to use SSE2NEON." +#endif +#if !defined(__clang__) +#pragma GCC push_options +#pragma GCC target("fpu=neon") +#endif +#elif defined(__aarch64__) +#if !defined(__clang__) +#pragma GCC push_options +#pragma GCC target("+simd") +#endif +#else +#error "Unsupported target. Must be either ARMv7-A+NEON or ARMv8-A." +#endif +#endif + +#include + +/* Rounding functions require either Aarch64 instructions or libm failback */ +#if !defined(__aarch64__) +#include +#endif + +/* "__has_builtin" can be used to query support for built-in functions + * provided by gcc/clang and other compilers that support it. + */ +#ifndef __has_builtin /* GCC prior to 10 or non-clang compilers */ +/* Compatibility with gcc <= 9 */ +#if __GNUC__ <= 9 +#define __has_builtin(x) HAS##x +#define HAS__builtin_popcount 1 +#define HAS__builtin_popcountll 1 +#else +#define __has_builtin(x) 0 +#endif +#endif + +/** + * MACRO for shuffle parameter for _mm_shuffle_ps(). + * Argument fp3 is a digit[0123] that represents the fp from argument "b" + * of mm_shuffle_ps that will be placed in fp3 of result. fp2 is the same + * for fp2 in result. fp1 is a digit[0123] that represents the fp from + * argument "a" of mm_shuffle_ps that will be places in fp1 of result. + * fp0 is the same for fp0 of result. + */ +#if defined(__aarch64__) +#define _MN_SHUFFLE(fp3,fp2,fp1,fp0) ( (uint8x16_t){ (((fp3)*4)+0), (((fp3)*4)+1), (((fp3)*4)+2), (((fp3)*4)+3), (((fp2)*4)+0), (((fp2)*4)+1), (((fp2)*4)+\ +2), (((fp2)*4)+3), (((fp1)*4)+0), (((fp1)*4)+1), (((fp1)*4)+2), (((fp1)*4)+3), (((fp0)*4)+0), (((fp0)*4)+1), (((fp0)*4)+2), (((fp0)*4)+3) } ) +#define _MF_SHUFFLE(fp3,fp2,fp1,fp0) ( (uint8x16_t){ (((fp3)*4)+0), (((fp3)*4)+1), (((fp3)*4)+2), (((fp3)*4)+3), (((fp2)*4)+0), (((fp2)*4)+1), (((fp2)*4)+\ +2), (((fp2)*4)+3), (((fp1)*4)+16+0), (((fp1)*4)+16+1), (((fp1)*4)+16+2), (((fp1)*4)+16+3), (((fp0)*4)+16+0), (((fp0)*4)+16+1), (((fp0)*4)+16+2), (((fp0)*\ +4)+16+3) } ) +#endif + +#define _MM_SHUFFLE(fp3, fp2, fp1, fp0) \ + (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | ((fp0))) + +/* Rounding mode macros. */ +#define _MM_FROUND_TO_NEAREST_INT 0x00 +#define _MM_FROUND_TO_NEG_INF 0x01 +#define _MM_FROUND_TO_POS_INF 0x02 +#define _MM_FROUND_TO_ZERO 0x03 +#define _MM_FROUND_CUR_DIRECTION 0x04 +#define _MM_FROUND_NO_EXC 0x08 +#define _MM_ROUND_NEAREST 0x0000 +#define _MM_ROUND_DOWN 0x2000 +#define _MM_ROUND_UP 0x4000 +#define _MM_ROUND_TOWARD_ZERO 0x6000 +/* Flush zero mode macros. */ +#define _MM_FLUSH_ZERO_MASK 0x8000 +#define _MM_FLUSH_ZERO_ON 0x8000 +#define _MM_FLUSH_ZERO_OFF 0x0000 +/* Denormals are zeros mode macros. */ +#define _MM_DENORMALS_ZERO_MASK 0x0040 +#define _MM_DENORMALS_ZERO_ON 0x0040 +#define _MM_DENORMALS_ZERO_OFF 0x0000 + +/* indicate immediate constant argument in a given range */ +#define __constrange(a, b) const + +/* A few intrinsics accept traditional data types like ints or floats, but + * most operate on data types that are specific to SSE. + * If a vector type ends in d, it contains doubles, and if it does not have + * a suffix, it contains floats. An integer vector type can contain any type + * of integer, from chars to shorts to unsigned long longs. + */ +typedef int64x1_t __m64; +typedef float32x4_t __m128; /* 128-bit vector containing 4 floats */ +// On ARM 32-bit architecture, the float64x2_t is not supported. +// The data type __m128d should be represented in a different way for related +// intrinsic conversion. +#if defined(__aarch64__) +typedef float64x2_t __m128d; /* 128-bit vector containing 2 doubles */ +#else +typedef float32x4_t __m128d; +#endif +// Note: upstream sse2neon declares __m128i as int64x2_t. However, there's +// many places within embree that assume __m128i can be indexed as a +// 4 element u32. +typedef int32x4_t __m128i; /* 128-bit vector containing integers */ + +/* type-safe casting between types */ + +#define vreinterpretq_m128_f16(x) vreinterpretq_f32_f16(x) +#define vreinterpretq_m128_f32(x) (x) +#define vreinterpretq_m128_f64(x) vreinterpretq_f32_f64(x) + +#define vreinterpretq_m128_u8(x) vreinterpretq_f32_u8(x) +#define vreinterpretq_m128_u16(x) vreinterpretq_f32_u16(x) +#define vreinterpretq_m128_u32(x) vreinterpretq_f32_u32(x) +#define vreinterpretq_m128_u64(x) vreinterpretq_f32_u64(x) + +#define vreinterpretq_m128_s8(x) vreinterpretq_f32_s8(x) +#define vreinterpretq_m128_s16(x) vreinterpretq_f32_s16(x) +#define vreinterpretq_m128_s32(x) vreinterpretq_f32_s32(x) +#define vreinterpretq_m128_s64(x) vreinterpretq_f32_s64(x) + +#define vreinterpretq_f16_m128(x) vreinterpretq_f16_f32(x) +#define vreinterpretq_f32_m128(x) (x) +#define vreinterpretq_f64_m128(x) vreinterpretq_f64_f32(x) + +#define vreinterpretq_u8_m128(x) vreinterpretq_u8_f32(x) +#define vreinterpretq_u16_m128(x) vreinterpretq_u16_f32(x) +#define vreinterpretq_u32_m128(x) vreinterpretq_u32_f32(x) +#define vreinterpretq_u64_m128(x) vreinterpretq_u64_f32(x) + +#define vreinterpretq_s8_m128(x) vreinterpretq_s8_f32(x) +#define vreinterpretq_s16_m128(x) vreinterpretq_s16_f32(x) +#define vreinterpretq_s32_m128(x) vreinterpretq_s32_f32(x) +#define vreinterpretq_s64_m128(x) vreinterpretq_s64_f32(x) + +#define vreinterpretq_m128i_s8(x) vreinterpretq_s32_s8(x) +#define vreinterpretq_m128i_s16(x) vreinterpretq_s32_s16(x) +#define vreinterpretq_m128i_s32(x) (x) +#define vreinterpretq_m128i_s64(x) vreinterpretq_s32_s64(x) + +#define vreinterpretq_m128i_u8(x) vreinterpretq_s32_u8(x) +#define vreinterpretq_m128i_u16(x) vreinterpretq_s32_u16(x) +#define vreinterpretq_m128i_u32(x) vreinterpretq_s32_u32(x) +#define vreinterpretq_m128i_u64(x) vreinterpretq_s32_u64(x) + +#define vreinterpretq_f32_m128i(x) vreinterpretq_f32_s32(x) +#define vreinterpretq_f64_m128i(x) vreinterpretq_f64_s32(x) + +#define vreinterpretq_s8_m128i(x) vreinterpretq_s8_s32(x) +#define vreinterpretq_s16_m128i(x) vreinterpretq_s16_s32(x) +#define vreinterpretq_s32_m128i(x) (x) +#define vreinterpretq_s64_m128i(x) vreinterpretq_s64_s32(x) + +#define vreinterpretq_u8_m128i(x) vreinterpretq_u8_s32(x) +#define vreinterpretq_u16_m128i(x) vreinterpretq_u16_s32(x) +#define vreinterpretq_u32_m128i(x) vreinterpretq_u32_s32(x) +#define vreinterpretq_u64_m128i(x) vreinterpretq_u64_s32(x) + +#define vreinterpret_m64_s8(x) vreinterpret_s64_s8(x) +#define vreinterpret_m64_s16(x) vreinterpret_s64_s16(x) +#define vreinterpret_m64_s32(x) vreinterpret_s64_s32(x) +#define vreinterpret_m64_s64(x) (x) + +#define vreinterpret_m64_u8(x) vreinterpret_s64_u8(x) +#define vreinterpret_m64_u16(x) vreinterpret_s64_u16(x) +#define vreinterpret_m64_u32(x) vreinterpret_s64_u32(x) +#define vreinterpret_m64_u64(x) vreinterpret_s64_u64(x) + +#define vreinterpret_m64_f16(x) vreinterpret_s64_f16(x) +#define vreinterpret_m64_f32(x) vreinterpret_s64_f32(x) +#define vreinterpret_m64_f64(x) vreinterpret_s64_f64(x) + +#define vreinterpret_u8_m64(x) vreinterpret_u8_s64(x) +#define vreinterpret_u16_m64(x) vreinterpret_u16_s64(x) +#define vreinterpret_u32_m64(x) vreinterpret_u32_s64(x) +#define vreinterpret_u64_m64(x) vreinterpret_u64_s64(x) + +#define vreinterpret_s8_m64(x) vreinterpret_s8_s64(x) +#define vreinterpret_s16_m64(x) vreinterpret_s16_s64(x) +#define vreinterpret_s32_m64(x) vreinterpret_s32_s64(x) +#define vreinterpret_s64_m64(x) (x) + +#define vreinterpret_f32_m64(x) vreinterpret_f32_s64(x) + +#if defined(__aarch64__) +#define vreinterpretq_m128d_s32(x) vreinterpretq_f64_s32(x) +#define vreinterpretq_m128d_s64(x) vreinterpretq_f64_s64(x) + +#define vreinterpretq_m128d_u64(x) vreinterpretq_f64_u64(x) + +#define vreinterpretq_m128d_f32(x) vreinterpretq_f64_f32(x) +#define vreinterpretq_m128d_f64(x) (x) + +#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f64(x) + +#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f64(x) +#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f64(x) + +#define vreinterpretq_f64_m128d(x) (x) +#define vreinterpretq_f32_m128d(x) vreinterpretq_f32_f64(x) +#else +#define vreinterpretq_m128d_s32(x) vreinterpretq_f32_s32(x) +#define vreinterpretq_m128d_s64(x) vreinterpretq_f32_s64(x) + +#define vreinterpretq_m128d_u32(x) vreinterpretq_f32_u32(x) +#define vreinterpretq_m128d_u64(x) vreinterpretq_f32_u64(x) + +#define vreinterpretq_m128d_f32(x) (x) + +#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f32(x) + +#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f32(x) +#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f32(x) + +#define vreinterpretq_f32_m128d(x) (x) +#endif + +// A struct is defined in this header file called 'SIMDVec' which can be used +// by applications which attempt to access the contents of an __m128 struct +// directly. It is important to note that accessing the __m128 struct directly +// is bad coding practice by Microsoft: @see: +// https://docs.microsoft.com/en-us/cpp/cpp/m128 +// +// However, some legacy source code may try to access the contents of an __m128 +// struct directly so the developer can use the SIMDVec as an alias for it. Any +// casting must be done manually by the developer, as you cannot cast or +// otherwise alias the base NEON data type for intrinsic operations. +// +// union intended to allow direct access to an __m128 variable using the names +// that the MSVC compiler provides. This union should really only be used when +// trying to access the members of the vector as integer values. GCC/clang +// allow native access to the float members through a simple array access +// operator (in C since 4.6, in C++ since 4.8). +// +// Ideally direct accesses to SIMD vectors should not be used since it can cause +// a performance hit. If it really is needed however, the original __m128 +// variable can be aliased with a pointer to this union and used to access +// individual components. The use of this union should be hidden behind a macro +// that is used throughout the codebase to access the members instead of always +// declaring this type of variable. +typedef union ALIGN_STRUCT(16) SIMDVec { + float m128_f32[4]; // as floats - DON'T USE. Added for convenience. + int8_t m128_i8[16]; // as signed 8-bit integers. + int16_t m128_i16[8]; // as signed 16-bit integers. + int32_t m128_i32[4]; // as signed 32-bit integers. + int64_t m128_i64[2]; // as signed 64-bit integers. + uint8_t m128_u8[16]; // as unsigned 8-bit integers. + uint16_t m128_u16[8]; // as unsigned 16-bit integers. + uint32_t m128_u32[4]; // as unsigned 32-bit integers. + uint64_t m128_u64[2]; // as unsigned 64-bit integers. +} SIMDVec; + +// casting using SIMDVec +#define vreinterpretq_nth_u64_m128i(x, n) (((SIMDVec *) &x)->m128_u64[n]) +#define vreinterpretq_nth_u32_m128i(x, n) (((SIMDVec *) &x)->m128_u32[n]) +#define vreinterpretq_nth_u8_m128i(x, n) (((SIMDVec *) &x)->m128_u8[n]) + +/* SSE macros */ +#define _MM_GET_FLUSH_ZERO_MODE _sse2neon_mm_get_flush_zero_mode +#define _MM_SET_FLUSH_ZERO_MODE _sse2neon_mm_set_flush_zero_mode +#define _MM_GET_DENORMALS_ZERO_MODE _sse2neon_mm_get_denormals_zero_mode +#define _MM_SET_DENORMALS_ZERO_MODE _sse2neon_mm_set_denormals_zero_mode + +// Function declaration +// SSE +FORCE_INLINE unsigned int _MM_GET_ROUNDING_MODE(); +FORCE_INLINE __m128 _mm_move_ss(__m128, __m128); +FORCE_INLINE __m128 _mm_or_ps(__m128, __m128); +FORCE_INLINE __m128 _mm_set_ps1(float); +FORCE_INLINE __m128 _mm_setzero_ps(void); +// SSE2 +FORCE_INLINE __m128i _mm_and_si128(__m128i, __m128i); +FORCE_INLINE __m128i _mm_castps_si128(__m128); +FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i, __m128i); +FORCE_INLINE __m128i _mm_cvtps_epi32(__m128); +FORCE_INLINE __m128d _mm_move_sd(__m128d, __m128d); +FORCE_INLINE __m128i _mm_or_si128(__m128i, __m128i); +FORCE_INLINE __m128i _mm_set_epi32(int, int, int, int); +FORCE_INLINE __m128i _mm_set_epi64x(int64_t, int64_t); +FORCE_INLINE __m128d _mm_set_pd(double, double); +FORCE_INLINE __m128i _mm_set1_epi32(int); +FORCE_INLINE __m128i _mm_setzero_si128(); +// SSE4.1 +FORCE_INLINE __m128d _mm_ceil_pd(__m128d); +FORCE_INLINE __m128 _mm_ceil_ps(__m128); +FORCE_INLINE __m128d _mm_floor_pd(__m128d); +FORCE_INLINE __m128 _mm_floor_ps(__m128); +FORCE_INLINE __m128d _mm_round_pd(__m128d, int); +FORCE_INLINE __m128 _mm_round_ps(__m128, int); +// SSE4.2 +FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t, uint8_t); + +/* Backwards compatibility for compilers with lack of specific type support */ + +// Older gcc does not define vld1q_u8_x4 type +#if defined(__GNUC__) && !defined(__clang__) && \ + ((__GNUC__ <= 10 && defined(__arm__)) || \ + (__GNUC__ == 10 && __GNUC_MINOR__ < 3 && defined(__aarch64__)) || \ + (__GNUC__ <= 9 && defined(__aarch64__))) +FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p) +{ + uint8x16x4_t ret; + ret.val[0] = vld1q_u8(p + 0); + ret.val[1] = vld1q_u8(p + 16); + ret.val[2] = vld1q_u8(p + 32); + ret.val[3] = vld1q_u8(p + 48); + return ret; +} +#else +// Wraps vld1q_u8_x4 +FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p) +{ + return vld1q_u8_x4(p); +} +#endif + +/* Function Naming Conventions + * The naming convention of SSE intrinsics is straightforward. A generic SSE + * intrinsic function is given as follows: + * _mm__ + * + * The parts of this format are given as follows: + * 1. describes the operation performed by the intrinsic + * 2. identifies the data type of the function's primary arguments + * + * This last part, , is a little complicated. It identifies the + * content of the input values, and can be set to any of the following values: + * + ps - vectors contain floats (ps stands for packed single-precision) + * + pd - vectors cantain doubles (pd stands for packed double-precision) + * + epi8/epi16/epi32/epi64 - vectors contain 8-bit/16-bit/32-bit/64-bit + * signed integers + * + epu8/epu16/epu32/epu64 - vectors contain 8-bit/16-bit/32-bit/64-bit + * unsigned integers + * + si128 - unspecified 128-bit vector or 256-bit vector + * + m128/m128i/m128d - identifies input vector types when they are different + * than the type of the returned vector + * + * For example, _mm_setzero_ps. The _mm implies that the function returns + * a 128-bit vector. The _ps at the end implies that the argument vectors + * contain floats. + * + * A complete example: Byte Shuffle - pshufb (_mm_shuffle_epi8) + * // Set packed 16-bit integers. 128 bits, 8 short, per 16 bits + * __m128i v_in = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + * // Set packed 8-bit integers + * // 128 bits, 16 chars, per 8 bits + * __m128i v_perm = _mm_setr_epi8(1, 0, 2, 3, 8, 9, 10, 11, + * 4, 5, 12, 13, 6, 7, 14, 15); + * // Shuffle packed 8-bit integers + * __m128i v_out = _mm_shuffle_epi8(v_in, v_perm); // pshufb + * + * Data (Number, Binary, Byte Index): + +------+------+-------------+------+------+-------------+ + | 1 | 2 | 3 | 4 | Number + +------+------+------+------+------+------+------+------+ + | 0000 | 0001 | 0000 | 0010 | 0000 | 0011 | 0000 | 0100 | Binary + +------+------+------+------+------+------+------+------+ + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index + +------+------+------+------+------+------+------+------+ + + +------+------+------+------+------+------+------+------+ + | 5 | 6 | 7 | 8 | Number + +------+------+------+------+------+------+------+------+ + | 0000 | 0101 | 0000 | 0110 | 0000 | 0111 | 0000 | 1000 | Binary + +------+------+------+------+------+------+------+------+ + | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Index + +------+------+------+------+------+------+------+------+ + * Index (Byte Index): + +------+------+------+------+------+------+------+------+ + | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 | + +------+------+------+------+------+------+------+------+ + + +------+------+------+------+------+------+------+------+ + | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 | + +------+------+------+------+------+------+------+------+ + * Result: + +------+------+------+------+------+------+------+------+ + | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 | Index + +------+------+------+------+------+------+------+------+ + | 0001 | 0000 | 0000 | 0010 | 0000 | 0101 | 0000 | 0110 | Binary + +------+------+------+------+------+------+------+------+ + | 256 | 2 | 5 | 6 | Number + +------+------+------+------+------+------+------+------+ + + +------+------+------+------+------+------+------+------+ + | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 | Index + +------+------+------+------+------+------+------+------+ + | 0000 | 0011 | 0000 | 0111 | 0000 | 0100 | 0000 | 1000 | Binary + +------+------+------+------+------+------+------+------+ + | 3 | 7 | 4 | 8 | Number + +------+------+------+------+------+------+-------------+ + */ + +/* Constants for use with _mm_prefetch. */ +enum _mm_hint { + _MM_HINT_NTA = 0, /* load data to L1 and L2 cache, mark it as NTA */ + _MM_HINT_T0 = 1, /* load data to L1 and L2 cache */ + _MM_HINT_T1 = 2, /* load data to L2 cache only */ + _MM_HINT_T2 = 3, /* load data to L2 cache only, mark it as NTA */ + _MM_HINT_ENTA = 4, /* exclusive version of _MM_HINT_NTA */ + _MM_HINT_ET0 = 5, /* exclusive version of _MM_HINT_T0 */ + _MM_HINT_ET1 = 6, /* exclusive version of _MM_HINT_T1 */ + _MM_HINT_ET2 = 7 /* exclusive version of _MM_HINT_T2 */ +}; + +// The bit field mapping to the FPCR(floating-point control register) +typedef struct { + uint16_t res0; + uint8_t res1 : 6; + uint8_t bit22 : 1; + uint8_t bit23 : 1; + uint8_t bit24 : 1; + uint8_t res2 : 7; +#if defined(__aarch64__) + uint32_t res3; +#endif +} fpcr_bitfield; + +// Takes the upper 64 bits of a and places it in the low end of the result +// Takes the lower 64 bits of b and places it into the high end of the result. +FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b) +{ + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a32, b10)); +} + +// takes the lower two 32-bit values from a and swaps them and places in high +// end of result takes the higher two 32 bit values from b and swaps them and +// places in low end of result. +FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32x2_t b23 = vrev64_f32(vget_high_f32(vreinterpretq_f32_m128(b))); + return vreinterpretq_m128_f32(vcombine_f32(a01, b23)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b) +{ + float32x2_t a21 = vget_high_f32( + vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3)); + float32x2_t b03 = vget_low_f32( + vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3)); + return vreinterpretq_m128_f32(vcombine_f32(a21, b03)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b) +{ + float32x2_t a03 = vget_low_f32( + vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3)); + float32x2_t b21 = vget_high_f32( + vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3)); + return vreinterpretq_m128_f32(vcombine_f32(a03, b21)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a10, b10)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a01, b10)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32x2_t b01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(b))); + return vreinterpretq_m128_f32(vcombine_f32(a01, b01)); +} + +// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the +// high +FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a10, b32)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b) +{ + float32x2_t a11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 1); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + return vreinterpretq_m128_f32(vcombine_f32(a11, b00)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b) +{ + float32x2_t a22 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + return vreinterpretq_m128_f32(vcombine_f32(a22, b00)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b) +{ + float32x2_t a00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 0); + float32x2_t b22 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(b)), 0); + return vreinterpretq_m128_f32(vcombine_f32(a00, b22)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b) +{ + float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + float32x2_t a22 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0); + float32x2_t a02 = vset_lane_f32(a0, a22, 1); /* TODO: use vzip ?*/ + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a02, b32)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b) +{ + float32x2_t a33 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 1); + float32x2_t b11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 1); + return vreinterpretq_m128_f32(vcombine_f32(a33, b11)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32_t b2 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 2); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + float32x2_t b20 = vset_lane_f32(b2, b00, 1); + return vreinterpretq_m128_f32(vcombine_f32(a10, b20)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32_t b2 = vgetq_lane_f32(b, 2); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + float32x2_t b20 = vset_lane_f32(b2, b00, 1); + return vreinterpretq_m128_f32(vcombine_f32(a01, b20)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b) +{ + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32_t b2 = vgetq_lane_f32(b, 2); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + float32x2_t b20 = vset_lane_f32(b2, b00, 1); + return vreinterpretq_m128_f32(vcombine_f32(a32, b20)); +} + +// Kahan summation for accurate summation of floating-point numbers. +// http://blog.zachbjornson.com/2019/08/11/fast-float-summation.html +FORCE_INLINE void _sse2neon_kadd_f32(float *sum, float *c, float y) +{ + y -= *c; + float t = *sum + y; + *c = (t - *sum) - y; + *sum = t; +} + +#if defined(__ARM_FEATURE_CRYPTO) +// Wraps vmull_p64 +FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b) +{ + poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0); + poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0); + return vreinterpretq_u64_p128(vmull_p64(a, b)); +} +#else // ARMv7 polyfill +// ARMv7/some A64 lacks vmull_p64, but it has vmull_p8. +// +// vmull_p8 calculates 8 8-bit->16-bit polynomial multiplies, but we need a +// 64-bit->128-bit polynomial multiply. +// +// It needs some work and is somewhat slow, but it is still faster than all +// known scalar methods. +// +// Algorithm adapted to C from +// https://www.workofard.com/2017/07/ghash-for-low-end-cores/, which is adapted +// from "Fast Software Polynomial Multiplication on ARM Processors Using the +// NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and Ricardo Dahab +// (https://hal.inria.fr/hal-01506572) +static uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b) +{ + poly8x8_t a = vreinterpret_p8_u64(_a); + poly8x8_t b = vreinterpret_p8_u64(_b); + + // Masks + uint8x16_t k48_32 = vcombine_u8(vcreate_u8(0x0000ffffffffffff), + vcreate_u8(0x00000000ffffffff)); + uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff), + vcreate_u8(0x0000000000000000)); + + // Do the multiplies, rotating with vext to get all combinations + uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0 + uint8x16_t e = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1 + uint8x16_t f = + vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0 + uint8x16_t g = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2 + uint8x16_t h = + vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0 + uint8x16_t i = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3 + uint8x16_t j = + vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0 + uint8x16_t k = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4 + + // Add cross products + uint8x16_t l = veorq_u8(e, f); // L = E + F + uint8x16_t m = veorq_u8(g, h); // M = G + H + uint8x16_t n = veorq_u8(i, j); // N = I + J + + // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL + // instructions. +#if defined(__aarch64__) + uint8x16_t lm_p0 = vreinterpretq_u8_u64( + vzip1q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m))); + uint8x16_t lm_p1 = vreinterpretq_u8_u64( + vzip2q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m))); + uint8x16_t nk_p0 = vreinterpretq_u8_u64( + vzip1q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k))); + uint8x16_t nk_p1 = vreinterpretq_u8_u64( + vzip2q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k))); +#else + uint8x16_t lm_p0 = vcombine_u8(vget_low_u8(l), vget_low_u8(m)); + uint8x16_t lm_p1 = vcombine_u8(vget_high_u8(l), vget_high_u8(m)); + uint8x16_t nk_p0 = vcombine_u8(vget_low_u8(n), vget_low_u8(k)); + uint8x16_t nk_p1 = vcombine_u8(vget_high_u8(n), vget_high_u8(k)); +#endif + // t0 = (L) (P0 + P1) << 8 + // t1 = (M) (P2 + P3) << 16 + uint8x16_t t0t1_tmp = veorq_u8(lm_p0, lm_p1); + uint8x16_t t0t1_h = vandq_u8(lm_p1, k48_32); + uint8x16_t t0t1_l = veorq_u8(t0t1_tmp, t0t1_h); + + // t2 = (N) (P4 + P5) << 24 + // t3 = (K) (P6 + P7) << 32 + uint8x16_t t2t3_tmp = veorq_u8(nk_p0, nk_p1); + uint8x16_t t2t3_h = vandq_u8(nk_p1, k16_00); + uint8x16_t t2t3_l = veorq_u8(t2t3_tmp, t2t3_h); + + // De-interleave +#if defined(__aarch64__) + uint8x16_t t0 = vreinterpretq_u8_u64( + vuzp1q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h))); + uint8x16_t t1 = vreinterpretq_u8_u64( + vuzp2q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h))); + uint8x16_t t2 = vreinterpretq_u8_u64( + vuzp1q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h))); + uint8x16_t t3 = vreinterpretq_u8_u64( + vuzp2q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h))); +#else + uint8x16_t t1 = vcombine_u8(vget_high_u8(t0t1_l), vget_high_u8(t0t1_h)); + uint8x16_t t0 = vcombine_u8(vget_low_u8(t0t1_l), vget_low_u8(t0t1_h)); + uint8x16_t t3 = vcombine_u8(vget_high_u8(t2t3_l), vget_high_u8(t2t3_h)); + uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h)); +#endif + // Shift the cross products + uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8 + uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16 + uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24 + uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32 + + // Accumulate the products + uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift); + uint8x16_t cross2 = veorq_u8(t2_shift, t3_shift); + uint8x16_t mix = veorq_u8(d, cross1); + uint8x16_t r = veorq_u8(mix, cross2); + return vreinterpretq_u64_u8(r); +} +#endif // ARMv7 polyfill + +// C equivalent: +// __m128i _mm_shuffle_epi32_default(__m128i a, +// __constrange(0, 255) int imm) { +// __m128i ret; +// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3]; +// ret[2] = a[(imm >> 4) & 0x03]; ret[3] = a[(imm >> 6) & 0x03]; +// return ret; +// } +#define _mm_shuffle_epi32_default(a, imm) \ + __extension__({ \ + int32x4_t ret; \ + ret = vmovq_n_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & (0x3))); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), \ + ret, 1); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), \ + ret, 2); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), \ + ret, 3); \ + vreinterpretq_m128i_s32(ret); \ + }) + +// Takes the upper 64 bits of a and places it in the low end of the result +// Takes the lower 64 bits of a and places it into the high end of the result. +FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a) +{ + int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a)); + int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a)); + return vreinterpretq_m128i_s32(vcombine_s32(a32, a10)); +} + +// takes the lower two 32-bit values from a and swaps them and places in low end +// of result takes the higher two 32 bit values from a and swaps them and places +// in high end of result. +FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a) +{ + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + int32x2_t a23 = vrev64_s32(vget_high_s32(vreinterpretq_s32_m128i(a))); + return vreinterpretq_m128i_s32(vcombine_s32(a01, a23)); +} + +// rotates the least significant 32 bits into the most significant 32 bits, and +// shifts the rest down +FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a) +{ + return vreinterpretq_m128i_s32( + vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 1)); +} + +// rotates the most significant 32 bits into the least significant 32 bits, and +// shifts the rest up +FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a) +{ + return vreinterpretq_m128i_s32( + vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 3)); +} + +// gets the lower 64 bits of a, and places it in the upper 64 bits +// gets the lower 64 bits of a and places it in the lower 64 bits +FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a) +{ + int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a)); + return vreinterpretq_m128i_s32(vcombine_s32(a10, a10)); +} + +// gets the lower 64 bits of a, swaps the 0 and 1 elements, and places it in the +// lower 64 bits gets the lower 64 bits of a, and places it in the upper 64 bits +FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a) +{ + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a)); + return vreinterpretq_m128i_s32(vcombine_s32(a01, a10)); +} + +// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the +// upper 64 bits gets the lower 64 bits of a, swaps the 0 and 1 elements, and +// places it in the lower 64 bits +FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a) +{ + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + return vreinterpretq_m128i_s32(vcombine_s32(a01, a01)); +} + +FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a) +{ + int32x2_t a11 = vdup_lane_s32(vget_low_s32(vreinterpretq_s32_m128i(a)), 1); + int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0); + return vreinterpretq_m128i_s32(vcombine_s32(a11, a22)); +} + +FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a) +{ + int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0); + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + return vreinterpretq_m128i_s32(vcombine_s32(a22, a01)); +} + +FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a) +{ + int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a)); + int32x2_t a33 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 1); + return vreinterpretq_m128i_s32(vcombine_s32(a32, a33)); +} + +// FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255) +// int imm) +#if defined(__aarch64__) +#define _mm_shuffle_epi32_splat(a, imm) \ + __extension__({ \ + vreinterpretq_m128i_s32( \ + vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \ + }) +#else +#define _mm_shuffle_epi32_splat(a, imm) \ + __extension__({ \ + vreinterpretq_m128i_s32( \ + vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \ + }) +#endif + +// NEON does not support a general purpose permute intrinsic +// Selects four specific single-precision, floating-point values from a and b, +// based on the mask i. +// +// C equivalent: +// __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, +// __constrange(0, 255) int imm) { +// __m128 ret; +// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3]; +// ret[2] = b[(imm >> 4) & 0x03]; ret[3] = b[(imm >> 6) & 0x03]; +// return ret; +// } +// +// https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx +#define _mm_shuffle_ps_default(a, b, imm) \ + __extension__({ \ + float32x4_t ret; \ + ret = vmovq_n_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & (0x3))); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), \ + ret, 1); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), \ + ret, 2); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), \ + ret, 3); \ + vreinterpretq_m128_f32(ret); \ + }) + +// Shuffles the lower 4 signed or unsigned 16-bit integers in a as specified +// by imm. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/y41dkk37(v=vs.100) +// FORCE_INLINE __m128i _mm_shufflelo_epi16_function(__m128i a, +// __constrange(0,255) int +// imm) +#define _mm_shufflelo_epi16_function(a, imm) \ + __extension__({ \ + int16x8_t ret = vreinterpretq_s16_m128i(a); \ + int16x4_t lowBits = vget_low_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm) & (0x3)), ret, 0); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 2) & 0x3), ret, \ + 1); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 4) & 0x3), ret, \ + 2); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 6) & 0x3), ret, \ + 3); \ + vreinterpretq_m128i_s16(ret); \ + }) + +// Shuffles the upper 4 signed or unsigned 16-bit integers in a as specified +// by imm. +// https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx +// FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a, +// __constrange(0,255) int +// imm) +#define _mm_shufflehi_epi16_function(a, imm) \ + __extension__({ \ + int16x8_t ret = vreinterpretq_s16_m128i(a); \ + int16x4_t highBits = vget_high_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & (0x3)), ret, 4); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, \ + 5); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, \ + 6); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, \ + 7); \ + vreinterpretq_m128i_s16(ret); \ + }) + +/* SSE */ + +// Adds the four single-precision, floating-point values of a and b. +// +// r0 := a0 + b0 +// r1 := a1 + b1 +// r2 := a2 + b2 +// r3 := a3 + b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx +FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// adds the scalar single-precision floating point values of a and b. +// https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx +FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b) +{ + float32_t b0 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 0); + float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0); + // the upper values in the result must be the remnants of . + return vreinterpretq_m128_f32(vaddq_f32(a, value)); +} + +// Computes the bitwise AND of the four single-precision, floating-point values +// of a and b. +// +// r0 := a0 & b0 +// r1 := a1 & b1 +// r2 := a2 & b2 +// r3 := a3 & b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); +} + +// Computes the bitwise AND-NOT of the four single-precision, floating-point +// values of a and b. +// +// r0 := ~a0 & b0 +// r1 := ~a1 & b1 +// r2 := ~a2 & b2 +// r3 := ~a3 & b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx +FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + vbicq_s32(vreinterpretq_s32_m128(b), + vreinterpretq_s32_m128(a))); // *NOTE* argument swap +} + +// Average packed unsigned 16-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu16 +FORCE_INLINE __m64 _mm_avg_pu16(__m64 a, __m64 b) +{ + return vreinterpret_m64_u16( + vrhadd_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b))); +} + +// Average packed unsigned 8-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu8 +FORCE_INLINE __m64 _mm_avg_pu8(__m64 a, __m64 b) +{ + return vreinterpret_m64_u8( + vrhadd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); +} + +// Compares for equality. +// https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for equality. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/k423z28e(v=vs.100) +FORCE_INLINE __m128 _mm_cmpeq_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpeq_ps(a, b)); +} + +// Compares for greater than or equal. +// https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for greater than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/kesh3ddc(v=vs.100) +FORCE_INLINE __m128 _mm_cmpge_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpge_ps(a, b)); +} + +// Compares for greater than. +// +// r0 := (a0 > b0) ? 0xffffffff : 0x0 +// r1 := (a1 > b1) ? 0xffffffff : 0x0 +// r2 := (a2 > b2) ? 0xffffffff : 0x0 +// r3 := (a3 > b3) ? 0xffffffff : 0x0 +// +// https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for greater than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/1xyyyy9e(v=vs.100) +FORCE_INLINE __m128 _mm_cmpgt_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpgt_ps(a, b)); +} + +// Compares for less than or equal. +// +// r0 := (a0 <= b0) ? 0xffffffff : 0x0 +// r1 := (a1 <= b1) ? 0xffffffff : 0x0 +// r2 := (a2 <= b2) ? 0xffffffff : 0x0 +// r3 := (a3 <= b3) ? 0xffffffff : 0x0 +// +// https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for less than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/a7x0hbhw(v=vs.100) +FORCE_INLINE __m128 _mm_cmple_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmple_ps(a, b)); +} + +// Compares for less than +// https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for less than +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fy94wye7(v=vs.100) +FORCE_INLINE __m128 _mm_cmplt_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmplt_ps(a, b)); +} + +// Compares for inequality. +// https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32(vmvnq_u32( + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); +} + +// Compares for inequality. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ekya8fh4(v=vs.100) +FORCE_INLINE __m128 _mm_cmpneq_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpneq_ps(a, b)); +} + +// Compares for not greater than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/wsexys62(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnge_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32(vmvnq_u32( + vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); +} + +// Compares for not greater than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fk2y80s8(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnge_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpnge_ps(a, b)); +} + +// Compares for not greater than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/d0xh7w0s(v=vs.100) +FORCE_INLINE __m128 _mm_cmpngt_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32(vmvnq_u32( + vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); +} + +// Compares for not greater than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100) +FORCE_INLINE __m128 _mm_cmpngt_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpngt_ps(a, b)); +} + +// Compares for not less than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/6a330kxw(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32(vmvnq_u32( + vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); +} + +// Compares for not less than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnle_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpnle_ps(a, b)); +} + +// Compares for not less than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/4686bbdw(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32(vmvnq_u32( + vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); +} + +// Compares for not less than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/56b9z2wf(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnlt_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpnlt_ps(a, b)); +} + +// Compares the four 32-bit floats in a and b to check if any values are NaN. +// Ordered compare between each value returns true for "orderable" and false for +// "not orderable" (NaN). +// https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx see +// also: +// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean +// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics +FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b) +{ + // Note: NEON does not have ordered compare builtin + // Need to compare a eq a and b eq b to check for NaN + // Do AND of results to get final + uint32x4_t ceqaa = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t ceqbb = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_u32(vandq_u32(ceqaa, ceqbb)); +} + +// Compares for ordered. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/343t62da(v=vs.100) +FORCE_INLINE __m128 _mm_cmpord_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpord_ps(a, b)); +} + +// Compares for unordered. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/khy6fk1t(v=vs.100) +FORCE_INLINE __m128 _mm_cmpunord_ps(__m128 a, __m128 b) +{ + uint32x4_t f32a = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t f32b = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_u32(vmvnq_u32(vandq_u32(f32a, f32b))); +} + +// Compares for unordered. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/2as2387b(v=vs.100) +FORCE_INLINE __m128 _mm_cmpunord_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpunord_ps(a, b)); +} + +// Compares the lower single-precision floating point scalar values of a and b +// using an equality operation. : +// https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx +FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b) +{ + uint32x4_t a_eq_b = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return vgetq_lane_u32(a_eq_b, 0) & 0x1; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a greater than or equal operation. : +// https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx +FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b) +{ + uint32x4_t a_ge_b = + vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return vgetq_lane_u32(a_ge_b, 0) & 0x1; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a greater than operation. : +// https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx +FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b) +{ + uint32x4_t a_gt_b = + vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return vgetq_lane_u32(a_gt_b, 0) & 0x1; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a less than or equal operation. : +// https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx +FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b) +{ + uint32x4_t a_le_b = + vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return vgetq_lane_u32(a_le_b, 0) & 0x1; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a less than operation. : +// https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx Important +// note!! The documentation on MSDN is incorrect! If either of the values is a +// NAN the docs say you will get a one, but in fact, it will return a zero!! +FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b) +{ + uint32x4_t a_lt_b = + vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return vgetq_lane_u32(a_lt_b, 0) & 0x1; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using an inequality operation. : +// https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx +FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b) +{ + return !_mm_comieq_ss(a, b); +} + +// Convert packed signed 32-bit integers in b to packed single-precision +// (32-bit) floating-point elements, store the results in the lower 2 elements +// of dst, and copy the upper 2 packed elements from a to the upper elements of +// dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[63:32] := Convert_Int32_To_FP32(b[63:32]) +// dst[95:64] := a[95:64] +// dst[127:96] := a[127:96] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_pi2ps +FORCE_INLINE __m128 _mm_cvt_pi2ps(__m128 a, __m64 b) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)), + vget_high_f32(vreinterpretq_f32_m128(a)))); +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ps2pi +FORCE_INLINE __m64 _mm_cvt_ps2pi(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpret_m64_s32( + vget_low_s32(vcvtnq_s32_f32(vrndiq_f32(vreinterpretq_f32_m128(a))))); +#else + return vreinterpret_m64_s32(vcvt_s32_f32(vget_low_f32( + vreinterpretq_f32_m128(_mm_round_ps(a, _MM_FROUND_CUR_DIRECTION))))); +#endif +} + +// Convert the signed 32-bit integer b to a single-precision (32-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper 3 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_si2ss +FORCE_INLINE __m128 _mm_cvt_si2ss(__m128 a, int b) +{ + return vreinterpretq_m128_f32( + vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0)); +} + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer, and store the result in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ss2si +FORCE_INLINE int _mm_cvt_ss2si(__m128 a) +{ +#if defined(__aarch64__) + return vgetq_lane_s32(vcvtnq_s32_f32(vrndiq_f32(vreinterpretq_f32_m128(a))), + 0); +#else + float32_t data = vgetq_lane_f32( + vreinterpretq_f32_m128(_mm_round_ps(a, _MM_FROUND_CUR_DIRECTION)), 0); + return (int32_t) data; +#endif +} + +// Convert packed 16-bit integers in a to packed single-precision (32-bit) +// floating-point elements, and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// m := j*32 +// dst[m+31:m] := Convert_Int16_To_FP32(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi16_ps +FORCE_INLINE __m128 _mm_cvtpi16_ps(__m64 a) +{ + return vreinterpretq_m128_f32( + vcvtq_f32_s32(vmovl_s16(vreinterpret_s16_m64(a)))); +} + +// Convert packed 32-bit integers in b to packed single-precision (32-bit) +// floating-point elements, store the results in the lower 2 elements of dst, +// and copy the upper 2 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[63:32] := Convert_Int32_To_FP32(b[63:32]) +// dst[95:64] := a[95:64] +// dst[127:96] := a[127:96] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_ps +FORCE_INLINE __m128 _mm_cvtpi32_ps(__m128 a, __m64 b) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)), + vget_high_f32(vreinterpretq_f32_m128(a)))); +} + +// Convert packed signed 32-bit integers in a to packed single-precision +// (32-bit) floating-point elements, store the results in the lower 2 elements +// of dst, then covert the packed signed 32-bit integers in b to +// single-precision (32-bit) floating-point element, and store the results in +// the upper 2 elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(a[31:0]) +// dst[63:32] := Convert_Int32_To_FP32(a[63:32]) +// dst[95:64] := Convert_Int32_To_FP32(b[31:0]) +// dst[127:96] := Convert_Int32_To_FP32(b[63:32]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32x2_ps +FORCE_INLINE __m128 _mm_cvtpi32x2_ps(__m64 a, __m64 b) +{ + return vreinterpretq_m128_f32(vcvtq_f32_s32( + vcombine_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b)))); +} + +// Convert the lower packed 8-bit integers in a to packed single-precision +// (32-bit) floating-point elements, and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*8 +// m := j*32 +// dst[m+31:m] := Convert_Int8_To_FP32(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi8_ps +FORCE_INLINE __m128 _mm_cvtpi8_ps(__m64 a) +{ + return vreinterpretq_m128_f32(vcvtq_f32_s32( + vmovl_s16(vget_low_s16(vmovl_s8(vreinterpret_s8_m64(a)))))); +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 16-bit integers, and store the results in dst. Note: this intrinsic +// will generate 0x7FFF, rather than 0x8000, for input values between 0x7FFF and +// 0x7FFFFFFF. +// +// FOR j := 0 to 3 +// i := 16*j +// k := 32*j +// IF a[k+31:k] >= FP32(0x7FFF) && a[k+31:k] <= FP32(0x7FFFFFFF) +// dst[i+15:i] := 0x7FFF +// ELSE +// dst[i+15:i] := Convert_FP32_To_Int16(a[k+31:k]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi16 +FORCE_INLINE __m64 _mm_cvtps_pi16(__m128 a) +{ + const __m128 i16Min = _mm_set_ps1((float) INT16_MIN); + const __m128 i16Max = _mm_set_ps1((float) INT16_MAX); + const __m128 i32Max = _mm_set_ps1((float) INT32_MAX); + const __m128i maxMask = _mm_castps_si128( + _mm_and_ps(_mm_cmpge_ps(a, i16Max), _mm_cmple_ps(a, i32Max))); + const __m128i betweenMask = _mm_castps_si128( + _mm_and_ps(_mm_cmpgt_ps(a, i16Min), _mm_cmplt_ps(a, i16Max))); + const __m128i minMask = _mm_cmpeq_epi32(_mm_or_si128(maxMask, betweenMask), + _mm_setzero_si128()); + __m128i max = _mm_and_si128(maxMask, _mm_set1_epi32(INT16_MAX)); + __m128i min = _mm_and_si128(minMask, _mm_set1_epi32(INT16_MIN)); + __m128i cvt = _mm_and_si128(betweenMask, _mm_cvtps_epi32(a)); + __m128i res32 = _mm_or_si128(_mm_or_si128(max, min), cvt); + return vreinterpret_m64_s16(vmovn_s32(vreinterpretq_s32_m128i(res32))); +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi32 +#define _mm_cvtps_pi32(a) _mm_cvt_ps2pi(a) + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 8-bit integers, and store the results in lower 4 elements of dst. +// Note: this intrinsic will generate 0x7F, rather than 0x80, for input values +// between 0x7F and 0x7FFFFFFF. +// +// FOR j := 0 to 3 +// i := 8*j +// k := 32*j +// IF a[k+31:k] >= FP32(0x7F) && a[k+31:k] <= FP32(0x7FFFFFFF) +// dst[i+7:i] := 0x7F +// ELSE +// dst[i+7:i] := Convert_FP32_To_Int8(a[k+31:k]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pi8 +FORCE_INLINE __m64 _mm_cvtps_pi8(__m128 a) +{ + const __m128 i8Min = _mm_set_ps1((float) INT8_MIN); + const __m128 i8Max = _mm_set_ps1((float) INT8_MAX); + const __m128 i32Max = _mm_set_ps1((float) INT32_MAX); + const __m128i maxMask = _mm_castps_si128( + _mm_and_ps(_mm_cmpge_ps(a, i8Max), _mm_cmple_ps(a, i32Max))); + const __m128i betweenMask = _mm_castps_si128( + _mm_and_ps(_mm_cmpgt_ps(a, i8Min), _mm_cmplt_ps(a, i8Max))); + const __m128i minMask = _mm_cmpeq_epi32(_mm_or_si128(maxMask, betweenMask), + _mm_setzero_si128()); + __m128i max = _mm_and_si128(maxMask, _mm_set1_epi32(INT8_MAX)); + __m128i min = _mm_and_si128(minMask, _mm_set1_epi32(INT8_MIN)); + __m128i cvt = _mm_and_si128(betweenMask, _mm_cvtps_epi32(a)); + __m128i res32 = _mm_or_si128(_mm_or_si128(max, min), cvt); + int16x4_t res16 = vmovn_s32(vreinterpretq_s32_m128i(res32)); + int8x8_t res8 = vmovn_s16(vcombine_s16(res16, res16)); + uint32_t bitMask[2] = {0xFFFFFFFF, 0}; + int8x8_t mask = vreinterpret_s8_u32(vld1_u32(bitMask)); + + return vreinterpret_m64_s8(vorr_s8(vand_s8(mask, res8), vdup_n_s8(0))); +} + +// Convert packed unsigned 16-bit integers in a to packed single-precision +// (32-bit) floating-point elements, and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// m := j*32 +// dst[m+31:m] := Convert_UInt16_To_FP32(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu16_ps +FORCE_INLINE __m128 _mm_cvtpu16_ps(__m64 a) +{ + return vreinterpretq_m128_f32( + vcvtq_f32_u32(vmovl_u16(vreinterpret_u16_m64(a)))); +} + +// Convert the lower packed unsigned 8-bit integers in a to packed +// single-precision (32-bit) floating-point elements, and store the results in +// dst. +// +// FOR j := 0 to 3 +// i := j*8 +// m := j*32 +// dst[m+31:m] := Convert_UInt8_To_FP32(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu8_ps +FORCE_INLINE __m128 _mm_cvtpu8_ps(__m64 a) +{ + return vreinterpretq_m128_f32(vcvtq_f32_u32( + vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_m64(a)))))); +} + +// Convert the signed 32-bit integer b to a single-precision (32-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper 3 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_ss +#define _mm_cvtsi32_ss(a, b) _mm_cvt_si2ss(a, b) + +// Convert the signed 64-bit integer b to a single-precision (32-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper 3 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int64_To_FP32(b[63:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_ss +FORCE_INLINE __m128 _mm_cvtsi64_ss(__m128 a, int64_t b) +{ + return vreinterpretq_m128_f32( + vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0)); +} + +// Copy the lower single-precision (32-bit) floating-point element of a to dst. +// +// dst[31:0] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_f32 +FORCE_INLINE float _mm_cvtss_f32(__m128 a) +{ + return vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); +} + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer, and store the result in dst. +// +// dst[31:0] := Convert_FP32_To_Int32(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si32 +#define _mm_cvtss_si32(a) _mm_cvt_ss2si(a) + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 64-bit integer, and store the result in dst. +// +// dst[63:0] := Convert_FP32_To_Int64(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si64 +FORCE_INLINE int64_t _mm_cvtss_si64(__m128 a) +{ +#if defined(__aarch64__) + return (int64_t) vgetq_lane_f32(vrndiq_f32(vreinterpretq_f32_m128(a)), 0); +#else + float32_t data = vgetq_lane_f32( + vreinterpretq_f32_m128(_mm_round_ps(a, _MM_FROUND_CUR_DIRECTION)), 0); + return (int64_t) data; +#endif +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers with truncation, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ps2pi +FORCE_INLINE __m64 _mm_cvtt_ps2pi(__m128 a) +{ + return vreinterpret_m64_s32( + vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)))); +} + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer with truncation, and store the result in dst. +// +// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ss2si +FORCE_INLINE int _mm_cvtt_ss2si(__m128 a) +{ + return vgetq_lane_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)), 0); +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers with truncation, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttps_pi32 +#define _mm_cvttps_pi32(a) _mm_cvtt_ps2pi(a) + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer with truncation, and store the result in dst. +// +// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si32 +#define _mm_cvttss_si32(a) _mm_cvtt_ss2si(a) + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 64-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP32_To_Int64_Truncate(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si64 +FORCE_INLINE int64_t _mm_cvttss_si64(__m128 a) +{ + return (int64_t) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); +} + +// Divides the four single-precision, floating-point values of a and b. +// +// r0 := a0 / b0 +// r1 := a1 / b1 +// r2 := a2 / b2 +// r3 := a3 / b3 +// +// https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx +FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) && !SSE2NEON_PRECISE_DIV + return vreinterpretq_m128_f32( + vdivq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(b)); + recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b))); +#if SSE2NEON_PRECISE_DIV + // Additional Netwon-Raphson iteration for accuracy + recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b))); +#endif + return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(a), recip)); +#endif +} + +// Divides the scalar single-precision floating point value of a by b. +// https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx +FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b) +{ + float32_t value = + vgetq_lane_f32(vreinterpretq_f32_m128(_mm_div_ps(a, b)), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0)); +} + +// Extract a 16-bit integer from a, selected with imm8, and store the result in +// the lower element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_extract_pi16 +#define _mm_extract_pi16(a, imm) \ + (int32_t) vget_lane_u16(vreinterpret_u16_m64(a), (imm)) + +// Free aligned memory that was allocated with _mm_malloc. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_free +FORCE_INLINE void _mm_free(void *addr) +{ + free(addr); +} + +// Macro: Get the flush zero bits from the MXCSR control and status register. +// The flush zero may contain any of the following flags: _MM_FLUSH_ZERO_ON or +// _MM_FLUSH_ZERO_OFF +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_FLUSH_ZERO_MODE +FORCE_INLINE unsigned int _sse2neon_mm_get_flush_zero_mode() +{ + union { + fpcr_bitfield field; +#if defined(__aarch64__) + uint64_t value; +#else + uint32_t value; +#endif + } r; + +#if defined(__aarch64__) + asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */ +#else + asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */ +#endif + + return r.field.bit24 ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF; +} + +// Macro: Get the rounding mode bits from the MXCSR control and status register. +// The rounding mode may contain any of the following flags: _MM_ROUND_NEAREST, +// _MM_ROUND_DOWN, _MM_ROUND_UP, _MM_ROUND_TOWARD_ZERO +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_ROUNDING_MODE +FORCE_INLINE unsigned int _MM_GET_ROUNDING_MODE() +{ + union { + fpcr_bitfield field; +#if defined(__aarch64__) + uint64_t value; +#else + uint32_t value; +#endif + } r; + +#if defined(__aarch64__) + asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */ +#else + asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */ +#endif + + if (r.field.bit22) { + return r.field.bit23 ? _MM_ROUND_TOWARD_ZERO : _MM_ROUND_UP; + } else { + return r.field.bit23 ? _MM_ROUND_DOWN : _MM_ROUND_NEAREST; + } +} + +// Copy a to dst, and insert the 16-bit integer i into dst at the location +// specified by imm8. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_insert_pi16 +#define _mm_insert_pi16(a, b, imm) \ + __extension__({ \ + vreinterpret_m64_s16( \ + vset_lane_s16((b), vreinterpret_s16_m64(a), (imm))); \ + }) + +// Loads four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx +FORCE_INLINE __m128 _mm_load_ps(const float *p) +{ + return vreinterpretq_m128_f32(vld1q_f32(p)); +} + +// Load a single-precision (32-bit) floating-point element from memory into all +// elements of dst. +// +// dst[31:0] := MEM[mem_addr+31:mem_addr] +// dst[63:32] := MEM[mem_addr+31:mem_addr] +// dst[95:64] := MEM[mem_addr+31:mem_addr] +// dst[127:96] := MEM[mem_addr+31:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_ps1 +#define _mm_load_ps1 _mm_load1_ps + +// Loads an single - precision, floating - point value into the low word and +// clears the upper three words. +// https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_load_ss(const float *p) +{ + return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0)); +} + +// Loads a single single-precision, floating-point value, copying it into all +// four words +// https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx +FORCE_INLINE __m128 _mm_load1_ps(const float *p) +{ + return vreinterpretq_m128_f32(vld1q_dup_f32(p)); +} + +// Sets the upper two single-precision, floating-point values with 64 +// bits of data loaded from the address p; the lower two values are passed +// through from a. +// +// r0 := a0 +// r1 := a1 +// r2 := *p0 +// r3 := *p1 +// +// https://msdn.microsoft.com/en-us/library/w92wta0x(v%3dvs.100).aspx +FORCE_INLINE __m128 _mm_loadh_pi(__m128 a, __m64 const *p) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vget_low_f32(a), vld1_f32((const float32_t *) p))); +} + +// Sets the lower two single-precision, floating-point values with 64 +// bits of data loaded from the address p; the upper two values are passed +// through from a. +// +// Return Value +// r0 := *p0 +// r1 := *p1 +// r2 := a2 +// r3 := a3 +// +// https://msdn.microsoft.com/en-us/library/s57cyak2(v=vs.100).aspx +FORCE_INLINE __m128 _mm_loadl_pi(__m128 a, __m64 const *p) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vld1_f32((const float32_t *) p), vget_high_f32(a))); +} + +// Load 4 single-precision (32-bit) floating-point elements from memory into dst +// in reverse order. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// dst[31:0] := MEM[mem_addr+127:mem_addr+96] +// dst[63:32] := MEM[mem_addr+95:mem_addr+64] +// dst[95:64] := MEM[mem_addr+63:mem_addr+32] +// dst[127:96] := MEM[mem_addr+31:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_ps +FORCE_INLINE __m128 _mm_loadr_ps(const float *p) +{ + float32x4_t v = vrev64q_f32(vld1q_f32(p)); + return vreinterpretq_m128_f32(vextq_f32(v, v, 2)); +} + +// Loads four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_loadu_ps(const float *p) +{ + // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are + // equivalent for neon + return vreinterpretq_m128_f32(vld1q_f32(p)); +} + +// Load unaligned 16-bit integer from memory into the first element of dst. +// +// dst[15:0] := MEM[mem_addr+15:mem_addr] +// dst[MAX:16] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si16 +FORCE_INLINE __m128i _mm_loadu_si16(const void *p) +{ + return vreinterpretq_m128i_s16( + vsetq_lane_s16(*(const int16_t *) p, vdupq_n_s16(0), 0)); +} + +// Load unaligned 64-bit integer from memory into the first element of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[MAX:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si64 +FORCE_INLINE __m128i _mm_loadu_si64(const void *p) +{ + return vreinterpretq_m128i_s64( + vcombine_s64(vld1_s64((const int64_t *) p), vdup_n_s64(0))); +} + +// Allocate aligned blocks of memory. +// https://software.intel.com/en-us/ +// cpp-compiler-developer-guide-and-reference-allocating-and-freeing-aligned-memory-blocks +FORCE_INLINE void *_mm_malloc(size_t size, size_t align) +{ + void *ptr; + if (align == 1) + return malloc(size); + if (align == 2 || (sizeof(void *) == 8 && align == 4)) + align = sizeof(void *); + if (!posix_memalign(&ptr, align, size)) + return ptr; + return NULL; +} + +// Conditionally store 8-bit integer elements from a into memory using mask +// (elements are not stored when the highest bit is not set in the corresponding +// element) and a non-temporal memory hint. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskmove_si64 +FORCE_INLINE void _mm_maskmove_si64(__m64 a, __m64 mask, char *mem_addr) +{ + int8x8_t shr_mask = vshr_n_s8(vreinterpret_s8_m64(mask), 7); + __m128 b = _mm_load_ps((const float *) mem_addr); + int8x8_t masked = + vbsl_s8(vreinterpret_u8_s8(shr_mask), vreinterpret_s8_m64(a), + vreinterpret_s8_u64(vget_low_u64(vreinterpretq_u64_m128(b)))); + vst1_s8((int8_t *) mem_addr, masked); +} + +// Conditionally store 8-bit integer elements from a into memory using mask +// (elements are not stored when the highest bit is not set in the corresponding +// element) and a non-temporal memory hint. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_maskmovq +#define _m_maskmovq(a, mask, mem_addr) _mm_maskmove_si64(a, mask, mem_addr) + +// Compare packed signed 16-bit integers in a and b, and store packed maximum +// values in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16 +FORCE_INLINE __m64 _mm_max_pi16(__m64 a, __m64 b) +{ + return vreinterpret_m64_s16( + vmax_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b))); +} + +// Computes the maximums of the four single-precision, floating-point values of +// a and b. +// https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx +FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b) +{ +#if SSE2NEON_PRECISE_MINMAX + float32x4_t _a = vreinterpretq_f32_m128(a); + float32x4_t _b = vreinterpretq_f32_m128(b); + return vbslq_f32(vcltq_f32(_b, _a), _a, _b); +#else + return vreinterpretq_m128_f32( + vmaxq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#endif +} + +// Compare packed unsigned 8-bit integers in a and b, and store packed maximum +// values in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8 +FORCE_INLINE __m64 _mm_max_pu8(__m64 a, __m64 b) +{ + return vreinterpret_m64_u8( + vmax_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); +} + +// Computes the maximum of the two lower scalar single-precision floating point +// values of a and b. +// https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b) +{ + float32_t value = vgetq_lane_f32(_mm_max_ps(a, b), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0)); +} + +// Compare packed signed 16-bit integers in a and b, and store packed minimum +// values in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16 +FORCE_INLINE __m64 _mm_min_pi16(__m64 a, __m64 b) +{ + return vreinterpret_m64_s16( + vmin_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b))); +} + +// Computes the minima of the four single-precision, floating-point values of a +// and b. +// https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b) +{ +#if SSE2NEON_PRECISE_MINMAX + float32x4_t _a = vreinterpretq_f32_m128(a); + float32x4_t _b = vreinterpretq_f32_m128(b); + return vbslq_f32(vcltq_f32(_a, _b), _a, _b); +#else + return vreinterpretq_m128_f32( + vminq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#endif +} + +// Compare packed unsigned 8-bit integers in a and b, and store packed minimum +// values in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8 +FORCE_INLINE __m64 _mm_min_pu8(__m64 a, __m64 b) +{ + return vreinterpret_m64_u8( + vmin_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); +} + +// Computes the minimum of the two lower scalar single-precision floating point +// values of a and b. +// https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx +FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b) +{ + float32_t value = vgetq_lane_f32(_mm_min_ps(a, b), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0)); +} + +// Sets the low word to the single-precision, floating-point value of b +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/35hdzazd(v=vs.100) +FORCE_INLINE __m128 _mm_move_ss(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), 0), + vreinterpretq_f32_m128(a), 0)); +} + +// Moves the upper two values of B into the lower two values of A. +// +// r3 := a3 +// r2 := a2 +// r1 := b3 +// r0 := b2 +FORCE_INLINE __m128 _mm_movehl_ps(__m128 __A, __m128 __B) +{ + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(__A)); + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(__B)); + return vreinterpretq_m128_f32(vcombine_f32(b32, a32)); +} + +// Moves the lower two values of B into the upper two values of A. +// +// r3 := b1 +// r2 := b0 +// r1 := a1 +// r0 := a0 +FORCE_INLINE __m128 _mm_movelh_ps(__m128 __A, __m128 __B) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(__A)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(__B)); + return vreinterpretq_m128_f32(vcombine_f32(a10, b10)); +} + +// Create mask from the most significant bit of each 8-bit element in a, and +// store the result in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_pi8 +FORCE_INLINE int _mm_movemask_pi8(__m64 a) +{ + uint8x8_t input = vreinterpret_u8_m64(a); +#if defined(__aarch64__) + static const int8x8_t shift = {0, 1, 2, 3, 4, 5, 6, 7}; + uint8x8_t tmp = vshr_n_u8(input, 7); + return vaddv_u8(vshl_u8(tmp, shift)); +#else + // Refer the implementation of `_mm_movemask_epi8` + uint16x4_t high_bits = vreinterpret_u16_u8(vshr_n_u8(input, 7)); + uint32x2_t paired16 = + vreinterpret_u32_u16(vsra_n_u16(high_bits, high_bits, 7)); + uint8x8_t paired32 = + vreinterpret_u8_u32(vsra_n_u32(paired16, paired16, 14)); + return vget_lane_u8(paired32, 0) | ((int) vget_lane_u8(paired32, 4) << 4); +#endif +} + +// NEON does not provide this method +// Creates a 4-bit mask from the most significant bits of the four +// single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx +FORCE_INLINE int _mm_movemask_ps(__m128 a) +{ + uint32x4_t input = vreinterpretq_u32_m128(a); +#if defined(__aarch64__) + static const int32x4_t shift = {0, 1, 2, 3}; + uint32x4_t tmp = vshrq_n_u32(input, 31); + return vaddvq_u32(vshlq_u32(tmp, shift)); +#else + // Uses the exact same method as _mm_movemask_epi8, see that for details. + // Shift out everything but the sign bits with a 32-bit unsigned shift + // right. + uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(input, 31)); + // Merge the two pairs together with a 64-bit unsigned shift right + add. + uint8x16_t paired = + vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31)); + // Extract the result. + return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2); +#endif +} + +// Multiplies the four single-precision, floating-point values of a and b. +// +// r0 := a0 * b0 +// r1 := a1 * b1 +// r2 := a2 * b2 +// r3 := a3 * b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx +FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vmulq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Multiply the lower single-precision (32-bit) floating-point element in a and +// b, store the result in the lower element of dst, and copy the upper 3 packed +// elements from a to the upper elements of dst. +// +// dst[31:0] := a[31:0] * b[31:0] +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_ss +FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_mul_ps(a, b)); +} + +// Multiply the packed unsigned 16-bit integers in a and b, producing +// intermediate 32-bit integers, and store the high 16 bits of the intermediate +// integers in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_pu16 +FORCE_INLINE __m64 _mm_mulhi_pu16(__m64 a, __m64 b) +{ + return vreinterpret_m64_u16(vshrn_n_u32( + vmull_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)), 16)); +} + +// Computes the bitwise OR of the four single-precision, floating-point values +// of a and b. +// https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx +FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); +} + +// Average packed unsigned 8-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgb +#define _m_pavgb(a, b) _mm_avg_pu8(a, b) + +// Average packed unsigned 16-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgw +#define _m_pavgw(a, b) _mm_avg_pu16(a, b) + +// Extract a 16-bit integer from a, selected with imm8, and store the result in +// the lower element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pextrw +#define _m_pextrw(a, imm) _mm_extract_pi16(a, imm) + +// Copy a to dst, and insert the 16-bit integer i into dst at the location +// specified by imm8. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=m_pinsrw +#define _m_pinsrw(a, i, imm) _mm_insert_pi16(a, i, imm) + +// Compare packed signed 16-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxsw +#define _m_pmaxsw(a, b) _mm_max_pi16(a, b) + +// Compare packed unsigned 8-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmaxub +#define _m_pmaxub(a, b) _mm_max_pu8(a, b) + +// Compare packed signed 16-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminsw +#define _m_pminsw(a, b) _mm_min_pi16(a, b) + +// Compare packed unsigned 8-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pminub +#define _m_pminub(a, b) _mm_min_pu8(a, b) + +// Create mask from the most significant bit of each 8-bit element in a, and +// store the result in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmovmskb +#define _m_pmovmskb(a) _mm_movemask_pi8(a) + +// Multiply the packed unsigned 16-bit integers in a and b, producing +// intermediate 32-bit integers, and store the high 16 bits of the intermediate +// integers in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmulhuw +#define _m_pmulhuw(a, b) _mm_mulhi_pu16(a, b) + +// Loads one cache line of data from address p to a location closer to the +// processor. https://msdn.microsoft.com/en-us/library/84szxsww(v=vs.100).aspx +FORCE_INLINE void _mm_prefetch(const void *p, int i) +{ + (void) i; + __builtin_prefetch(p); +} + +// Compute the absolute differences of packed unsigned 8-bit integers in a and +// b, then horizontally sum each consecutive 8 differences to produce four +// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low +// 16 bits of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=m_psadbw +#define _m_psadbw(a, b) _mm_sad_pu8(a, b) + +// Shuffle 16-bit integers in a using the control in imm8, and store the results +// in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pshufw +#define _m_pshufw(a, imm) _mm_shuffle_pi16(a, imm) + +// Compute the approximate reciprocal of packed single-precision (32-bit) +// floating-point elements in a, and store the results in dst. The maximum +// relative error for this approximation is less than 1.5*2^-12. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ps +FORCE_INLINE __m128 _mm_rcp_ps(__m128 in) +{ + float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in)); + recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in))); +#if SSE2NEON_PRECISE_DIV + // Additional Netwon-Raphson iteration for accuracy + recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in))); +#endif + return vreinterpretq_m128_f32(recip); +} + +// Compute the approximate reciprocal of the lower single-precision (32-bit) +// floating-point element in a, store the result in the lower element of dst, +// and copy the upper 3 packed elements from a to the upper elements of dst. The +// maximum relative error for this approximation is less than 1.5*2^-12. +// +// dst[31:0] := (1.0 / a[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ss +FORCE_INLINE __m128 _mm_rcp_ss(__m128 a) +{ + return _mm_move_ss(a, _mm_rcp_ps(a)); +} + +// Computes the approximations of the reciprocal square roots of the four +// single-precision floating point values of in. +// The current precision is 1% error. +// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx +FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in) +{ + float32x4_t out = vrsqrteq_f32(vreinterpretq_f32_m128(in)); +#if SSE2NEON_PRECISE_SQRT + // Additional Netwon-Raphson iteration for accuracy + out = vmulq_f32( + out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out)); + out = vmulq_f32( + out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out)); +#endif + return vreinterpretq_m128_f32(out); +} + +// Compute the approximate reciprocal square root of the lower single-precision +// (32-bit) floating-point element in a, store the result in the lower element +// of dst, and copy the upper 3 packed elements from a to the upper elements of +// dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt_ss +FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in) +{ + return vsetq_lane_f32(vgetq_lane_f32(_mm_rsqrt_ps(in), 0), in, 0); +} + +// Compute the absolute differences of packed unsigned 8-bit integers in a and +// b, then horizontally sum each consecutive 8 differences to produce four +// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low +// 16 bits of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_pu8 +FORCE_INLINE __m64 _mm_sad_pu8(__m64 a, __m64 b) +{ + uint64x1_t t = vpaddl_u32(vpaddl_u16( + vpaddl_u8(vabd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))))); + return vreinterpret_m64_u16( + vset_lane_u16(vget_lane_u64(t, 0), vdup_n_u16(0), 0)); +} + +// Macro: Set the flush zero bits of the MXCSR control and status register to +// the value in unsigned 32-bit integer a. The flush zero may contain any of the +// following flags: _MM_FLUSH_ZERO_ON or _MM_FLUSH_ZERO_OFF +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_FLUSH_ZERO_MODE +FORCE_INLINE void _sse2neon_mm_set_flush_zero_mode(unsigned int flag) +{ + // AArch32 Advanced SIMD arithmetic always uses the Flush-to-zero setting, + // regardless of the value of the FZ bit. + union { + fpcr_bitfield field; +#if defined(__aarch64__) + uint64_t value; +#else + uint32_t value; +#endif + } r; + +#if defined(__aarch64__) + asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */ +#else + asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */ +#endif + + r.field.bit24 = (flag & _MM_FLUSH_ZERO_MASK) == _MM_FLUSH_ZERO_ON; + +#if defined(__aarch64__) + asm volatile("msr FPCR, %0" ::"r"(r)); /* write */ +#else + asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */ +#endif +} + +// Sets the four single-precision, floating-point values to the four inputs. +// https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x) +{ + float ALIGN_STRUCT(16) data[4] = {x, y, z, w}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +} + +// Sets the four single-precision, floating-point values to w. +// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set_ps1(float _w) +{ + return vreinterpretq_m128_f32(vdupq_n_f32(_w)); +} + +// Macro: Set the rounding mode bits of the MXCSR control and status register to +// the value in unsigned 32-bit integer a. The rounding mode may contain any of +// the following flags: _MM_ROUND_NEAREST, _MM_ROUND_DOWN, _MM_ROUND_UP, +// _MM_ROUND_TOWARD_ZERO +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_ROUNDING_MODE +FORCE_INLINE void _MM_SET_ROUNDING_MODE(int rounding) +{ + union { + fpcr_bitfield field; +#if defined(__aarch64__) + uint64_t value; +#else + uint32_t value; +#endif + } r; + +#if defined(__aarch64__) + asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */ +#else + asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */ +#endif + + switch (rounding) { + case _MM_ROUND_TOWARD_ZERO: + r.field.bit22 = 1; + r.field.bit23 = 1; + break; + case _MM_ROUND_DOWN: + r.field.bit22 = 0; + r.field.bit23 = 1; + break; + case _MM_ROUND_UP: + r.field.bit22 = 1; + r.field.bit23 = 0; + break; + default: //_MM_ROUND_NEAREST + r.field.bit22 = 0; + r.field.bit23 = 0; + } + +#if defined(__aarch64__) + asm volatile("msr FPCR, %0" ::"r"(r)); /* write */ +#else + asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */ +#endif +} + +// Copy single-precision (32-bit) floating-point element a to the lower element +// of dst, and zero the upper 3 elements. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_ss +FORCE_INLINE __m128 _mm_set_ss(float a) +{ + float ALIGN_STRUCT(16) data[4] = {a, 0, 0, 0}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +} + +// Sets the four single-precision, floating-point values to w. +// +// r0 := r1 := r2 := r3 := w +// +// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set1_ps(float _w) +{ + return vreinterpretq_m128_f32(vdupq_n_f32(_w)); +} + +FORCE_INLINE void _mm_setcsr(unsigned int a) +{ + _MM_SET_ROUNDING_MODE(a); +} + +// Sets the four single-precision, floating-point values to the four inputs in +// reverse order. +// https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx +FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x) +{ + float ALIGN_STRUCT(16) data[4] = {w, z, y, x}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +} + +// Clears the four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_setzero_ps(void) +{ + return vreinterpretq_m128_f32(vdupq_n_f32(0)); +} + +// Shuffle 16-bit integers in a using the control in imm8, and store the results +// in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pi16 +#if __has_builtin(__builtin_shufflevector) +#define _mm_shuffle_pi16(a, imm) \ + __extension__({ \ + vreinterpret_m64_s16(__builtin_shufflevector( \ + vreinterpret_s16_m64(a), vreinterpret_s16_m64(a), (imm & 0x3), \ + ((imm >> 2) & 0x3), ((imm >> 4) & 0x3), ((imm >> 6) & 0x3))); \ + }) +#else +#define _mm_shuffle_pi16(a, imm) \ + __extension__({ \ + int16x4_t ret; \ + ret = \ + vmov_n_s16(vget_lane_s16(vreinterpret_s16_m64(a), (imm) & (0x3))); \ + ret = vset_lane_s16( \ + vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 2) & 0x3), ret, \ + 1); \ + ret = vset_lane_s16( \ + vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 4) & 0x3), ret, \ + 2); \ + ret = vset_lane_s16( \ + vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 6) & 0x3), ret, \ + 3); \ + vreinterpret_m64_s16(ret); \ + }) +#endif + +// Guarantees that every preceding store is globally visible before any +// subsequent store. +// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx +FORCE_INLINE void _mm_sfence(void) +{ + __sync_synchronize(); +} + +// FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255) +// int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shuffle_ps(a, b, imm) \ + __extension__({ \ + float32x4_t _input1 = vreinterpretq_f32_m128(a); \ + float32x4_t _input2 = vreinterpretq_f32_m128(b); \ + float32x4_t _shuf = __builtin_shufflevector( \ + _input1, _input2, (imm) & (0x3), ((imm) >> 2) & 0x3, \ + (((imm) >> 4) & 0x3) + 4, (((imm) >> 6) & 0x3) + 4); \ + vreinterpretq_m128_f32(_shuf); \ + }) +#else // generic +#define _mm_shuffle_ps(a, b, imm) \ + __extension__({ \ + __m128 ret; \ + switch (imm) { \ + case _MM_SHUFFLE(1, 0, 3, 2): \ + ret = _mm_shuffle_ps_1032((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 3, 0, 1): \ + ret = _mm_shuffle_ps_2301((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 3, 2, 1): \ + ret = _mm_shuffle_ps_0321((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 1, 0, 3): \ + ret = _mm_shuffle_ps_2103((a), (b)); \ + break; \ + case _MM_SHUFFLE(1, 0, 1, 0): \ + ret = _mm_movelh_ps((a), (b)); \ + break; \ + case _MM_SHUFFLE(1, 0, 0, 1): \ + ret = _mm_shuffle_ps_1001((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 1, 0, 1): \ + ret = _mm_shuffle_ps_0101((a), (b)); \ + break; \ + case _MM_SHUFFLE(3, 2, 1, 0): \ + ret = _mm_shuffle_ps_3210((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 0, 1, 1): \ + ret = _mm_shuffle_ps_0011((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 0, 2, 2): \ + ret = _mm_shuffle_ps_0022((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 2, 0, 0): \ + ret = _mm_shuffle_ps_2200((a), (b)); \ + break; \ + case _MM_SHUFFLE(3, 2, 0, 2): \ + ret = _mm_shuffle_ps_3202((a), (b)); \ + break; \ + case _MM_SHUFFLE(3, 2, 3, 2): \ + ret = _mm_movehl_ps((b), (a)); \ + break; \ + case _MM_SHUFFLE(1, 1, 3, 3): \ + ret = _mm_shuffle_ps_1133((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 0, 1, 0): \ + ret = _mm_shuffle_ps_2010((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 0, 0, 1): \ + ret = _mm_shuffle_ps_2001((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 0, 3, 2): \ + ret = _mm_shuffle_ps_2032((a), (b)); \ + break; \ + default: \ + ret = _mm_shuffle_ps_default((a), (b), (imm)); \ + break; \ + } \ + ret; \ + }) +#endif + +// Computes the approximations of square roots of the four single-precision, +// floating-point values of a. First computes reciprocal square roots and then +// reciprocals of the four values. +// +// r0 := sqrt(a0) +// r1 := sqrt(a1) +// r2 := sqrt(a2) +// r3 := sqrt(a3) +// +// https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in) +{ +#if SSE2NEON_PRECISE_SQRT + float32x4_t recip = vrsqrteq_f32(vreinterpretq_f32_m128(in)); + + // Test for vrsqrteq_f32(0) -> positive infinity case. + // Change to zero, so that s * 1/sqrt(s) result is zero too. + const uint32x4_t pos_inf = vdupq_n_u32(0x7F800000); + const uint32x4_t div_by_zero = + vceqq_u32(pos_inf, vreinterpretq_u32_f32(recip)); + recip = vreinterpretq_f32_u32( + vandq_u32(vmvnq_u32(div_by_zero), vreinterpretq_u32_f32(recip))); + + // Additional Netwon-Raphson iteration for accuracy + recip = vmulq_f32( + vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)), + recip); + recip = vmulq_f32( + vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)), + recip); + + // sqrt(s) = s * 1/sqrt(s) + return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(in), recip)); +#elif defined(__aarch64__) + return vreinterpretq_m128_f32(vsqrtq_f32(vreinterpretq_f32_m128(in))); +#else + float32x4_t recipsq = vrsqrteq_f32(vreinterpretq_f32_m128(in)); + float32x4_t sq = vrecpeq_f32(recipsq); + return vreinterpretq_m128_f32(sq); +#endif +} + +// Computes the approximation of the square root of the scalar single-precision +// floating point value of in. +// https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in) +{ + float32_t value = + vgetq_lane_f32(vreinterpretq_f32_m128(_mm_sqrt_ps(in)), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(in), 0)); +} + +// Stores four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx +FORCE_INLINE void _mm_store_ps(float *p, __m128 a) +{ + vst1q_f32(p, vreinterpretq_f32_m128(a)); +} + +// Store the lower single-precision (32-bit) floating-point element from a into +// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte +// boundary or a general-protection exception may be generated. +// +// MEM[mem_addr+31:mem_addr] := a[31:0] +// MEM[mem_addr+63:mem_addr+32] := a[31:0] +// MEM[mem_addr+95:mem_addr+64] := a[31:0] +// MEM[mem_addr+127:mem_addr+96] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_ps1 +FORCE_INLINE void _mm_store_ps1(float *p, __m128 a) +{ + float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + vst1q_f32(p, vdupq_n_f32(a0)); +} + +// Stores the lower single - precision, floating - point value. +// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx +FORCE_INLINE void _mm_store_ss(float *p, __m128 a) +{ + vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0); +} + +// Store the lower single-precision (32-bit) floating-point element from a into +// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte +// boundary or a general-protection exception may be generated. +// +// MEM[mem_addr+31:mem_addr] := a[31:0] +// MEM[mem_addr+63:mem_addr+32] := a[31:0] +// MEM[mem_addr+95:mem_addr+64] := a[31:0] +// MEM[mem_addr+127:mem_addr+96] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store1_ps +#define _mm_store1_ps _mm_store_ps1 + +// Stores the upper two single-precision, floating-point values of a to the +// address p. +// +// *p0 := a2 +// *p1 := a3 +// +// https://msdn.microsoft.com/en-us/library/a7525fs8(v%3dvs.90).aspx +FORCE_INLINE void _mm_storeh_pi(__m64 *p, __m128 a) +{ + *p = vreinterpret_m64_f32(vget_high_f32(a)); +} + +// Stores the lower two single-precision floating point values of a to the +// address p. +// +// *p0 := a0 +// *p1 := a1 +// +// https://msdn.microsoft.com/en-us/library/h54t98ks(v=vs.90).aspx +FORCE_INLINE void _mm_storel_pi(__m64 *p, __m128 a) +{ + *p = vreinterpret_m64_f32(vget_low_f32(a)); +} + +// Store 4 single-precision (32-bit) floating-point elements from a into memory +// in reverse order. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// MEM[mem_addr+31:mem_addr] := a[127:96] +// MEM[mem_addr+63:mem_addr+32] := a[95:64] +// MEM[mem_addr+95:mem_addr+64] := a[63:32] +// MEM[mem_addr+127:mem_addr+96] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_ps +FORCE_INLINE void _mm_storer_ps(float *p, __m128 a) +{ + float32x4_t tmp = vrev64q_f32(vreinterpretq_f32_m128(a)); + float32x4_t rev = vextq_f32(tmp, tmp, 2); + vst1q_f32(p, rev); +} + +// Stores four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx +FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a) +{ + vst1q_f32(p, vreinterpretq_f32_m128(a)); +} + +// Stores 16-bits of integer data a at the address p. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si16 +FORCE_INLINE void _mm_storeu_si16(void *p, __m128i a) +{ + vst1q_lane_s16((int16_t *) p, vreinterpretq_s16_m128i(a), 0); +} + +// Stores 64-bits of integer data a at the address p. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si64 +FORCE_INLINE void _mm_storeu_si64(void *p, __m128i a) +{ + vst1q_lane_s64((int64_t *) p, vreinterpretq_s64_m128i(a), 0); +} + +// Store 64-bits of integer data from a into memory using a non-temporal memory +// hint. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_pi +FORCE_INLINE void _mm_stream_pi(__m64 *p, __m64 a) +{ + vst1_s64((int64_t *) p, vreinterpret_s64_m64(a)); +} + +// Store 128-bits (composed of 4 packed single-precision (32-bit) floating- +// point elements) from a into memory using a non-temporal memory hint. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_ps +FORCE_INLINE void _mm_stream_ps(float *p, __m128 a) +{ +#if __has_builtin(__builtin_nontemporal_store) + __builtin_nontemporal_store(a, (float32x4_t *) p); +#else + vst1q_f32(p, vreinterpretq_f32_m128(a)); +#endif +} + +// Subtracts the four single-precision, floating-point values of a and b. +// +// r0 := a0 - b0 +// r1 := a1 - b1 +// r2 := a2 - b2 +// r3 := a3 - b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vsubq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Subtract the lower single-precision (32-bit) floating-point element in b from +// the lower single-precision (32-bit) floating-point element in a, store the +// result in the lower element of dst, and copy the upper 3 packed elements from +// a to the upper elements of dst. +// +// dst[31:0] := a[31:0] - b[31:0] +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_ss +FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_sub_ps(a, b)); +} + +// Macro: Transpose the 4x4 matrix formed by the 4 rows of single-precision +// (32-bit) floating-point elements in row0, row1, row2, and row3, and store the +// transposed matrix in these vectors (row0 now contains column 0, etc.). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=MM_TRANSPOSE4_PS +#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \ + do { \ + float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \ + float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \ + row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \ + vget_low_f32(ROW23.val[0])); \ + row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \ + vget_low_f32(ROW23.val[1])); \ + row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \ + vget_high_f32(ROW23.val[0])); \ + row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \ + vget_high_f32(ROW23.val[1])); \ + } while (0) + +// according to the documentation, these intrinsics behave the same as the +// non-'u' versions. We'll just alias them here. +#define _mm_ucomieq_ss _mm_comieq_ss +#define _mm_ucomige_ss _mm_comige_ss +#define _mm_ucomigt_ss _mm_comigt_ss +#define _mm_ucomile_ss _mm_comile_ss +#define _mm_ucomilt_ss _mm_comilt_ss +#define _mm_ucomineq_ss _mm_comineq_ss + +// Return vector of type __m128i with undefined elements. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_undefined_si128 +FORCE_INLINE __m128i _mm_undefined_si128(void) +{ +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + __m128i a; + return a; +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif +} + +// Return vector of type __m128 with undefined elements. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ps +FORCE_INLINE __m128 _mm_undefined_ps(void) +{ +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + __m128 a; + return a; +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif +} + +// Selects and interleaves the upper two single-precision, floating-point values +// from a and b. +// +// r0 := a2 +// r1 := b2 +// r2 := a3 +// r3 := b3 +// +// https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vzip2q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x2_t a1 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32x2_t b1 = vget_high_f32(vreinterpretq_f32_m128(b)); + float32x2x2_t result = vzip_f32(a1, b1); + return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1])); +#endif +} + +// Selects and interleaves the lower two single-precision, floating-point values +// from a and b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// +// https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vzip1q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x2_t a1 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t b1 = vget_low_f32(vreinterpretq_f32_m128(b)); + float32x2x2_t result = vzip_f32(a1, b1); + return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1])); +#endif +} + +// Computes bitwise EXOR (exclusive-or) of the four single-precision, +// floating-point values of a and b. +// https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx +FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); +} + +/* SSE2 */ + +// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or +// unsigned 16-bit integers in b. +// https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or +// unsigned 32-bit integers in b. +// +// r0 := a0 + b0 +// r1 := a1 + b1 +// r2 := a2 + b2 +// r3 := a3 + b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vaddq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Adds the 4 signed or unsigned 64-bit integers in a to the 4 signed or +// unsigned 32-bit integers in b. +// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi64(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s64( + vaddq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b))); +} + +// Adds the 16 signed or unsigned 8-bit integers in a to the 16 signed or +// unsigned 8-bit integers in b. +// https://technet.microsoft.com/en-us/subscriptions/yc7tcyzs(v=vs.90) +FORCE_INLINE __m128i _mm_add_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Add packed double-precision (64-bit) floating-point elements in a and b, and +// store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_pd +FORCE_INLINE __m128d _mm_add_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] + db[0]; + c[1] = da[1] + db[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Add the lower double-precision (64-bit) floating-point element in a and b, +// store the result in the lower element of dst, and copy the upper element from +// a to the upper element of dst. +// +// dst[63:0] := a[63:0] + b[63:0] +// dst[127:64] := a[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_sd +FORCE_INLINE __m128d _mm_add_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_add_pd(a, b)); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] + db[0]; + c[1] = da[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Add 64-bit integers a and b, and store the result in dst. +// +// dst[63:0] := a[63:0] + b[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_si64 +FORCE_INLINE __m64 _mm_add_si64(__m64 a, __m64 b) +{ + return vreinterpret_m64_s64( + vadd_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b))); +} + +// Adds the 8 signed 16-bit integers in a to the 8 signed 16-bit integers in b +// and saturates. +// +// r0 := SignedSaturate(a0 + b0) +// r1 := SignedSaturate(a1 + b1) +// ... +// r7 := SignedSaturate(a7 + b7) +// +// https://msdn.microsoft.com/en-us/library/1a306ef8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_adds_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vqaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Add packed signed 8-bit integers in a and b using saturation, and store the +// results in dst. +// +// FOR j := 0 to 15 +// i := j*8 +// dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] ) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epi8 +FORCE_INLINE __m128i _mm_adds_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vqaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Add packed unsigned 16-bit integers in a and b using saturation, and store +// the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epu16 +FORCE_INLINE __m128i _mm_adds_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vqaddq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Adds the 16 unsigned 8-bit integers in a to the 16 unsigned 8-bit integers in +// b and saturates.. +// https://msdn.microsoft.com/en-us/library/9hahyddy(v=vs.100).aspx +FORCE_INLINE __m128i _mm_adds_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vqaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Compute the bitwise AND of packed double-precision (64-bit) floating-point +// elements in a and b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := a[i+63:i] AND b[i+63:i] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_and_pd +FORCE_INLINE __m128d _mm_and_pd(__m128d a, __m128d b) +{ + return vreinterpretq_m128d_s64( + vandq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b))); +} + +// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in +// b. +// +// r := a & b +// +// https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compute the bitwise NOT of packed double-precision (64-bit) floating-point +// elements in a and then AND with b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := ((NOT a[i+63:i]) AND b[i+63:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_andnot_pd +FORCE_INLINE __m128d _mm_andnot_pd(__m128d a, __m128d b) +{ + // *NOTE* argument swap + return vreinterpretq_m128d_s64( + vbicq_s64(vreinterpretq_s64_m128d(b), vreinterpretq_s64_m128d(a))); +} + +// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the +// 128-bit value in a. +// +// r := (~a) & b +// +// https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vbicq_s32(vreinterpretq_s32_m128i(b), + vreinterpretq_s32_m128i(a))); // *NOTE* argument swap +} + +// Computes the average of the 8 unsigned 16-bit integers in a and the 8 +// unsigned 16-bit integers in b and rounds. +// +// r0 := (a0 + b0) / 2 +// r1 := (a1 + b1) / 2 +// ... +// r7 := (a7 + b7) / 2 +// +// https://msdn.microsoft.com/en-us/library/vstudio/y13ca3c8(v=vs.90).aspx +FORCE_INLINE __m128i _mm_avg_epu16(__m128i a, __m128i b) +{ + return (__m128i) vrhaddq_u16(vreinterpretq_u16_m128i(a), + vreinterpretq_u16_m128i(b)); +} + +// Computes the average of the 16 unsigned 8-bit integers in a and the 16 +// unsigned 8-bit integers in b and rounds. +// +// r0 := (a0 + b0) / 2 +// r1 := (a1 + b1) / 2 +// ... +// r15 := (a15 + b15) / 2 +// +// https://msdn.microsoft.com/en-us/library/vstudio/8zwh554a(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_avg_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vrhaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Shift a left by imm8 bytes while shifting in zeros, and store the results in +// dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_bslli_si128 +#define _mm_bslli_si128(a, imm) _mm_slli_si128(a, imm) + +// Shift a right by imm8 bytes while shifting in zeros, and store the results in +// dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_bsrli_si128 +#define _mm_bsrli_si128(a, imm) _mm_srli_si128(a, imm) + +// Cast vector of type __m128d to type __m128. This intrinsic is only used for +// compilation and does not generate any instructions, thus it has zero latency. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_ps +FORCE_INLINE __m128 _mm_castpd_ps(__m128d a) +{ + return vreinterpretq_m128_s64(vreinterpretq_s64_m128d(a)); +} + +// Cast vector of type __m128d to type __m128i. This intrinsic is only used for +// compilation and does not generate any instructions, thus it has zero latency. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_si128 +FORCE_INLINE __m128i _mm_castpd_si128(__m128d a) +{ + return vreinterpretq_m128i_s64(vreinterpretq_s64_m128d(a)); +} + +// Cast vector of type __m128 to type __m128d. This intrinsic is only used for +// compilation and does not generate any instructions, thus it has zero latency. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_pd +FORCE_INLINE __m128d _mm_castps_pd(__m128 a) +{ + return vreinterpretq_m128d_s32(vreinterpretq_s32_m128(a)); +} + +// Applies a type cast to reinterpret four 32-bit floating point values passed +// in as a 128-bit parameter as packed 32-bit integers. +// https://msdn.microsoft.com/en-us/library/bb514099.aspx +FORCE_INLINE __m128i _mm_castps_si128(__m128 a) +{ + return vreinterpretq_m128i_s32(vreinterpretq_s32_m128(a)); +} + +// Cast vector of type __m128i to type __m128d. This intrinsic is only used for +// compilation and does not generate any instructions, thus it has zero latency. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castsi128_pd +FORCE_INLINE __m128d _mm_castsi128_pd(__m128i a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vreinterpretq_f64_m128i(a)); +#else + return vreinterpretq_m128d_f32(vreinterpretq_f32_m128i(a)); +#endif +} + +// Applies a type cast to reinterpret four 32-bit integers passed in as a +// 128-bit parameter as packed 32-bit floating point values. +// https://msdn.microsoft.com/en-us/library/bb514029.aspx +FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a) +{ + return vreinterpretq_m128_s32(vreinterpretq_s32_m128i(a)); +} + +// Cache line containing p is flushed and invalidated from all caches in the +// coherency domain. : +// https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx +FORCE_INLINE void _mm_clflush(void const *p) +{ + (void) p; + // no corollary for Neon? +} + +// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or +// unsigned 16-bit integers in b for equality. +// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpeq_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vceqq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Compare packed 32-bit integers in a and b for equality, and store the results +// in dst +FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vceqq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compares the 16 signed or unsigned 8-bit integers in a and the 16 signed or +// unsigned 8-bit integers in b for equality. +// https://msdn.microsoft.com/en-us/library/windows/desktop/bz5xk21a(v=vs.90).aspx +FORCE_INLINE __m128i _mm_cmpeq_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vceqq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for equality, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_pd +FORCE_INLINE __m128d _mm_cmpeq_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64( + vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi) + uint32x4_t cmp = + vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b)); + uint32x4_t swapped = vrev64q_u32(cmp); + return vreinterpretq_m128d_u32(vandq_u32(cmp, swapped)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for equality, store the result in the lower element of dst, and copy the +// upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_sd +FORCE_INLINE __m128d _mm_cmpeq_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_cmpeq_pd(a, b)); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for greater-than-or-equal, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_pd +FORCE_INLINE __m128d _mm_cmpge_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64( + vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = (*(double *) &a1) >= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for greater-than-or-equal, store the result in the lower element of dst, +// and copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_sd +FORCE_INLINE __m128d _mm_cmpge_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_cmpge_pd(a, b)); +#else + // expand "_mm_cmpge_pd()" to reduce unnecessary operations + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = a1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers +// in b for greater than. +// +// r0 := (a0 > b0) ? 0xffff : 0x0 +// r1 := (a1 > b1) ? 0xffff : 0x0 +// ... +// r7 := (a7 > b7) ? 0xffff : 0x0 +// +// https://technet.microsoft.com/en-us/library/xd43yfsa(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vcgtq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers +// in b for greater than. +// https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vcgtq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers +// in b for greater than. +// +// r0 := (a0 > b0) ? 0xff : 0x0 +// r1 := (a1 > b1) ? 0xff : 0x0 +// ... +// r15 := (a15 > b15) ? 0xff : 0x0 +// +// https://msdn.microsoft.com/zh-tw/library/wf45zt2b(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vcgtq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for greater-than, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_pd +FORCE_INLINE __m128d _mm_cmpgt_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64( + vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = (*(double *) &a1) > (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for greater-than, store the result in the lower element of dst, and copy +// the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_sd +FORCE_INLINE __m128d _mm_cmpgt_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_cmpgt_pd(a, b)); +#else + // expand "_mm_cmpge_pd()" to reduce unnecessary operations + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = a1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for less-than-or-equal, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_pd +FORCE_INLINE __m128d _mm_cmple_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64( + vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = (*(double *) &a1) <= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for less-than-or-equal, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_sd +FORCE_INLINE __m128d _mm_cmple_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_cmple_pd(a, b)); +#else + // expand "_mm_cmpge_pd()" to reduce unnecessary operations + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = a1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers +// in b for less than. +// +// r0 := (a0 < b0) ? 0xffff : 0x0 +// r1 := (a1 < b1) ? 0xffff : 0x0 +// ... +// r7 := (a7 < b7) ? 0xffff : 0x0 +// +// https://technet.microsoft.com/en-us/library/t863edb2(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmplt_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vcltq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + + +// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers +// in b for less than. +// https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vcltq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers +// in b for lesser than. +// https://msdn.microsoft.com/en-us/library/windows/desktop/9s46csht(v=vs.90).aspx +FORCE_INLINE __m128i _mm_cmplt_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vcltq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for less-than, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_pd +FORCE_INLINE __m128d _mm_cmplt_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64( + vcltq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = (*(double *) &a1) < (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for less-than, store the result in the lower element of dst, and copy the +// upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_sd +FORCE_INLINE __m128d _mm_cmplt_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_cmplt_pd(a, b)); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = a1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for not-equal, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_pd +FORCE_INLINE __m128d _mm_cmpneq_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_s32(vmvnq_s32(vreinterpretq_s32_u64( + vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))))); +#else + // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi) + uint32x4_t cmp = + vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b)); + uint32x4_t swapped = vrev64q_u32(cmp); + return vreinterpretq_m128d_u32(vmvnq_u32(vandq_u32(cmp, swapped))); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for not-equal, store the result in the lower element of dst, and copy the +// upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_sd +FORCE_INLINE __m128d _mm_cmpneq_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_cmpneq_pd(a, b)); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for not-greater-than-or-equal, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnge_pd +FORCE_INLINE __m128d _mm_cmpnge_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64(veorq_u64( + vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)), + vdupq_n_u64(UINT64_MAX))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = + !((*(double *) &a0) >= (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = + !((*(double *) &a1) >= (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for not-greater-than-or-equal, store the result in the lower element of +// dst, and copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnge_sd +FORCE_INLINE __m128d _mm_cmpnge_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_cmpnge_pd(a, b)); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for not-greater-than, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_cmpngt_pd +FORCE_INLINE __m128d _mm_cmpngt_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64(veorq_u64( + vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)), + vdupq_n_u64(UINT64_MAX))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = + !((*(double *) &a0) > (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = + !((*(double *) &a1) > (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for not-greater-than, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpngt_sd +FORCE_INLINE __m128d _mm_cmpngt_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_cmpngt_pd(a, b)); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for not-less-than-or-equal, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnle_pd +FORCE_INLINE __m128d _mm_cmpnle_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64(veorq_u64( + vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)), + vdupq_n_u64(UINT64_MAX))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = + !((*(double *) &a0) <= (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = + !((*(double *) &a1) <= (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for not-less-than-or-equal, store the result in the lower element of dst, +// and copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnle_sd +FORCE_INLINE __m128d _mm_cmpnle_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_cmpnle_pd(a, b)); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// for not-less-than, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnlt_pd +FORCE_INLINE __m128d _mm_cmpnlt_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_u64(veorq_u64( + vcltq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)), + vdupq_n_u64(UINT64_MAX))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = + !((*(double *) &a0) < (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0); + d[1] = + !((*(double *) &a1) < (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b for not-less-than, store the result in the lower element of dst, and copy +// the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnlt_sd +FORCE_INLINE __m128d _mm_cmpnlt_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_cmpnlt_pd(a, b)); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// to see if neither is NaN, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpord_pd +FORCE_INLINE __m128d _mm_cmpord_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + // Excluding NaNs, any two floating point numbers can be compared. + uint64x2_t not_nan_a = + vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(a)); + uint64x2_t not_nan_b = + vceqq_f64(vreinterpretq_f64_m128d(b), vreinterpretq_f64_m128d(b)); + return vreinterpretq_m128d_u64(vandq_u64(not_nan_a, not_nan_b)); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = ((*(double *) &a0) == (*(double *) &a0) && + (*(double *) &b0) == (*(double *) &b0)) + ? ~UINT64_C(0) + : UINT64_C(0); + d[1] = ((*(double *) &a1) == (*(double *) &a1) && + (*(double *) &b1) == (*(double *) &b1)) + ? ~UINT64_C(0) + : UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b to see if neither is NaN, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpord_sd +FORCE_INLINE __m128d _mm_cmpord_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_cmpord_pd(a, b)); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t d[2]; + d[0] = ((*(double *) &a0) == (*(double *) &a0) && + (*(double *) &b0) == (*(double *) &b0)) + ? ~UINT64_C(0) + : UINT64_C(0); + d[1] = a1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b +// to see if either is NaN, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpunord_pd +FORCE_INLINE __m128d _mm_cmpunord_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + // Two NaNs are not equal in comparison operation. + uint64x2_t not_nan_a = + vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(a)); + uint64x2_t not_nan_b = + vceqq_f64(vreinterpretq_f64_m128d(b), vreinterpretq_f64_m128d(b)); + return vreinterpretq_m128d_s32( + vmvnq_s32(vreinterpretq_s32_u64(vandq_u64(not_nan_a, not_nan_b)))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = ((*(double *) &a0) == (*(double *) &a0) && + (*(double *) &b0) == (*(double *) &b0)) + ? UINT64_C(0) + : ~UINT64_C(0); + d[1] = ((*(double *) &a1) == (*(double *) &a1) && + (*(double *) &b1) == (*(double *) &b1)) + ? UINT64_C(0) + : ~UINT64_C(0); + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b to see if either is NaN, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpunord_sd +FORCE_INLINE __m128d _mm_cmpunord_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_cmpunord_pd(a, b)); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t d[2]; + d[0] = ((*(double *) &a0) == (*(double *) &a0) && + (*(double *) &b0) == (*(double *) &b0)) + ? UINT64_C(0) + : ~UINT64_C(0); + d[1] = a1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point element in a and b +// for greater-than-or-equal, and return the boolean result (0 or 1). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comige_sd +FORCE_INLINE int _mm_comige_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vgetq_lane_u64(vcgeq_f64(a, b), 0) & 0x1; +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + + return (*(double *) &a0 >= *(double *) &b0); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point element in a and b +// for greater-than, and return the boolean result (0 or 1). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comigt_sd +FORCE_INLINE int _mm_comigt_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vgetq_lane_u64(vcgtq_f64(a, b), 0) & 0x1; +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + + return (*(double *) &a0 > *(double *) &b0); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point element in a and b +// for less-than-or-equal, and return the boolean result (0 or 1). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comile_sd +FORCE_INLINE int _mm_comile_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vgetq_lane_u64(vcleq_f64(a, b), 0) & 0x1; +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + + return (*(double *) &a0 <= *(double *) &b0); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point element in a and b +// for less-than, and return the boolean result (0 or 1). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comilt_sd +FORCE_INLINE int _mm_comilt_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vgetq_lane_u64(vcltq_f64(a, b), 0) & 0x1; +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + + return (*(double *) &a0 < *(double *) &b0); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point element in a and b +// for equality, and return the boolean result (0 or 1). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comieq_sd +FORCE_INLINE int _mm_comieq_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vgetq_lane_u64(vceqq_f64(a, b), 0) & 0x1; +#else + uint32x4_t a_not_nan = + vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(a)); + uint32x4_t b_not_nan = + vceqq_u32(vreinterpretq_u32_m128d(b), vreinterpretq_u32_m128d(b)); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_eq_b = + vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b)); + uint64x2_t and_results = vandq_u64(vreinterpretq_u64_u32(a_and_b_not_nan), + vreinterpretq_u64_u32(a_eq_b)); + return vgetq_lane_u64(and_results, 0) & 0x1; +#endif +} + +// Compare the lower double-precision (64-bit) floating-point element in a and b +// for not-equal, and return the boolean result (0 or 1). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comineq_sd +FORCE_INLINE int _mm_comineq_sd(__m128d a, __m128d b) +{ + return !_mm_comieq_sd(a, b); +} + +// Convert packed signed 32-bit integers in a to packed double-precision +// (64-bit) floating-point elements, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*32 +// m := j*64 +// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi32_pd +FORCE_INLINE __m128d _mm_cvtepi32_pd(__m128i a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcvtq_f64_s64(vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a))))); +#else + double a0 = (double) vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0); + double a1 = (double) vgetq_lane_s32(vreinterpretq_s32_m128i(a), 1); + return _mm_set_pd(a1, a0); +#endif +} + +// Converts the four signed 32-bit integer values of a to single-precision, +// floating-point values +// https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a) +{ + return vreinterpretq_m128_f32(vcvtq_f32_s32(vreinterpretq_s32_m128i(a))); +} + +// Convert packed double-precision (64-bit) floating-point elements in a to +// packed 32-bit integers, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// k := 64*j +// dst[i+31:i] := Convert_FP64_To_Int32(a[k+63:k]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_epi32 +FORCE_INLINE __m128i _mm_cvtpd_epi32(__m128d a) +{ + __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION); + double d0 = ((double *) &rnd)[0]; + double d1 = ((double *) &rnd)[1]; + return _mm_set_epi32(0, 0, (int32_t) d1, (int32_t) d0); +} + +// Convert packed double-precision (64-bit) floating-point elements in a to +// packed 32-bit integers, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// k := 64*j +// dst[i+31:i] := Convert_FP64_To_Int32(a[k+63:k]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_pi32 +FORCE_INLINE __m64 _mm_cvtpd_pi32(__m128d a) +{ + __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION); + double d0 = ((double *) &rnd)[0]; + double d1 = ((double *) &rnd)[1]; + int32_t ALIGN_STRUCT(16) data[2] = {(int32_t) d0, (int32_t) d1}; + return vreinterpret_m64_s32(vld1_s32(data)); +} + +// Convert packed double-precision (64-bit) floating-point elements in a to +// packed single-precision (32-bit) floating-point elements, and store the +// results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// k := 64*j +// dst[i+31:i] := Convert_FP64_To_FP32(a[k+64:k]) +// ENDFOR +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_ps +FORCE_INLINE __m128 _mm_cvtpd_ps(__m128d a) +{ +#if defined(__aarch64__) + float32x2_t tmp = vcvt_f32_f64(vreinterpretq_f64_m128d(a)); + return vreinterpretq_m128_f32(vcombine_f32(tmp, vdup_n_f32(0))); +#else + float a0 = (float) ((double *) &a)[0]; + float a1 = (float) ((double *) &a)[1]; + return _mm_set_ps(0, 0, a1, a0); +#endif +} + +// Convert packed signed 32-bit integers in a to packed double-precision +// (64-bit) floating-point elements, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*32 +// m := j*64 +// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_pd +FORCE_INLINE __m128d _mm_cvtpi32_pd(__m64 a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcvtq_f64_s64(vmovl_s32(vreinterpret_s32_m64(a)))); +#else + double a0 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 0); + double a1 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 1); + return _mm_set_pd(a1, a0); +#endif +} + +// Converts the four single-precision, floating-point values of a to signed +// 32-bit integer values. +// +// r0 := (int) a0 +// r1 := (int) a1 +// r2 := (int) a2 +// r3 := (int) a3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx +// *NOTE*. The default rounding mode on SSE is 'round to even', which ARMv7-A +// does not support! It is supported on ARMv8-A however. +FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a) +{ +#if defined(__aarch64__) + switch (_MM_GET_ROUNDING_MODE()) { + case _MM_ROUND_NEAREST: + return vreinterpretq_m128i_s32(vcvtnq_s32_f32(a)); + case _MM_ROUND_DOWN: + return vreinterpretq_m128i_s32(vcvtmq_s32_f32(a)); + case _MM_ROUND_UP: + return vreinterpretq_m128i_s32(vcvtpq_s32_f32(a)); + default: // _MM_ROUND_TOWARD_ZERO + return vreinterpretq_m128i_s32(vcvtq_s32_f32(a)); + } +#else + float *f = (float *) &a; + switch (_MM_GET_ROUNDING_MODE()) { + case _MM_ROUND_NEAREST: { + uint32x4_t signmask = vdupq_n_u32(0x80000000); + float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a), + vdupq_n_f32(0.5f)); /* +/- 0.5 */ + int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32( + vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/ + int32x4_t r_trunc = vcvtq_s32_f32( + vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */ + int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32( + vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */ + int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone), + vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */ + float32x4_t delta = vsubq_f32( + vreinterpretq_f32_m128(a), + vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */ + uint32x4_t is_delta_half = + vceqq_f32(delta, half); /* delta == +/- 0.5 */ + return vreinterpretq_m128i_s32( + vbslq_s32(is_delta_half, r_even, r_normal)); + } + case _MM_ROUND_DOWN: + return _mm_set_epi32(floorf(f[3]), floorf(f[2]), floorf(f[1]), + floorf(f[0])); + case _MM_ROUND_UP: + return _mm_set_epi32(ceilf(f[3]), ceilf(f[2]), ceilf(f[1]), + ceilf(f[0])); + default: // _MM_ROUND_TOWARD_ZERO + return _mm_set_epi32((int32_t) f[3], (int32_t) f[2], (int32_t) f[1], + (int32_t) f[0]); + } +#endif +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed double-precision (64-bit) floating-point elements, and store the +// results in dst. +// +// FOR j := 0 to 1 +// i := 64*j +// k := 32*j +// dst[i+63:i] := Convert_FP32_To_FP64(a[k+31:k]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pd +FORCE_INLINE __m128d _mm_cvtps_pd(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcvt_f64_f32(vget_low_f32(vreinterpretq_f32_m128(a)))); +#else + double a0 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + double a1 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 1); + return _mm_set_pd(a1, a0); +#endif +} + +// Copy the lower double-precision (64-bit) floating-point element of a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_f64 +FORCE_INLINE double _mm_cvtsd_f64(__m128d a) +{ +#if defined(__aarch64__) + return (double) vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0); +#else + return ((double *) &a)[0]; +#endif +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 32-bit integer, and store the result in dst. +// +// dst[31:0] := Convert_FP64_To_Int32(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si32 +FORCE_INLINE int32_t _mm_cvtsd_si32(__m128d a) +{ +#if defined(__aarch64__) + return (int32_t) vgetq_lane_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)), 0); +#else + __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION); + double ret = ((double *) &rnd)[0]; + return (int32_t) ret; +#endif +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 64-bit integer, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int64(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si64 +FORCE_INLINE int64_t _mm_cvtsd_si64(__m128d a) +{ +#if defined(__aarch64__) + return (int64_t) vgetq_lane_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)), 0); +#else + __m128d rnd = _mm_round_pd(a, _MM_FROUND_CUR_DIRECTION); + double ret = ((double *) &rnd)[0]; + return (int64_t) ret; +#endif +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 64-bit integer, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int64(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_si64x +#define _mm_cvtsd_si64x _mm_cvtsd_si64 + +// Convert the lower double-precision (64-bit) floating-point element in b to a +// single-precision (32-bit) floating-point element, store the result in the +// lower element of dst, and copy the upper 3 packed elements from a to the +// upper elements of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_ss +FORCE_INLINE __m128 _mm_cvtsd_ss(__m128 a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vsetq_lane_f32( + vget_lane_f32(vcvt_f32_f64(vreinterpretq_f64_m128d(b)), 0), + vreinterpretq_f32_m128(a), 0)); +#else + return vreinterpretq_m128_f32(vsetq_lane_f32((float) ((double *) &b)[0], + vreinterpretq_f32_m128(a), 0)); +#endif +} + +// Copy the lower 32-bit integer in a to dst. +// +// dst[31:0] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si32 +FORCE_INLINE int _mm_cvtsi128_si32(__m128i a) +{ + return vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0); +} + +// Copy the lower 64-bit integer in a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64 +FORCE_INLINE int64_t _mm_cvtsi128_si64(__m128i a) +{ + return vgetq_lane_s64(vreinterpretq_s64_m128i(a), 0); +} + +// Copy the lower 64-bit integer in a to dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x +#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a) + +// Convert the signed 32-bit integer b to a double-precision (64-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_sd +FORCE_INLINE __m128d _mm_cvtsi32_sd(__m128d a, int32_t b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vsetq_lane_f64((double) b, vreinterpretq_f64_m128d(a), 0)); +#else + double bf = (double) b; + return vreinterpretq_m128d_s64( + vsetq_lane_s64(*(int64_t *) &bf, vreinterpretq_s64_m128d(a), 0)); +#endif +} + +// Copy the lower 64-bit integer in a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x +#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a) + +// Moves 32-bit integer a to the least significant 32 bits of an __m128 object, +// zero extending the upper bits. +// +// r0 := a +// r1 := 0x0 +// r2 := 0x0 +// r3 := 0x0 +// +// https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_cvtsi32_si128(int a) +{ + return vreinterpretq_m128i_s32(vsetq_lane_s32(a, vdupq_n_s32(0), 0)); +} + +// Convert the signed 64-bit integer b to a double-precision (64-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_sd +FORCE_INLINE __m128d _mm_cvtsi64_sd(__m128d a, int64_t b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vsetq_lane_f64((double) b, vreinterpretq_f64_m128d(a), 0)); +#else + double bf = (double) b; + return vreinterpretq_m128d_s64( + vsetq_lane_s64(*(int64_t *) &bf, vreinterpretq_s64_m128d(a), 0)); +#endif +} + +// Moves 64-bit integer a to the least significant 64 bits of an __m128 object, +// zero extending the upper bits. +// +// r0 := a +// r1 := 0x0 +FORCE_INLINE __m128i _mm_cvtsi64_si128(int64_t a) +{ + return vreinterpretq_m128i_s64(vsetq_lane_s64(a, vdupq_n_s64(0), 0)); +} + +// Copy 64-bit integer a to the lower element of dst, and zero the upper +// element. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64x_si128 +#define _mm_cvtsi64x_si128(a) _mm_cvtsi64_si128(a) + +// Convert the signed 64-bit integer b to a double-precision (64-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64x_sd +#define _mm_cvtsi64x_sd(a, b) _mm_cvtsi64_sd(a, b) + +// Convert the lower single-precision (32-bit) floating-point element in b to a +// double-precision (64-bit) floating-point element, store the result in the +// lower element of dst, and copy the upper element from a to the upper element +// of dst. +// +// dst[63:0] := Convert_FP32_To_FP64(b[31:0]) +// dst[127:64] := a[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_sd +FORCE_INLINE __m128d _mm_cvtss_sd(__m128d a, __m128 b) +{ + double d = (double) vgetq_lane_f32(vreinterpretq_f32_m128(b), 0); +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vsetq_lane_f64(d, vreinterpretq_f64_m128d(a), 0)); +#else + return vreinterpretq_m128d_s64( + vsetq_lane_s64(*(int64_t *) &d, vreinterpretq_s64_m128d(a), 0)); +#endif +} + +// Convert packed double-precision (64-bit) floating-point elements in a to +// packed 32-bit integers with truncation, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttpd_epi32 +FORCE_INLINE __m128i _mm_cvttpd_epi32(__m128d a) +{ + double a0 = ((double *) &a)[0]; + double a1 = ((double *) &a)[1]; + return _mm_set_epi32(0, 0, (int32_t) a1, (int32_t) a0); +} + +// Convert packed double-precision (64-bit) floating-point elements in a to +// packed 32-bit integers with truncation, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttpd_pi32 +FORCE_INLINE __m64 _mm_cvttpd_pi32(__m128d a) +{ + double a0 = ((double *) &a)[0]; + double a1 = ((double *) &a)[1]; + int32_t ALIGN_STRUCT(16) data[2] = {(int32_t) a0, (int32_t) a1}; + return vreinterpret_m64_s32(vld1_s32(data)); +} + +// Converts the four single-precision, floating-point values of a to signed +// 32-bit integer values using truncate. +// https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a) +{ + return vreinterpretq_m128i_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a))); +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 32-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int32_Truncate(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si32 +FORCE_INLINE int32_t _mm_cvttsd_si32(__m128d a) +{ + double ret = *((double *) &a); + return (int32_t) ret; +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 64-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64 +FORCE_INLINE int64_t _mm_cvttsd_si64(__m128d a) +{ +#if defined(__aarch64__) + return vgetq_lane_s64(vcvtq_s64_f64(vreinterpretq_f64_m128d(a)), 0); +#else + double ret = *((double *) &a); + return (int64_t) ret; +#endif +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 64-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64x +#define _mm_cvttsd_si64x(a) _mm_cvttsd_si64(a) + +// Divide packed double-precision (64-bit) floating-point elements in a by +// packed elements in b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 64*j +// dst[i+63:i] := a[i+63:i] / b[i+63:i] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_pd +FORCE_INLINE __m128d _mm_div_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vdivq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] / db[0]; + c[1] = da[1] / db[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Divide the lower double-precision (64-bit) floating-point element in a by the +// lower double-precision (64-bit) floating-point element in b, store the result +// in the lower element of dst, and copy the upper element from a to the upper +// element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_sd +FORCE_INLINE __m128d _mm_div_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + float64x2_t tmp = + vdivq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)); + return vreinterpretq_m128d_f64( + vsetq_lane_f64(vgetq_lane_f64(vreinterpretq_f64_m128d(a), 1), tmp, 1)); +#else + return _mm_move_sd(a, _mm_div_pd(a, b)); +#endif +} + +// Extracts the selected signed or unsigned 16-bit integer from a and zero +// extends. +// https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx +// FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm) +#define _mm_extract_epi16(a, imm) \ + vgetq_lane_u16(vreinterpretq_u16_m128i(a), (imm)) + +// Inserts the least significant 16 bits of b into the selected 16-bit integer +// of a. +// https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx +// FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, int b, +// __constrange(0,8) int imm) +#define _mm_insert_epi16(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s16( \ + vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \ + }) + +// Loads two double-precision from 16-byte aligned memory, floating-point +// values. +// +// dst[127:0] := MEM[mem_addr+127:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd +FORCE_INLINE __m128d _mm_load_pd(const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vld1q_f64(p)); +#else + const float *fp = (const float *) p; + float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], fp[2], fp[3]}; + return vreinterpretq_m128d_f32(vld1q_f32(data)); +#endif +} + +// Load a double-precision (64-bit) floating-point element from memory into both +// elements of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1 +#define _mm_load_pd1 _mm_load1_pd + +// Load a double-precision (64-bit) floating-point element from memory into the +// lower of dst, and zero the upper element. mem_addr does not need to be +// aligned on any particular boundary. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_sd +FORCE_INLINE __m128d _mm_load_sd(const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vsetq_lane_f64(*p, vdupq_n_f64(0), 0)); +#else + const float *fp = (const float *) p; + float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], 0, 0}; + return vreinterpretq_m128d_f32(vld1q_f32(data)); +#endif +} + +// Loads 128-bit value. : +// https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx +FORCE_INLINE __m128i _mm_load_si128(const __m128i *p) +{ + return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p)); +} + +// Load a double-precision (64-bit) floating-point element from memory into both +// elements of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load1_pd +FORCE_INLINE __m128d _mm_load1_pd(const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vld1q_dup_f64(p)); +#else + return vreinterpretq_m128d_s64(vdupq_n_s64(*(const int64_t *) p)); +#endif +} + +// Load a double-precision (64-bit) floating-point element from memory into the +// upper element of dst, and copy the lower element from a to dst. mem_addr does +// not need to be aligned on any particular boundary. +// +// dst[63:0] := a[63:0] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadh_pd +FORCE_INLINE __m128d _mm_loadh_pd(__m128d a, const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcombine_f64(vget_low_f64(vreinterpretq_f64_m128d(a)), vld1_f64(p))); +#else + return vreinterpretq_m128d_f32(vcombine_f32( + vget_low_f32(vreinterpretq_f32_m128d(a)), vld1_f32((const float *) p))); +#endif +} + +// Load 64-bit integer from memory into the first element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_epi64 +FORCE_INLINE __m128i _mm_loadl_epi64(__m128i const *p) +{ + /* Load the lower 64 bits of the value pointed to by p into the + * lower 64 bits of the result, zeroing the upper 64 bits of the result. + */ + return vreinterpretq_m128i_s32( + vcombine_s32(vld1_s32((int32_t const *) p), vcreate_s32(0))); +} + +// Load a double-precision (64-bit) floating-point element from memory into the +// lower element of dst, and copy the upper element from a to dst. mem_addr does +// not need to be aligned on any particular boundary. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := a[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_pd +FORCE_INLINE __m128d _mm_loadl_pd(__m128d a, const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcombine_f64(vld1_f64(p), vget_high_f64(vreinterpretq_f64_m128d(a)))); +#else + return vreinterpretq_m128d_f32( + vcombine_f32(vld1_f32((const float *) p), + vget_high_f32(vreinterpretq_f32_m128d(a)))); +#endif +} + +// Load 2 double-precision (64-bit) floating-point elements from memory into dst +// in reverse order. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// dst[63:0] := MEM[mem_addr+127:mem_addr+64] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_pd +FORCE_INLINE __m128d _mm_loadr_pd(const double *p) +{ +#if defined(__aarch64__) + float64x2_t v = vld1q_f64(p); + return vreinterpretq_m128d_f64(vextq_f64(v, v, 1)); +#else + int64x2_t v = vld1q_s64((const int64_t *) p); + return vreinterpretq_m128d_s64(vextq_s64(v, v, 1)); +#endif +} + +// Loads two double-precision from unaligned memory, floating-point values. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_pd +FORCE_INLINE __m128d _mm_loadu_pd(const double *p) +{ + return _mm_load_pd(p); +} + +// Loads 128-bit value. : +// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx +FORCE_INLINE __m128i _mm_loadu_si128(const __m128i *p) +{ + return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p)); +} + +// Load unaligned 32-bit integer from memory into the first element of dst. +// +// dst[31:0] := MEM[mem_addr+31:mem_addr] +// dst[MAX:32] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si32 +FORCE_INLINE __m128i _mm_loadu_si32(const void *p) +{ + return vreinterpretq_m128i_s32( + vsetq_lane_s32(*(const int32_t *) p, vdupq_n_s32(0), 0)); +} + +// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit +// integers from b. +// +// r0 := (a0 * b0) + (a1 * b1) +// r1 := (a2 * b2) + (a3 * b3) +// r2 := (a4 * b4) + (a5 * b5) +// r3 := (a6 * b6) + (a7 * b7) +// https://msdn.microsoft.com/en-us/library/yht36sa6(v=vs.90).aspx +FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b) +{ + int32x4_t low = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)), + vget_low_s16(vreinterpretq_s16_m128i(b))); + int32x4_t high = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)), + vget_high_s16(vreinterpretq_s16_m128i(b))); + + int32x2_t low_sum = vpadd_s32(vget_low_s32(low), vget_high_s32(low)); + int32x2_t high_sum = vpadd_s32(vget_low_s32(high), vget_high_s32(high)); + + return vreinterpretq_m128i_s32(vcombine_s32(low_sum, high_sum)); +} + +// Conditionally store 8-bit integer elements from a into memory using mask +// (elements are not stored when the highest bit is not set in the corresponding +// element) and a non-temporal memory hint. mem_addr does not need to be aligned +// on any particular boundary. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskmoveu_si128 +FORCE_INLINE void _mm_maskmoveu_si128(__m128i a, __m128i mask, char *mem_addr) +{ + int8x16_t shr_mask = vshrq_n_s8(vreinterpretq_s8_m128i(mask), 7); + __m128 b = _mm_load_ps((const float *) mem_addr); + int8x16_t masked = + vbslq_s8(vreinterpretq_u8_s8(shr_mask), vreinterpretq_s8_m128i(a), + vreinterpretq_s8_m128(b)); + vst1q_s8((int8_t *) mem_addr, masked); +} + +// Computes the pairwise maxima of the 8 signed 16-bit integers from a and the 8 +// signed 16-bit integers from b. +// https://msdn.microsoft.com/en-us/LIBRary/3x060h7c(v=vs.100).aspx +FORCE_INLINE __m128i _mm_max_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vmaxq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Computes the pairwise maxima of the 16 unsigned 8-bit integers from a and the +// 16 unsigned 8-bit integers from b. +// https://msdn.microsoft.com/en-us/library/st6634za(v=vs.100).aspx +FORCE_INLINE __m128i _mm_max_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vmaxq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b, +// and store packed maximum values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pd +FORCE_INLINE __m128d _mm_max_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vmaxq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) > (*(double *) &b0) ? a0 : b0; + d[1] = (*(double *) &a1) > (*(double *) &b1) ? a1 : b1; + + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b, store the maximum value in the lower element of dst, and copy the upper +// element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_sd +FORCE_INLINE __m128d _mm_max_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_max_pd(a, b)); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2] = {fmax(da[0], db[0]), da[1]}; + return vld1q_f32((float32_t *) c); +#endif +} + +// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8 +// signed 16-bit integers from b. +// https://msdn.microsoft.com/en-us/library/vstudio/6te997ew(v=vs.100).aspx +FORCE_INLINE __m128i _mm_min_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vminq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the +// 16 unsigned 8-bit integers from b. +// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx +FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vminq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Compare packed double-precision (64-bit) floating-point elements in a and b, +// and store packed minimum values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pd +FORCE_INLINE __m128d _mm_min_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vminq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a)); + uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a)); + uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b)); + uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b)); + uint64_t d[2]; + d[0] = (*(double *) &a0) < (*(double *) &b0) ? a0 : b0; + d[1] = (*(double *) &a1) < (*(double *) &b1) ? a1 : b1; + return vreinterpretq_m128d_u64(vld1q_u64(d)); +#endif +} + +// Compare the lower double-precision (64-bit) floating-point elements in a and +// b, store the minimum value in the lower element of dst, and copy the upper +// element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_sd +FORCE_INLINE __m128d _mm_min_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_min_pd(a, b)); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2] = {fmin(da[0], db[0]), da[1]}; + return vld1q_f32((float32_t *) c); +#endif +} + +// Copy the lower 64-bit integer in a to the lower element of dst, and zero the +// upper element. +// +// dst[63:0] := a[63:0] +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_epi64 +FORCE_INLINE __m128i _mm_move_epi64(__m128i a) +{ + return vreinterpretq_m128i_s64( + vsetq_lane_s64(0, vreinterpretq_s64_m128i(a), 1)); +} + +// Move the lower double-precision (64-bit) floating-point element from b to the +// lower element of dst, and copy the upper element from a to the upper element +// of dst. +// +// dst[63:0] := b[63:0] +// dst[127:64] := a[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sd +FORCE_INLINE __m128d _mm_move_sd(__m128d a, __m128d b) +{ + return vreinterpretq_m128d_f32( + vcombine_f32(vget_low_f32(vreinterpretq_f32_m128d(b)), + vget_high_f32(vreinterpretq_f32_m128d(a)))); +} + +// NEON does not provide a version of this function. +// Creates a 16-bit mask from the most significant bits of the 16 signed or +// unsigned 8-bit integers in a and zero extends the upper bits. +// https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx +FORCE_INLINE int _mm_movemask_epi8(__m128i a) +{ + // Use increasingly wide shifts+adds to collect the sign bits + // together. + // Since the widening shifts would be rather confusing to follow in little + // endian, everything will be illustrated in big endian order instead. This + // has a different result - the bits would actually be reversed on a big + // endian machine. + + // Starting input (only half the elements are shown): + // 89 ff 1d c0 00 10 99 33 + uint8x16_t input = vreinterpretq_u8_m128i(a); + + // Shift out everything but the sign bits with an unsigned shift right. + // + // Bytes of the vector:: + // 89 ff 1d c0 00 10 99 33 + // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7) + // | | | | | | | | + // 01 01 00 01 00 00 01 00 + // + // Bits of first important lane(s): + // 10001001 (89) + // \______ + // | + // 00000001 (01) + uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7)); + + // Merge the even lanes together with a 16-bit unsigned shift right + add. + // 'xx' represents garbage data which will be ignored in the final result. + // In the important bytes, the add functions like a binary OR. + // + // 01 01 00 01 00 00 01 00 + // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7)) + // \| \| \| \| + // xx 03 xx 01 xx 00 xx 02 + // + // 00000001 00000001 (01 01) + // \_______ | + // \| + // xxxxxxxx xxxxxx11 (xx 03) + uint32x4_t paired16 = + vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7)); + + // Repeat with a wider 32-bit shift + add. + // xx 03 xx 01 xx 00 xx 02 + // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >> + // 14)) + // \| \| + // xx xx xx 0d xx xx xx 02 + // + // 00000011 00000001 (03 01) + // \\_____ || + // '----.\|| + // xxxxxxxx xxxx1101 (xx 0d) + uint64x2_t paired32 = + vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); + + // Last, an even wider 64-bit shift + add to get our result in the low 8 bit + // lanes. xx xx xx 0d xx xx xx 02 + // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >> + // 28)) + // \| + // xx xx xx xx xx xx xx d2 + // + // 00001101 00000010 (0d 02) + // \ \___ | | + // '---. \| | + // xxxxxxxx 11010010 (xx d2) + uint8x16_t paired64 = + vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); + + // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts. + // xx xx xx xx xx xx xx d2 + // || return paired64[0] + // d2 + // Note: Little endian would return the correct value 4b (01001011) instead. + return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8); +} + +// Set each bit of mask dst based on the most significant bit of the +// corresponding packed double-precision (64-bit) floating-point element in a. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_pd +FORCE_INLINE int _mm_movemask_pd(__m128d a) +{ + uint64x2_t input = vreinterpretq_u64_m128d(a); + uint64x2_t high_bits = vshrq_n_u64(input, 63); + return vgetq_lane_u64(high_bits, 0) | (vgetq_lane_u64(high_bits, 1) << 1); +} + +// Copy the lower 64-bit integer in a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi64_pi64 +FORCE_INLINE __m64 _mm_movepi64_pi64(__m128i a) +{ + return vreinterpret_m64_s64(vget_low_s64(vreinterpretq_s64_m128i(a))); +} + +// Copy the 64-bit integer a to the lower element of dst, and zero the upper +// element. +// +// dst[63:0] := a[63:0] +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movpi64_epi64 +FORCE_INLINE __m128i _mm_movpi64_epi64(__m64 a) +{ + return vreinterpretq_m128i_s64( + vcombine_s64(vreinterpret_s64_m64(a), vdup_n_s64(0))); +} + +// Multiply the low unsigned 32-bit integers from each packed 64-bit element in +// a and b, and store the unsigned 64-bit results in dst. +// +// r0 := (a0 & 0xFFFFFFFF) * (b0 & 0xFFFFFFFF) +// r1 := (a2 & 0xFFFFFFFF) * (b2 & 0xFFFFFFFF) +FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b) +{ + // vmull_u32 upcasts instead of masking, so we downcast. + uint32x2_t a_lo = vmovn_u64(vreinterpretq_u64_m128i(a)); + uint32x2_t b_lo = vmovn_u64(vreinterpretq_u64_m128i(b)); + return vreinterpretq_m128i_u64(vmull_u32(a_lo, b_lo)); +} + +// Multiply packed double-precision (64-bit) floating-point elements in a and b, +// and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_pd +FORCE_INLINE __m128d _mm_mul_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vmulq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] * db[0]; + c[1] = da[1] * db[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Multiply the lower double-precision (64-bit) floating-point element in a and +// b, store the result in the lower element of dst, and copy the upper element +// from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mul_sd +FORCE_INLINE __m128d _mm_mul_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_mul_pd(a, b)); +} + +// Multiply the low unsigned 32-bit integers from a and b, and store the +// unsigned 64-bit result in dst. +// +// dst[63:0] := a[31:0] * b[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_su32 +FORCE_INLINE __m64 _mm_mul_su32(__m64 a, __m64 b) +{ + return vreinterpret_m64_u64(vget_low_u64( + vmull_u32(vreinterpret_u32_m64(a), vreinterpret_u32_m64(b)))); +} + +// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit +// integers from b. +// +// r0 := (a0 * b0)[31:16] +// r1 := (a1 * b1)[31:16] +// ... +// r7 := (a7 * b7)[31:16] +// +// https://msdn.microsoft.com/en-us/library/vstudio/59hddw1d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b) +{ + /* FIXME: issue with large values because of result saturation */ + // int16x8_t ret = vqdmulhq_s16(vreinterpretq_s16_m128i(a), + // vreinterpretq_s16_m128i(b)); /* =2*a*b */ return + // vreinterpretq_m128i_s16(vshrq_n_s16(ret, 1)); + int16x4_t a3210 = vget_low_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b3210 = vget_low_s16(vreinterpretq_s16_m128i(b)); + int32x4_t ab3210 = vmull_s16(a3210, b3210); /* 3333222211110000 */ + int16x4_t a7654 = vget_high_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b7654 = vget_high_s16(vreinterpretq_s16_m128i(b)); + int32x4_t ab7654 = vmull_s16(a7654, b7654); /* 7777666655554444 */ + uint16x8x2_t r = + vuzpq_u16(vreinterpretq_u16_s32(ab3210), vreinterpretq_u16_s32(ab7654)); + return vreinterpretq_m128i_u16(r.val[1]); +} + +// Multiply the packed unsigned 16-bit integers in a and b, producing +// intermediate 32-bit integers, and store the high 16 bits of the intermediate +// integers in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_epu16 +FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b) +{ + uint16x4_t a3210 = vget_low_u16(vreinterpretq_u16_m128i(a)); + uint16x4_t b3210 = vget_low_u16(vreinterpretq_u16_m128i(b)); + uint32x4_t ab3210 = vmull_u16(a3210, b3210); +#if defined(__aarch64__) + uint32x4_t ab7654 = + vmull_high_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)); + uint16x8_t r = vuzp2q_u16(vreinterpretq_u16_u32(ab3210), + vreinterpretq_u16_u32(ab7654)); + return vreinterpretq_m128i_u16(r); +#else + uint16x4_t a7654 = vget_high_u16(vreinterpretq_u16_m128i(a)); + uint16x4_t b7654 = vget_high_u16(vreinterpretq_u16_m128i(b)); + uint32x4_t ab7654 = vmull_u16(a7654, b7654); + uint16x8x2_t r = + vuzpq_u16(vreinterpretq_u16_u32(ab3210), vreinterpretq_u16_u32(ab7654)); + return vreinterpretq_m128i_u16(r.val[1]); +#endif +} + +// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or +// unsigned 16-bit integers from b. +// +// r0 := (a0 * b0)[15:0] +// r1 := (a1 * b1)[15:0] +// ... +// r7 := (a7 * b7)[15:0] +// +// https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx +FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vmulq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Compute the bitwise OR of packed double-precision (64-bit) floating-point +// elements in a and b, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_or_pd +FORCE_INLINE __m128d _mm_or_pd(__m128d a, __m128d b) +{ + return vreinterpretq_m128d_s64( + vorrq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b))); +} + +// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b. +// +// r := a | b +// +// https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx +FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and +// saturates. +// https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)), + vqmovn_s16(vreinterpretq_s16_m128i(b)))); +} + +// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers +// and saturates. +// +// r0 := SignedSaturate(a0) +// r1 := SignedSaturate(a1) +// r2 := SignedSaturate(a2) +// r3 := SignedSaturate(a3) +// r4 := SignedSaturate(b0) +// r5 := SignedSaturate(b1) +// r6 := SignedSaturate(b2) +// r7 := SignedSaturate(b3) +// +// https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)), + vqmovn_s32(vreinterpretq_s32_m128i(b)))); +} + +// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned +// integers and saturates. +// +// r0 := UnsignedSaturate(a0) +// r1 := UnsignedSaturate(a1) +// ... +// r7 := UnsignedSaturate(a7) +// r8 := UnsignedSaturate(b0) +// r9 := UnsignedSaturate(b1) +// ... +// r15 := UnsignedSaturate(b7) +// +// https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx +FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b) +{ + return vreinterpretq_m128i_u8( + vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)), + vqmovun_s16(vreinterpretq_s16_m128i(b)))); +} + +// Pause the processor. This is typically used in spin-wait loops and depending +// on the x86 processor typical values are in the 40-100 cycle range. The +// 'yield' instruction isn't a good fit beacuse it's effectively a nop on most +// Arm cores. Experience with several databases has shown has shown an 'isb' is +// a reasonable approximation. +FORCE_INLINE void _mm_pause() +{ + __asm__ __volatile__("isb\n"); +} + +// Compute the absolute differences of packed unsigned 8-bit integers in a and +// b, then horizontally sum each consecutive 8 differences to produce two +// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low +// 16 bits of 64-bit elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_epu8 +FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b) +{ + uint16x8_t t = vpaddlq_u8(vabdq_u8((uint8x16_t) a, (uint8x16_t) b)); + return vreinterpretq_m128i_u64(vpaddlq_u32(vpaddlq_u16(t))); +} + +// Sets the 8 signed 16-bit integer values. +// https://msdn.microsoft.com/en-au/library/3e0fek84(v=vs.90).aspx +FORCE_INLINE __m128i _mm_set_epi16(short i7, + short i6, + short i5, + short i4, + short i3, + short i2, + short i1, + short i0) +{ + int16_t ALIGN_STRUCT(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7}; + return vreinterpretq_m128i_s16(vld1q_s16(data)); +} + +// Sets the 4 signed 32-bit integer values. +// https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0) +{ + int32_t ALIGN_STRUCT(16) data[4] = {i0, i1, i2, i3}; + return vreinterpretq_m128i_s32(vld1q_s32(data)); +} + +// Returns the __m128i structure with its two 64-bit integer values +// initialized to the values of the two 64-bit integers passed in. +// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx +FORCE_INLINE __m128i _mm_set_epi64(__m64 i1, __m64 i2) +{ + return _mm_set_epi64x((int64_t) i1, (int64_t) i2); +} + +// Returns the __m128i structure with its two 64-bit integer values +// initialized to the values of the two 64-bit integers passed in. +// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx +FORCE_INLINE __m128i _mm_set_epi64x(int64_t i1, int64_t i2) +{ + return vreinterpretq_m128i_s64( + vcombine_s64(vcreate_s64(i2), vcreate_s64(i1))); +} + +// Sets the 16 signed 8-bit integer values. +// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx +FORCE_INLINE __m128i _mm_set_epi8(signed char b15, + signed char b14, + signed char b13, + signed char b12, + signed char b11, + signed char b10, + signed char b9, + signed char b8, + signed char b7, + signed char b6, + signed char b5, + signed char b4, + signed char b3, + signed char b2, + signed char b1, + signed char b0) +{ + int8_t ALIGN_STRUCT(16) + data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3, + (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7, + (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11, + (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15}; + return (__m128i) vld1q_s8(data); +} + +// Set packed double-precision (64-bit) floating-point elements in dst with the +// supplied values. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd +FORCE_INLINE __m128d _mm_set_pd(double e1, double e0) +{ + double ALIGN_STRUCT(16) data[2] = {e0, e1}; +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vld1q_f64((float64_t *) data)); +#else + return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) data)); +#endif +} + +// Broadcast double-precision (64-bit) floating-point value a to all elements of +// dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd1 +#define _mm_set_pd1 _mm_set1_pd + +// Copy double-precision (64-bit) floating-point element a to the lower element +// of dst, and zero the upper element. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_sd +FORCE_INLINE __m128d _mm_set_sd(double a) +{ + return _mm_set_pd(0, a); +} + +// Sets the 8 signed 16-bit integer values to w. +// +// r0 := w +// r1 := w +// ... +// r7 := w +// +// https://msdn.microsoft.com/en-us/library/k0ya3x0e(v=vs.90).aspx +FORCE_INLINE __m128i _mm_set1_epi16(short w) +{ + return vreinterpretq_m128i_s16(vdupq_n_s16(w)); +} + +// Sets the 4 signed 32-bit integer values to i. +// +// r0 := i +// r1 := i +// r2 := i +// r3 := I +// +// https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set1_epi32(int _i) +{ + return vreinterpretq_m128i_s32(vdupq_n_s32(_i)); +} + +// Sets the 2 signed 64-bit integer values to i. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/whtfzhzk(v=vs.100) +FORCE_INLINE __m128i _mm_set1_epi64(__m64 _i) +{ + return vreinterpretq_m128i_s64(vdupq_n_s64((int64_t) _i)); +} + +// Sets the 2 signed 64-bit integer values to i. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_epi64x +FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i) +{ + return vreinterpretq_m128i_s64(vdupq_n_s64(_i)); +} + +// Sets the 16 signed 8-bit integer values to b. +// +// r0 := b +// r1 := b +// ... +// r15 := b +// +// https://msdn.microsoft.com/en-us/library/6e14xhyf(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set1_epi8(signed char w) +{ + return vreinterpretq_m128i_s8(vdupq_n_s8(w)); +} + +// Broadcast double-precision (64-bit) floating-point value a to all elements of +// dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_pd +FORCE_INLINE __m128d _mm_set1_pd(double d) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vdupq_n_f64(d)); +#else + return vreinterpretq_m128d_s64(vdupq_n_s64(*(int64_t *) &d)); +#endif +} + +// Sets the 8 signed 16-bit integer values in reverse order. +// +// Return Value +// r0 := w0 +// r1 := w1 +// ... +// r7 := w7 +FORCE_INLINE __m128i _mm_setr_epi16(short w0, + short w1, + short w2, + short w3, + short w4, + short w5, + short w6, + short w7) +{ + int16_t ALIGN_STRUCT(16) data[8] = {w0, w1, w2, w3, w4, w5, w6, w7}; + return vreinterpretq_m128i_s16(vld1q_s16((int16_t *) data)); +} + +// Sets the 4 signed 32-bit integer values in reverse order +// https://technet.microsoft.com/en-us/library/security/27yb3ee5(v=vs.90).aspx +FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0) +{ + int32_t ALIGN_STRUCT(16) data[4] = {i3, i2, i1, i0}; + return vreinterpretq_m128i_s32(vld1q_s32(data)); +} + +// Set packed 64-bit integers in dst with the supplied values in reverse order. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_epi64 +FORCE_INLINE __m128i _mm_setr_epi64(__m64 e1, __m64 e0) +{ + return vreinterpretq_m128i_s64(vcombine_s64(e1, e0)); +} + +// Sets the 16 signed 8-bit integer values in reverse order. +// https://msdn.microsoft.com/en-us/library/2khb9c7k(v=vs.90).aspx +FORCE_INLINE __m128i _mm_setr_epi8(signed char b0, + signed char b1, + signed char b2, + signed char b3, + signed char b4, + signed char b5, + signed char b6, + signed char b7, + signed char b8, + signed char b9, + signed char b10, + signed char b11, + signed char b12, + signed char b13, + signed char b14, + signed char b15) +{ + int8_t ALIGN_STRUCT(16) + data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3, + (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7, + (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11, + (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15}; + return (__m128i) vld1q_s8(data); +} + +// Set packed double-precision (64-bit) floating-point elements in dst with the +// supplied values in reverse order. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_pd +FORCE_INLINE __m128d _mm_setr_pd(double e1, double e0) +{ + return _mm_set_pd(e0, e1); +} + +// Return vector of type __m128d with all elements set to zero. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_pd +FORCE_INLINE __m128d _mm_setzero_pd(void) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vdupq_n_f64(0)); +#else + return vreinterpretq_m128d_f32(vdupq_n_f32(0)); +#endif +} + +// Sets the 128-bit value to zero +// https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx +FORCE_INLINE __m128i _mm_setzero_si128(void) +{ + return vreinterpretq_m128i_s32(vdupq_n_s32(0)); +} + +// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm. +// https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx +// FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a, +// __constrange(0,255) int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shuffle_epi32(a, imm) \ + __extension__({ \ + int32x4_t _input = vreinterpretq_s32_m128i(a); \ + int32x4_t _shuf = __builtin_shufflevector( \ + _input, _input, (imm) & (0x3), ((imm) >> 2) & 0x3, \ + ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); \ + vreinterpretq_m128i_s32(_shuf); \ + }) +#else // generic +#define _mm_shuffle_epi32(a, imm) \ + __extension__({ \ + __m128i ret; \ + switch (imm) { \ + case _MM_SHUFFLE(1, 0, 3, 2): \ + ret = _mm_shuffle_epi_1032((a)); \ + break; \ + case _MM_SHUFFLE(2, 3, 0, 1): \ + ret = _mm_shuffle_epi_2301((a)); \ + break; \ + case _MM_SHUFFLE(0, 3, 2, 1): \ + ret = _mm_shuffle_epi_0321((a)); \ + break; \ + case _MM_SHUFFLE(2, 1, 0, 3): \ + ret = _mm_shuffle_epi_2103((a)); \ + break; \ + case _MM_SHUFFLE(1, 0, 1, 0): \ + ret = _mm_shuffle_epi_1010((a)); \ + break; \ + case _MM_SHUFFLE(1, 0, 0, 1): \ + ret = _mm_shuffle_epi_1001((a)); \ + break; \ + case _MM_SHUFFLE(0, 1, 0, 1): \ + ret = _mm_shuffle_epi_0101((a)); \ + break; \ + case _MM_SHUFFLE(2, 2, 1, 1): \ + ret = _mm_shuffle_epi_2211((a)); \ + break; \ + case _MM_SHUFFLE(0, 1, 2, 2): \ + ret = _mm_shuffle_epi_0122((a)); \ + break; \ + case _MM_SHUFFLE(3, 3, 3, 2): \ + ret = _mm_shuffle_epi_3332((a)); \ + break; \ + case _MM_SHUFFLE(0, 0, 0, 0): \ + ret = _mm_shuffle_epi32_splat((a), 0); \ + break; \ + case _MM_SHUFFLE(1, 1, 1, 1): \ + ret = _mm_shuffle_epi32_splat((a), 1); \ + break; \ + case _MM_SHUFFLE(2, 2, 2, 2): \ + ret = _mm_shuffle_epi32_splat((a), 2); \ + break; \ + case _MM_SHUFFLE(3, 3, 3, 3): \ + ret = _mm_shuffle_epi32_splat((a), 3); \ + break; \ + default: \ + ret = _mm_shuffle_epi32_default((a), (imm)); \ + break; \ + } \ + ret; \ + }) +#endif + +// Shuffle double-precision (64-bit) floating-point elements using the control +// in imm8, and store the results in dst. +// +// dst[63:0] := (imm8[0] == 0) ? a[63:0] : a[127:64] +// dst[127:64] := (imm8[1] == 0) ? b[63:0] : b[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pd +#if __has_builtin(__builtin_shufflevector) +#define _mm_shuffle_pd(a, b, imm8) \ + vreinterpretq_m128d_s64(__builtin_shufflevector( \ + vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b), imm8 & 0x1, \ + ((imm8 & 0x2) >> 1) + 2)) +#else +#define _mm_shuffle_pd(a, b, imm8) \ + _mm_castsi128_pd(_mm_set_epi64x( \ + vgetq_lane_s64(vreinterpretq_s64_m128d(b), (imm8 & 0x2) >> 1), \ + vgetq_lane_s64(vreinterpretq_s64_m128d(a), imm8 & 0x1))) +#endif + +// FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a, +// __constrange(0,255) int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shufflehi_epi16(a, imm) \ + __extension__({ \ + int16x8_t _input = vreinterpretq_s16_m128i(a); \ + int16x8_t _shuf = __builtin_shufflevector( \ + _input, _input, 0, 1, 2, 3, ((imm) & (0x3)) + 4, \ + (((imm) >> 2) & 0x3) + 4, (((imm) >> 4) & 0x3) + 4, \ + (((imm) >> 6) & 0x3) + 4); \ + vreinterpretq_m128i_s16(_shuf); \ + }) +#else // generic +#define _mm_shufflehi_epi16(a, imm) _mm_shufflehi_epi16_function((a), (imm)) +#endif + +// FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i a, +// __constrange(0,255) int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shufflelo_epi16(a, imm) \ + __extension__({ \ + int16x8_t _input = vreinterpretq_s16_m128i(a); \ + int16x8_t _shuf = __builtin_shufflevector( \ + _input, _input, ((imm) & (0x3)), (((imm) >> 2) & 0x3), \ + (((imm) >> 4) & 0x3), (((imm) >> 6) & 0x3), 4, 5, 6, 7); \ + vreinterpretq_m128i_s16(_shuf); \ + }) +#else // generic +#define _mm_shufflelo_epi16(a, imm) _mm_shufflelo_epi16_function((a), (imm)) +#endif + +// Shift packed 16-bit integers in a left by count while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF count[63:0] > 15 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := ZeroExtend16(a[i+15:i] << count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sll_epi16 +FORCE_INLINE __m128i _mm_sll_epi16(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (_sse2neon_unlikely(c & ~15)) + return _mm_setzero_si128(); + + int16x8_t vc = vdupq_n_s16((int16_t) c); + return vreinterpretq_m128i_s16(vshlq_s16(vreinterpretq_s16_m128i(a), vc)); +} + +// Shift packed 32-bit integers in a left by count while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF count[63:0] > 31 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := ZeroExtend32(a[i+31:i] << count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sll_epi32 +FORCE_INLINE __m128i _mm_sll_epi32(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (_sse2neon_unlikely(c & ~31)) + return _mm_setzero_si128(); + + int32x4_t vc = vdupq_n_s32((int32_t) c); + return vreinterpretq_m128i_s32(vshlq_s32(vreinterpretq_s32_m128i(a), vc)); +} + +// Shift packed 64-bit integers in a left by count while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// IF count[63:0] > 63 +// dst[i+63:i] := 0 +// ELSE +// dst[i+63:i] := ZeroExtend64(a[i+63:i] << count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sll_epi64 +FORCE_INLINE __m128i _mm_sll_epi64(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (_sse2neon_unlikely(c & ~63)) + return _mm_setzero_si128(); + + int64x2_t vc = vdupq_n_s64((int64_t) c); + return vreinterpretq_m128i_s64(vshlq_s64(vreinterpretq_s64_m128i(a), vc)); +} + +// Shift packed 16-bit integers in a left by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF imm8[7:0] > 15 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := ZeroExtend16(a[i+15:i] << imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_epi16 +FORCE_INLINE __m128i _mm_slli_epi16(__m128i a, int imm) +{ + if (_sse2neon_unlikely(imm & ~15)) + return _mm_setzero_si128(); + return vreinterpretq_m128i_s16( + vshlq_s16(vreinterpretq_s16_m128i(a), vdupq_n_s16(imm))); +} + +// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF imm8[7:0] > 31 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := ZeroExtend32(a[i+31:i] << imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_epi32 +FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, int imm) +{ + if (_sse2neon_unlikely(imm & ~31)) + return _mm_setzero_si128(); + return vreinterpretq_m128i_s32( + vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(imm))); +} + +// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// IF imm8[7:0] > 63 +// dst[i+63:i] := 0 +// ELSE +// dst[i+63:i] := ZeroExtend64(a[i+63:i] << imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_epi64 +FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm) +{ + if (_sse2neon_unlikely(imm & ~63)) + return _mm_setzero_si128(); + return vreinterpretq_m128i_s64( + vshlq_s64(vreinterpretq_s64_m128i(a), vdupq_n_s64(imm))); +} + +// Shift a left by imm8 bytes while shifting in zeros, and store the results in +// dst. +// +// tmp := imm8[7:0] +// IF tmp > 15 +// tmp := 16 +// FI +// dst[127:0] := a[127:0] << (tmp*8) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_slli_si128 +FORCE_INLINE __m128i _mm_slli_si128(__m128i a, int imm) +{ + if (_sse2neon_unlikely(imm & ~15)) + return _mm_setzero_si128(); + uint8x16_t tmp[2] = {vdupq_n_u8(0), vreinterpretq_u8_m128i(a)}; + return vreinterpretq_m128i_u8( + vld1q_u8(((uint8_t const *) tmp) + (16 - imm))); +} + +// Compute the square root of packed double-precision (64-bit) floating-point +// elements in a, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_pd +FORCE_INLINE __m128d _mm_sqrt_pd(__m128d a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vsqrtq_f64(vreinterpretq_f64_m128d(a))); +#else + double a0 = sqrt(((double *) &a)[0]); + double a1 = sqrt(((double *) &a)[1]); + return _mm_set_pd(a1, a0); +#endif +} + +// Compute the square root of the lower double-precision (64-bit) floating-point +// element in b, store the result in the lower element of dst, and copy the +// upper element from a to the upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_sd +FORCE_INLINE __m128d _mm_sqrt_sd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return _mm_move_sd(a, _mm_sqrt_pd(b)); +#else + return _mm_set_pd(((double *) &a)[1], sqrt(((double *) &b)[0])); +#endif +} + +// Shift packed 16-bit integers in a right by count while shifting in sign bits, +// and store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF count[63:0] > 15 +// dst[i+15:i] := (a[i+15] ? 0xFFFF : 0x0) +// ELSE +// dst[i+15:i] := SignExtend16(a[i+15:i] >> count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sra_epi16 +FORCE_INLINE __m128i _mm_sra_epi16(__m128i a, __m128i count) +{ + int64_t c = (int64_t) vget_low_s64((int64x2_t) count); + if (_sse2neon_unlikely(c & ~15)) + return _mm_cmplt_epi16(a, _mm_setzero_si128()); + return vreinterpretq_m128i_s16(vshlq_s16((int16x8_t) a, vdupq_n_s16(-c))); +} + +// Shift packed 32-bit integers in a right by count while shifting in sign bits, +// and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF count[63:0] > 31 +// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0) +// ELSE +// dst[i+31:i] := SignExtend32(a[i+31:i] >> count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sra_epi32 +FORCE_INLINE __m128i _mm_sra_epi32(__m128i a, __m128i count) +{ + int64_t c = (int64_t) vget_low_s64((int64x2_t) count); + if (_sse2neon_unlikely(c & ~31)) + return _mm_cmplt_epi32(a, _mm_setzero_si128()); + return vreinterpretq_m128i_s32(vshlq_s32((int32x4_t) a, vdupq_n_s32(-c))); +} + +// Shift packed 16-bit integers in a right by imm8 while shifting in sign +// bits, and store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF imm8[7:0] > 15 +// dst[i+15:i] := (a[i+15] ? 0xFFFF : 0x0) +// ELSE +// dst[i+15:i] := SignExtend16(a[i+15:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi16 +FORCE_INLINE __m128i _mm_srai_epi16(__m128i a, int imm) +{ + const int count = (imm & ~15) ? 15 : imm; + return (__m128i) vshlq_s16((int16x8_t) a, vdupq_n_s16(-count)); +} + +// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, +// and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF imm8[7:0] > 31 +// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0) +// ELSE +// dst[i+31:i] := SignExtend32(a[i+31:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi32 +// FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm) +#define _mm_srai_epi32(a, imm) \ + __extension__({ \ + __m128i ret; \ + if (_sse2neon_unlikely((imm) == 0)) { \ + ret = a; \ + } else if (_sse2neon_likely(0 < (imm) && (imm) < 32)) { \ + ret = vreinterpretq_m128i_s32( \ + vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-imm))); \ + } else { \ + ret = vreinterpretq_m128i_s32( \ + vshrq_n_s32(vreinterpretq_s32_m128i(a), 31)); \ + } \ + ret; \ + }) + +// Shift packed 16-bit integers in a right by count while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF count[63:0] > 15 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi16 +FORCE_INLINE __m128i _mm_srl_epi16(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (_sse2neon_unlikely(c & ~15)) + return _mm_setzero_si128(); + + int16x8_t vc = vdupq_n_s16(-(int16_t) c); + return vreinterpretq_m128i_u16(vshlq_u16(vreinterpretq_u16_m128i(a), vc)); +} + +// Shift packed 32-bit integers in a right by count while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF count[63:0] > 31 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi32 +FORCE_INLINE __m128i _mm_srl_epi32(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (_sse2neon_unlikely(c & ~31)) + return _mm_setzero_si128(); + + int32x4_t vc = vdupq_n_s32(-(int32_t) c); + return vreinterpretq_m128i_u32(vshlq_u32(vreinterpretq_u32_m128i(a), vc)); +} + +// Shift packed 64-bit integers in a right by count while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// IF count[63:0] > 63 +// dst[i+63:i] := 0 +// ELSE +// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> count[63:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srl_epi64 +FORCE_INLINE __m128i _mm_srl_epi64(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (_sse2neon_unlikely(c & ~63)) + return _mm_setzero_si128(); + + int64x2_t vc = vdupq_n_s64(-(int64_t) c); + return vreinterpretq_m128i_u64(vshlq_u64(vreinterpretq_u64_m128i(a), vc)); +} + +// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF imm8[7:0] > 15 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi16 +#define _mm_srli_epi16(a, imm) \ + __extension__({ \ + __m128i ret; \ + if (_sse2neon_unlikely(imm & ~15)) { \ + ret = _mm_setzero_si128(); \ + } else { \ + ret = vreinterpretq_m128i_u16( \ + vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-imm))); \ + } \ + ret; \ + }) + +// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF imm8[7:0] > 31 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi32 +// FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm) +#define _mm_srli_epi32(a, imm) \ + __extension__({ \ + __m128i ret; \ + if (_sse2neon_unlikely(imm & ~31)) { \ + ret = _mm_setzero_si128(); \ + } else { \ + ret = vreinterpretq_m128i_u32( \ + vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-imm))); \ + } \ + ret; \ + }) + +// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// IF imm8[7:0] > 63 +// dst[i+63:i] := 0 +// ELSE +// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi64 +#define _mm_srli_epi64(a, imm) \ + __extension__({ \ + __m128i ret; \ + if (_sse2neon_unlikely(imm & ~63)) { \ + ret = _mm_setzero_si128(); \ + } else { \ + ret = vreinterpretq_m128i_u64( \ + vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-imm))); \ + } \ + ret; \ + }) + +// Shift a right by imm8 bytes while shifting in zeros, and store the results in +// dst. +// +// tmp := imm8[7:0] +// IF tmp > 15 +// tmp := 16 +// FI +// dst[127:0] := a[127:0] >> (tmp*8) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_si128 +FORCE_INLINE __m128i _mm_srli_si128(__m128i a, int imm) +{ + if (_sse2neon_unlikely(imm & ~15)) + return _mm_setzero_si128(); + uint8x16_t tmp[2] = {vreinterpretq_u8_m128i(a), vdupq_n_u8(0)}; + return vreinterpretq_m128i_u8(vld1q_u8(((uint8_t const *) tmp) + imm)); +} + +// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point +// elements) from a into memory. mem_addr must be aligned on a 16-byte boundary +// or a general-protection exception may be generated. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd +FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a) +{ +#if defined(__aarch64__) + vst1q_f64((float64_t *) mem_addr, vreinterpretq_f64_m128d(a)); +#else + vst1q_f32((float32_t *) mem_addr, vreinterpretq_f32_m128d(a)); +#endif +} + +// Store the lower double-precision (64-bit) floating-point element from a into +// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte +// boundary or a general-protection exception may be generated. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd1 +FORCE_INLINE void _mm_store_pd1(double *mem_addr, __m128d a) +{ +#if defined(__aarch64__) + float64x1_t a_low = vget_low_f64(vreinterpretq_f64_m128d(a)); + vst1q_f64((float64_t *) mem_addr, + vreinterpretq_f64_m128d(vcombine_f64(a_low, a_low))); +#else + float32x2_t a_low = vget_low_f32(vreinterpretq_f32_m128d(a)); + vst1q_f32((float32_t *) mem_addr, + vreinterpretq_f32_m128d(vcombine_f32(a_low, a_low))); +#endif +} + +// Store the lower double-precision (64-bit) floating-point element from a into +// memory. mem_addr does not need to be aligned on any particular boundary. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_store_sd +FORCE_INLINE void _mm_store_sd(double *mem_addr, __m128d a) +{ +#if defined(__aarch64__) + vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a))); +#else + vst1_u64((uint64_t *) mem_addr, vget_low_u64(vreinterpretq_u64_m128d(a))); +#endif +} + +// Stores four 32-bit integer values as (as a __m128i value) at the address p. +// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx +FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a) +{ + vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a)); +} + +// Store the lower double-precision (64-bit) floating-point element from a into +// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte +// boundary or a general-protection exception may be generated. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=9,526,5601&text=_mm_store1_pd +#define _mm_store1_pd _mm_store_pd1 + +// Store the upper double-precision (64-bit) floating-point element from a into +// memory. +// +// MEM[mem_addr+63:mem_addr] := a[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeh_pd +FORCE_INLINE void _mm_storeh_pd(double *mem_addr, __m128d a) +{ +#if defined(__aarch64__) + vst1_f64((float64_t *) mem_addr, vget_high_f64(vreinterpretq_f64_m128d(a))); +#else + vst1_f32((float32_t *) mem_addr, vget_high_f32(vreinterpretq_f32_m128d(a))); +#endif +} + +// Reads the lower 64 bits of b and stores them into the lower 64 bits of a. +// https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx +FORCE_INLINE void _mm_storel_epi64(__m128i *a, __m128i b) +{ + uint64x1_t hi = vget_high_u64(vreinterpretq_u64_m128i(*a)); + uint64x1_t lo = vget_low_u64(vreinterpretq_u64_m128i(b)); + *a = vreinterpretq_m128i_u64(vcombine_u64(lo, hi)); +} + +// Store the lower double-precision (64-bit) floating-point element from a into +// memory. +// +// MEM[mem_addr+63:mem_addr] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storel_pd +FORCE_INLINE void _mm_storel_pd(double *mem_addr, __m128d a) +{ +#if defined(__aarch64__) + vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a))); +#else + vst1_f32((float32_t *) mem_addr, vget_low_f32(vreinterpretq_f32_m128d(a))); +#endif +} + +// Store 2 double-precision (64-bit) floating-point elements from a into memory +// in reverse order. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// MEM[mem_addr+63:mem_addr] := a[127:64] +// MEM[mem_addr+127:mem_addr+64] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storer_pd +FORCE_INLINE void _mm_storer_pd(double *mem_addr, __m128d a) +{ + float32x4_t f = vreinterpretq_f32_m128d(a); + _mm_store_pd(mem_addr, vreinterpretq_m128d_f32(vextq_f32(f, f, 2))); +} + +// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point +// elements) from a into memory. mem_addr does not need to be aligned on any +// particular boundary. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_pd +FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a) +{ + _mm_store_pd(mem_addr, a); +} + +// Stores 128-bits of integer data a at the address p. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si128 +FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a) +{ + vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a)); +} + +// Stores 32-bits of integer data a at the address p. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si32 +FORCE_INLINE void _mm_storeu_si32(void *p, __m128i a) +{ + vst1q_lane_s32((int32_t *) p, vreinterpretq_s32_m128i(a), 0); +} + +// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point +// elements) from a into memory using a non-temporal memory hint. mem_addr must +// be aligned on a 16-byte boundary or a general-protection exception may be +// generated. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_pd +FORCE_INLINE void _mm_stream_pd(double *p, __m128d a) +{ +#if __has_builtin(__builtin_nontemporal_store) + __builtin_nontemporal_store(a, (float32x4_t *) p); +#elif defined(__aarch64__) + vst1q_f64(p, vreinterpretq_f64_m128d(a)); +#else + vst1q_s64((int64_t *) p, vreinterpretq_s64_m128d(a)); +#endif +} + +// Stores the data in a to the address p without polluting the caches. If the +// cache line containing address p is already in the cache, the cache will be +// updated. +// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx +FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a) +{ +#if __has_builtin(__builtin_nontemporal_store) + __builtin_nontemporal_store(a, p); +#else + vst1q_s64((int64_t *) p, vreinterpretq_s64_m128i(a)); +#endif +} + +// Store 32-bit integer a into memory using a non-temporal hint to minimize +// cache pollution. If the cache line containing address mem_addr is already in +// the cache, the cache will be updated. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_si32 +FORCE_INLINE void _mm_stream_si32(int *p, int a) +{ + vst1q_lane_s32((int32_t *) p, vdupq_n_s32(a), 0); +} + +// Subtract packed 16-bit integers in b from packed 16-bit integers in a, and +// store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi16 +FORCE_INLINE __m128i _mm_sub_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or +// unsigned 32-bit integers of a. +// +// r0 := a0 - b0 +// r1 := a1 - b1 +// r2 := a2 - b2 +// r3 := a3 - b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx +FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vsubq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Subtract 2 packed 64-bit integers in b from 2 packed 64-bit integers in a, +// and store the results in dst. +// r0 := a0 - b0 +// r1 := a1 - b1 +FORCE_INLINE __m128i _mm_sub_epi64(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s64( + vsubq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b))); +} + +// Subtract packed 8-bit integers in b from packed 8-bit integers in a, and +// store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_epi8 +FORCE_INLINE __m128i _mm_sub_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Subtract packed double-precision (64-bit) floating-point elements in b from +// packed double-precision (64-bit) floating-point elements in a, and store the +// results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := a[i+63:i] - b[i+63:i] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_sub_pd +FORCE_INLINE __m128d _mm_sub_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vsubq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] - db[0]; + c[1] = da[1] - db[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Subtract the lower double-precision (64-bit) floating-point element in b from +// the lower double-precision (64-bit) floating-point element in a, store the +// result in the lower element of dst, and copy the upper element from a to the +// upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_sd +FORCE_INLINE __m128d _mm_sub_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_sub_pd(a, b)); +} + +// Subtract 64-bit integer b from 64-bit integer a, and store the result in dst. +// +// dst[63:0] := a[63:0] - b[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_si64 +FORCE_INLINE __m64 _mm_sub_si64(__m64 a, __m64 b) +{ + return vreinterpret_m64_s64( + vsub_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b))); +} + +// Subtracts the 8 signed 16-bit integers of b from the 8 signed 16-bit integers +// of a and saturates. +// +// r0 := SignedSaturate(a0 - b0) +// r1 := SignedSaturate(a1 - b1) +// ... +// r7 := SignedSaturate(a7 - b7) +// +// https://technet.microsoft.com/en-us/subscriptions/3247z5b8(v=vs.90) +FORCE_INLINE __m128i _mm_subs_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vqsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers +// of a and saturates. +// +// r0 := SignedSaturate(a0 - b0) +// r1 := SignedSaturate(a1 - b1) +// ... +// r15 := SignedSaturate(a15 - b15) +// +// https://technet.microsoft.com/en-us/subscriptions/by7kzks1(v=vs.90) +FORCE_INLINE __m128i _mm_subs_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vqsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Subtracts the 8 unsigned 16-bit integers of bfrom the 8 unsigned 16-bit +// integers of a and saturates.. +// https://technet.microsoft.com/en-us/subscriptions/index/f44y0s19(v=vs.90).aspx +FORCE_INLINE __m128i _mm_subs_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vqsubq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Subtracts the 16 unsigned 8-bit integers of b from the 16 unsigned 8-bit +// integers of a and saturates. +// +// r0 := UnsignedSaturate(a0 - b0) +// r1 := UnsignedSaturate(a1 - b1) +// ... +// r15 := UnsignedSaturate(a15 - b15) +// +// https://technet.microsoft.com/en-us/subscriptions/yadkxc18(v=vs.90) +FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vqsubq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +#define _mm_ucomieq_sd _mm_comieq_sd +#define _mm_ucomige_sd _mm_comige_sd +#define _mm_ucomigt_sd _mm_comigt_sd +#define _mm_ucomile_sd _mm_comile_sd +#define _mm_ucomilt_sd _mm_comilt_sd +#define _mm_ucomineq_sd _mm_comineq_sd + +// Return vector of type __m128d with undefined elements. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_pd +FORCE_INLINE __m128d _mm_undefined_pd(void) +{ +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + __m128d a; + return a; +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif +} + +// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the +// upper 4 signed or unsigned 16-bit integers in b. +// +// r0 := a4 +// r1 := b4 +// r2 := a5 +// r3 := b5 +// r4 := a6 +// r5 := b6 +// r6 := a7 +// r7 := b7 +// +// https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s16( + vzip2q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +#else + int16x4_t a1 = vget_high_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b1 = vget_high_s16(vreinterpretq_s16_m128i(b)); + int16x4x2_t result = vzip_s16(a1, b1); + return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1])); +#endif +} + +// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the +// upper 2 signed or unsigned 32-bit integers in b. +// https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s32( + vzip2q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +#else + int32x2_t a1 = vget_high_s32(vreinterpretq_s32_m128i(a)); + int32x2_t b1 = vget_high_s32(vreinterpretq_s32_m128i(b)); + int32x2x2_t result = vzip_s32(a1, b1); + return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1])); +#endif +} + +// Interleaves the upper signed or unsigned 64-bit integer in a with the +// upper signed or unsigned 64-bit integer in b. +// +// r0 := a1 +// r1 := b1 +FORCE_INLINE __m128i _mm_unpackhi_epi64(__m128i a, __m128i b) +{ + int64x1_t a_h = vget_high_s64(vreinterpretq_s64_m128i(a)); + int64x1_t b_h = vget_high_s64(vreinterpretq_s64_m128i(b)); + return vreinterpretq_m128i_s64(vcombine_s64(a_h, b_h)); +} + +// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper +// 8 signed or unsigned 8-bit integers in b. +// +// r0 := a8 +// r1 := b8 +// r2 := a9 +// r3 := b9 +// ... +// r14 := a15 +// r15 := b15 +// +// https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s8( + vzip2q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +#else + int8x8_t a1 = + vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(a))); + int8x8_t b1 = + vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(b))); + int8x8x2_t result = vzip_s8(a1, b1); + return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1])); +#endif +} + +// Unpack and interleave double-precision (64-bit) floating-point elements from +// the high half of a and b, and store the results in dst. +// +// DEFINE INTERLEAVE_HIGH_QWORDS(src1[127:0], src2[127:0]) { +// dst[63:0] := src1[127:64] +// dst[127:64] := src2[127:64] +// RETURN dst[127:0] +// } +// dst[127:0] := INTERLEAVE_HIGH_QWORDS(a[127:0], b[127:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpackhi_pd +FORCE_INLINE __m128d _mm_unpackhi_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vzip2q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + return vreinterpretq_m128d_s64( + vcombine_s64(vget_high_s64(vreinterpretq_s64_m128d(a)), + vget_high_s64(vreinterpretq_s64_m128d(b)))); +#endif +} + +// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the +// lower 4 signed or unsigned 16-bit integers in b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// r4 := a2 +// r5 := b2 +// r6 := a3 +// r7 := b3 +// +// https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s16( + vzip1q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +#else + int16x4_t a1 = vget_low_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b1 = vget_low_s16(vreinterpretq_s16_m128i(b)); + int16x4x2_t result = vzip_s16(a1, b1); + return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1])); +#endif +} + +// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the +// lower 2 signed or unsigned 32 - bit integers in b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// +// https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s32( + vzip1q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +#else + int32x2_t a1 = vget_low_s32(vreinterpretq_s32_m128i(a)); + int32x2_t b1 = vget_low_s32(vreinterpretq_s32_m128i(b)); + int32x2x2_t result = vzip_s32(a1, b1); + return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1])); +#endif +} + +FORCE_INLINE __m128i _mm_unpacklo_epi64(__m128i a, __m128i b) +{ + int64x1_t a_l = vget_low_s64(vreinterpretq_s64_m128i(a)); + int64x1_t b_l = vget_low_s64(vreinterpretq_s64_m128i(b)); + return vreinterpretq_m128i_s64(vcombine_s64(a_l, b_l)); +} + +// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower +// 8 signed or unsigned 8-bit integers in b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// ... +// r14 := a7 +// r15 := b7 +// +// https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s8( + vzip1q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +#else + int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(a))); + int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(b))); + int8x8x2_t result = vzip_s8(a1, b1); + return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1])); +#endif +} + +// Unpack and interleave double-precision (64-bit) floating-point elements from +// the low half of a and b, and store the results in dst. +// +// DEFINE INTERLEAVE_QWORDS(src1[127:0], src2[127:0]) { +// dst[63:0] := src1[63:0] +// dst[127:64] := src2[63:0] +// RETURN dst[127:0] +// } +// dst[127:0] := INTERLEAVE_QWORDS(a[127:0], b[127:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_unpacklo_pd +FORCE_INLINE __m128d _mm_unpacklo_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vzip1q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + return vreinterpretq_m128d_s64( + vcombine_s64(vget_low_s64(vreinterpretq_s64_m128d(a)), + vget_low_s64(vreinterpretq_s64_m128d(b)))); +#endif +} + +// Compute the bitwise XOR of packed double-precision (64-bit) floating-point +// elements in a and b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := a[i+63:i] XOR b[i+63:i] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_pd +FORCE_INLINE __m128d _mm_xor_pd(__m128d a, __m128d b) +{ + return vreinterpretq_m128d_s64( + veorq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b))); +} + +// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in +// b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx +FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +/* SSE3 */ + +// Alternatively add and subtract packed double-precision (64-bit) +// floating-point elements in a to/from packed elements in b, and store the +// results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// IF ((j & 1) == 0) +// dst[i+63:i] := a[i+63:i] - b[i+63:i] +// ELSE +// dst[i+63:i] := a[i+63:i] + b[i+63:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_addsub_pd +FORCE_INLINE __m128d _mm_addsub_pd(__m128d a, __m128d b) +{ + __m128d mask = _mm_set_pd(1.0f, -1.0f); +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vfmaq_f64(vreinterpretq_f64_m128d(a), + vreinterpretq_f64_m128d(b), + vreinterpretq_f64_m128d(mask))); +#else + return _mm_add_pd(_mm_mul_pd(b, mask), a); +#endif +} + +// Alternatively add and subtract packed single-precision (32-bit) +// floating-point elements in a to/from packed elements in b, and store the +// results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=addsub_ps +FORCE_INLINE __m128 _mm_addsub_ps(__m128 a, __m128 b) +{ + __m128 mask = {-1.0f, 1.0f, -1.0f, 1.0f}; +#if defined(__aarch64__) || defined(__ARM_FEATURE_FMA) /* VFPv4+ */ + return vreinterpretq_m128_f32(vfmaq_f32(vreinterpretq_f32_m128(a), + vreinterpretq_f32_m128(mask), + vreinterpretq_f32_m128(b))); +#else + return _mm_add_ps(_mm_mul_ps(b, mask), a); +#endif +} + +// Horizontally add adjacent pairs of double-precision (64-bit) floating-point +// elements in a and b, and pack the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pd +FORCE_INLINE __m128d _mm_hadd_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vpaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[] = {da[0] + da[1], db[0] + db[1]}; + return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c)); +#endif +} + +// Computes pairwise add of each argument as single-precision, floating-point +// values a and b. +// https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx +FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32( + vcombine_f32(vpadd_f32(a10, a32), vpadd_f32(b10, b32))); +#endif +} + +// Horizontally subtract adjacent pairs of double-precision (64-bit) +// floating-point elements in a and b, and pack the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_pd +FORCE_INLINE __m128d _mm_hsub_pd(__m128d _a, __m128d _b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vsubq_f64( + vuzp1q_f64(vreinterpretq_f64_m128d(_a), vreinterpretq_f64_m128d(_b)), + vuzp2q_f64(vreinterpretq_f64_m128d(_a), vreinterpretq_f64_m128d(_b)))); +#else + double *da = (double *) &_a; + double *db = (double *) &_b; + double c[] = {da[0] - da[1], db[0] - db[1]}; + return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c)); +#endif +} + +// Horizontally substract adjacent pairs of single-precision (32-bit) +// floating-point elements in a and b, and pack the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_ps +FORCE_INLINE __m128 _mm_hsub_ps(__m128 _a, __m128 _b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vsubq_f32( + vuzp1q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)), + vuzp2q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)))); +#else + float32x4x2_t c = + vuzpq_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)); + return vreinterpretq_m128_f32(vsubq_f32(c.val[0], c.val[1])); +#endif +} + +// Load 128-bits of integer data from unaligned memory into dst. This intrinsic +// may perform better than _mm_loadu_si128 when the data crosses a cache line +// boundary. +// +// dst[127:0] := MEM[mem_addr+127:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128 +#define _mm_lddqu_si128 _mm_loadu_si128 + +// Load a double-precision (64-bit) floating-point element from memory into both +// elements of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loaddup_pd +#define _mm_loaddup_pd _mm_load1_pd + +// Duplicate the low double-precision (64-bit) floating-point element from a, +// and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movedup_pd +FORCE_INLINE __m128d _mm_movedup_pd(__m128d a) +{ +#if (__aarch64__) + return vreinterpretq_m128d_f64( + vdupq_laneq_f64(vreinterpretq_f64_m128d(a), 0)); +#else + return vreinterpretq_m128d_u64( + vdupq_n_u64(vgetq_lane_u64(vreinterpretq_u64_m128d(a), 0))); +#endif +} + +// Duplicate odd-indexed single-precision (32-bit) floating-point elements +// from a, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movehdup_ps +FORCE_INLINE __m128 _mm_movehdup_ps(__m128 a) +{ +#if __has_builtin(__builtin_shufflevector) + return vreinterpretq_m128_f32(__builtin_shufflevector( + vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 1, 1, 3, 3)); +#else + float32_t a1 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 1); + float32_t a3 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 3); + float ALIGN_STRUCT(16) data[4] = {a1, a1, a3, a3}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +#endif +} + +// Duplicate even-indexed single-precision (32-bit) floating-point elements +// from a, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_moveldup_ps +FORCE_INLINE __m128 _mm_moveldup_ps(__m128 a) +{ +#if __has_builtin(__builtin_shufflevector) + return vreinterpretq_m128_f32(__builtin_shufflevector( + vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 0, 0, 2, 2)); +#else + float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + float32_t a2 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 2); + float ALIGN_STRUCT(16) data[4] = {a0, a0, a2, a2}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +#endif +} + +/* SSSE3 */ + +// Compute the absolute value of packed signed 16-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// dst[i+15:i] := ABS(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi16 +FORCE_INLINE __m128i _mm_abs_epi16(__m128i a) +{ + return vreinterpretq_m128i_s16(vabsq_s16(vreinterpretq_s16_m128i(a))); +} + +// Compute the absolute value of packed signed 32-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// dst[i+31:i] := ABS(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi32 +FORCE_INLINE __m128i _mm_abs_epi32(__m128i a) +{ + return vreinterpretq_m128i_s32(vabsq_s32(vreinterpretq_s32_m128i(a))); +} + +// Compute the absolute value of packed signed 8-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 15 +// i := j*8 +// dst[i+7:i] := ABS(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi8 +FORCE_INLINE __m128i _mm_abs_epi8(__m128i a) +{ + return vreinterpretq_m128i_s8(vabsq_s8(vreinterpretq_s8_m128i(a))); +} + +// Compute the absolute value of packed signed 16-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := ABS(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi16 +FORCE_INLINE __m64 _mm_abs_pi16(__m64 a) +{ + return vreinterpret_m64_s16(vabs_s16(vreinterpret_s16_m64(a))); +} + +// Compute the absolute value of packed signed 32-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 1 +// i := j*32 +// dst[i+31:i] := ABS(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi32 +FORCE_INLINE __m64 _mm_abs_pi32(__m64 a) +{ + return vreinterpret_m64_s32(vabs_s32(vreinterpret_s32_m64(a))); +} + +// Compute the absolute value of packed signed 8-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := ABS(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi8 +FORCE_INLINE __m64 _mm_abs_pi8(__m64 a) +{ + return vreinterpret_m64_s8(vabs_s8(vreinterpret_s8_m64(a))); +} + +// Concatenate 16-byte blocks in a and b into a 32-byte temporary result, shift +// the result right by imm8 bytes, and store the low 16 bytes in dst. +// +// tmp[255:0] := ((a[127:0] << 128)[255:0] OR b[127:0]) >> (imm8*8) +// dst[127:0] := tmp[127:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_epi8 +FORCE_INLINE __m128i _mm_alignr_epi8(__m128i a, __m128i b, int imm) +{ + if (_sse2neon_unlikely(imm & ~31)) + return _mm_setzero_si128(); + int idx; + uint8x16_t tmp[2]; + if (imm >= 16) { + idx = imm - 16; + tmp[0] = vreinterpretq_u8_m128i(a); + tmp[1] = vdupq_n_u8(0); + } else { + idx = imm; + tmp[0] = vreinterpretq_u8_m128i(b); + tmp[1] = vreinterpretq_u8_m128i(a); + } + return vreinterpretq_m128i_u8(vld1q_u8(((uint8_t const *) tmp) + idx)); +} + +// Concatenate 8-byte blocks in a and b into a 16-byte temporary result, shift +// the result right by imm8 bytes, and store the low 8 bytes in dst. +// +// tmp[127:0] := ((a[63:0] << 64)[127:0] OR b[63:0]) >> (imm8*8) +// dst[63:0] := tmp[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_pi8 +#define _mm_alignr_pi8(a, b, imm) \ + __extension__({ \ + __m64 ret; \ + if (_sse2neon_unlikely((imm) >= 16)) { \ + ret = vreinterpret_m64_s8(vdup_n_s8(0)); \ + } else { \ + uint8x8_t tmp_low, tmp_high; \ + if (imm >= 8) { \ + const int idx = imm - 8; \ + tmp_low = vreinterpret_u8_m64(a); \ + tmp_high = vdup_n_u8(0); \ + ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \ + } else { \ + const int idx = imm; \ + tmp_low = vreinterpret_u8_m64(b); \ + tmp_high = vreinterpret_u8_m64(a); \ + ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \ + } \ + } \ + ret; \ + }) + +// Computes pairwise add of each argument as a 16-bit signed or unsigned integer +// values a and b. +FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b) +{ + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); +#if defined(__aarch64__) + return vreinterpretq_m128i_s16(vpaddq_s16(a, b)); +#else + return vreinterpretq_m128i_s16( + vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)), + vpadd_s16(vget_low_s16(b), vget_high_s16(b)))); +#endif +} + +// Computes pairwise add of each argument as a 32-bit signed or unsigned integer +// values a and b. +FORCE_INLINE __m128i _mm_hadd_epi32(__m128i _a, __m128i _b) +{ + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + return vreinterpretq_m128i_s32( + vcombine_s32(vpadd_s32(vget_low_s32(a), vget_high_s32(a)), + vpadd_s32(vget_low_s32(b), vget_high_s32(b)))); +} + +// Horizontally add adjacent pairs of 16-bit integers in a and b, and pack the +// signed 16-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi16 +FORCE_INLINE __m64 _mm_hadd_pi16(__m64 a, __m64 b) +{ + return vreinterpret_m64_s16( + vpadd_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b))); +} + +// Horizontally add adjacent pairs of 32-bit integers in a and b, and pack the +// signed 32-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi32 +FORCE_INLINE __m64 _mm_hadd_pi32(__m64 a, __m64 b) +{ + return vreinterpret_m64_s32( + vpadd_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b))); +} + +// Computes saturated pairwise sub of each argument as a 16-bit signed +// integer values a and b. +FORCE_INLINE __m128i _mm_hadds_epi16(__m128i _a, __m128i _b) +{ +#if defined(__aarch64__) + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + return vreinterpretq_s64_s16( + vqaddq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b))); +#else + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|a4|a6|b0|b2|b4|b6] + // [a1|a3|a5|a7|b1|b3|b5|b7] + int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b)); + int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16)); + // Saturated add + return vreinterpretq_m128i_s16(vqaddq_s16(ab0246, ab1357)); +#endif +} + +// Horizontally add adjacent pairs of signed 16-bit integers in a and b using +// saturation, and pack the signed 16-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadds_pi16 +FORCE_INLINE __m64 _mm_hadds_pi16(__m64 _a, __m64 _b) +{ + int16x4_t a = vreinterpret_s16_m64(_a); + int16x4_t b = vreinterpret_s16_m64(_b); +#if defined(__aarch64__) + return vreinterpret_s64_s16(vqadd_s16(vuzp1_s16(a, b), vuzp2_s16(a, b))); +#else + int16x4x2_t res = vuzp_s16(a, b); + return vreinterpret_s64_s16(vqadd_s16(res.val[0], res.val[1])); +#endif +} + +// Computes pairwise difference of each argument as a 16-bit signed or unsigned +// integer values a and b. +FORCE_INLINE __m128i _mm_hsub_epi16(__m128i _a, __m128i _b) +{ + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|a4|a6|b0|b2|b4|b6] + // [a1|a3|a5|a7|b1|b3|b5|b7] + int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b)); + int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16)); + // Subtract + return vreinterpretq_m128i_s16(vsubq_s16(ab0246, ab1357)); +} + +// Computes pairwise difference of each argument as a 32-bit signed or unsigned +// integer values a and b. +FORCE_INLINE __m128i _mm_hsub_epi32(__m128i _a, __m128i _b) +{ + int64x2_t a = vreinterpretq_s64_m128i(_a); + int64x2_t b = vreinterpretq_s64_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|b0|b2] + // [a1|a2|b1|b3] + int32x4_t ab02 = vcombine_s32(vmovn_s64(a), vmovn_s64(b)); + int32x4_t ab13 = vcombine_s32(vshrn_n_s64(a, 32), vshrn_n_s64(b, 32)); + // Subtract + return vreinterpretq_m128i_s32(vsubq_s32(ab02, ab13)); +} + +// Horizontally subtract adjacent pairs of 16-bit integers in a and b, and pack +// the signed 16-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_pi16 +FORCE_INLINE __m64 _mm_hsub_pi16(__m64 _a, __m64 _b) +{ + int32x4_t ab = + vcombine_s32(vreinterpret_s32_m64(_a), vreinterpret_s32_m64(_b)); + + int16x4_t ab_low_bits = vmovn_s32(ab); + int16x4_t ab_high_bits = vshrn_n_s32(ab, 16); + + return vreinterpret_m64_s16(vsub_s16(ab_low_bits, ab_high_bits)); +} + +// Horizontally subtract adjacent pairs of 32-bit integers in a and b, and pack +// the signed 32-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_hsub_pi32 +FORCE_INLINE __m64 _mm_hsub_pi32(__m64 _a, __m64 _b) +{ +#if defined(__aarch64__) + int32x2_t a = vreinterpret_s32_m64(_a); + int32x2_t b = vreinterpret_s32_m64(_b); + return vreinterpret_m64_s32(vsub_s32(vtrn1_s32(a, b), vtrn2_s32(a, b))); +#else + int32x2x2_t trn_ab = + vtrn_s32(vreinterpret_s32_m64(_a), vreinterpret_s32_m64(_b)); + return vreinterpret_m64_s32(vsub_s32(trn_ab.val[0], trn_ab.val[1])); +#endif +} + +// Computes saturated pairwise difference of each argument as a 16-bit signed +// integer values a and b. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_epi16 +FORCE_INLINE __m128i _mm_hsubs_epi16(__m128i _a, __m128i _b) +{ +#if defined(__aarch64__) + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + return vreinterpretq_s64_s16( + vqsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b))); +#else + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|a4|a6|b0|b2|b4|b6] + // [a1|a3|a5|a7|b1|b3|b5|b7] + int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b)); + int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16)); + // Saturated subtract + return vreinterpretq_m128i_s16(vqsubq_s16(ab0246, ab1357)); +#endif +} + +// Horizontally subtract adjacent pairs of signed 16-bit integers in a and b +// using saturation, and pack the signed 16-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_pi16 +FORCE_INLINE __m64 _mm_hsubs_pi16(__m64 _a, __m64 _b) +{ + int16x4_t a = vreinterpret_s16_m64(_a); + int16x4_t b = vreinterpret_s16_m64(_b); +#if defined(__aarch64__) + return vreinterpret_s64_s16(vqsub_s16(vuzp1_s16(a, b), vuzp2_s16(a, b))); +#else + int16x4x2_t res = vuzp_s16(a, b); + return vreinterpret_s64_s16(vqsub_s16(res.val[0], res.val[1])); +#endif +} + +// Vertically multiply each unsigned 8-bit integer from a with the corresponding +// signed 8-bit integer from b, producing intermediate signed 16-bit integers. +// Horizontally add adjacent pairs of intermediate signed 16-bit integers, +// and pack the saturated results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// dst[i+15:i] := Saturate_To_Int16( a[i+15:i+8]*b[i+15:i+8] + +// a[i+7:i]*b[i+7:i] ) +// ENDFOR +FORCE_INLINE __m128i _mm_maddubs_epi16(__m128i _a, __m128i _b) +{ +#if defined(__aarch64__) + uint8x16_t a = vreinterpretq_u8_m128i(_a); + int8x16_t b = vreinterpretq_s8_m128i(_b); + int16x8_t tl = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(a))), + vmovl_s8(vget_low_s8(b))); + int16x8_t th = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(a))), + vmovl_s8(vget_high_s8(b))); + return vreinterpretq_m128i_s16( + vqaddq_s16(vuzp1q_s16(tl, th), vuzp2q_s16(tl, th))); +#else + // This would be much simpler if x86 would choose to zero extend OR sign + // extend, not both. This could probably be optimized better. + uint16x8_t a = vreinterpretq_u16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + + // Zero extend a + int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a, 8)); + int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a, vdupq_n_u16(0xff00))); + + // Sign extend by shifting left then shifting right. + int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b, 8), 8); + int16x8_t b_odd = vshrq_n_s16(b, 8); + + // multiply + int16x8_t prod1 = vmulq_s16(a_even, b_even); + int16x8_t prod2 = vmulq_s16(a_odd, b_odd); + + // saturated add + return vreinterpretq_m128i_s16(vqaddq_s16(prod1, prod2)); +#endif +} + +// Vertically multiply each unsigned 8-bit integer from a with the corresponding +// signed 8-bit integer from b, producing intermediate signed 16-bit integers. +// Horizontally add adjacent pairs of intermediate signed 16-bit integers, and +// pack the saturated results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maddubs_pi16 +FORCE_INLINE __m64 _mm_maddubs_pi16(__m64 _a, __m64 _b) +{ + uint16x4_t a = vreinterpret_u16_m64(_a); + int16x4_t b = vreinterpret_s16_m64(_b); + + // Zero extend a + int16x4_t a_odd = vreinterpret_s16_u16(vshr_n_u16(a, 8)); + int16x4_t a_even = vreinterpret_s16_u16(vand_u16(a, vdup_n_u16(0xff))); + + // Sign extend by shifting left then shifting right. + int16x4_t b_even = vshr_n_s16(vshl_n_s16(b, 8), 8); + int16x4_t b_odd = vshr_n_s16(b, 8); + + // multiply + int16x4_t prod1 = vmul_s16(a_even, b_even); + int16x4_t prod2 = vmul_s16(a_odd, b_odd); + + // saturated add + return vreinterpret_m64_s16(vqadd_s16(prod1, prod2)); +} + +// Multiply packed signed 16-bit integers in a and b, producing intermediate +// signed 32-bit integers. Shift right by 15 bits while rounding up, and store +// the packed 16-bit integers in dst. +// +// r0 := Round(((int32_t)a0 * (int32_t)b0) >> 15) +// r1 := Round(((int32_t)a1 * (int32_t)b1) >> 15) +// r2 := Round(((int32_t)a2 * (int32_t)b2) >> 15) +// ... +// r7 := Round(((int32_t)a7 * (int32_t)b7) >> 15) +FORCE_INLINE __m128i _mm_mulhrs_epi16(__m128i a, __m128i b) +{ + // Has issues due to saturation + // return vreinterpretq_m128i_s16(vqrdmulhq_s16(a, b)); + + // Multiply + int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)), + vget_low_s16(vreinterpretq_s16_m128i(b))); + int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)), + vget_high_s16(vreinterpretq_s16_m128i(b))); + + // Rounding narrowing shift right + // narrow = (int16_t)((mul + 16384) >> 15); + int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15); + int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15); + + // Join together + return vreinterpretq_m128i_s16(vcombine_s16(narrow_lo, narrow_hi)); +} + +// Multiply packed signed 16-bit integers in a and b, producing intermediate +// signed 32-bit integers. Truncate each intermediate integer to the 18 most +// significant bits, round by adding 1, and store bits [16:1] to dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhrs_pi16 +FORCE_INLINE __m64 _mm_mulhrs_pi16(__m64 a, __m64 b) +{ + int32x4_t mul_extend = + vmull_s16((vreinterpret_s16_m64(a)), (vreinterpret_s16_m64(b))); + + // Rounding narrowing shift right + return vreinterpret_m64_s16(vrshrn_n_s32(mul_extend, 15)); +} + +// Shuffle packed 8-bit integers in a according to shuffle control mask in the +// corresponding 8-bit element of b, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_epi8 +FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b) +{ + int8x16_t tbl = vreinterpretq_s8_m128i(a); // input a + uint8x16_t idx = vreinterpretq_u8_m128i(b); // input b + uint8x16_t idx_masked = + vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits +#if defined(__aarch64__) + return vreinterpretq_m128i_s8(vqtbl1q_s8(tbl, idx_masked)); +#elif defined(__GNUC__) + int8x16_t ret; + // %e and %f represent the even and odd D registers + // respectively. + __asm__ __volatile__( + "vtbl.8 %e[ret], {%e[tbl], %f[tbl]}, %e[idx]\n" + "vtbl.8 %f[ret], {%e[tbl], %f[tbl]}, %f[idx]\n" + : [ret] "=&w"(ret) + : [tbl] "w"(tbl), [idx] "w"(idx_masked)); + return vreinterpretq_m128i_s8(ret); +#else + // use this line if testing on aarch64 + int8x8x2_t a_split = {vget_low_s8(tbl), vget_high_s8(tbl)}; + return vreinterpretq_m128i_s8( + vcombine_s8(vtbl2_s8(a_split, vget_low_u8(idx_masked)), + vtbl2_s8(a_split, vget_high_u8(idx_masked)))); +#endif +} + +// Shuffle packed 8-bit integers in a according to shuffle control mask in the +// corresponding 8-bit element of b, and store the results in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// IF b[i+7] == 1 +// dst[i+7:i] := 0 +// ELSE +// index[2:0] := b[i+2:i] +// dst[i+7:i] := a[index*8+7:index*8] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_pi8 +FORCE_INLINE __m64 _mm_shuffle_pi8(__m64 a, __m64 b) +{ + const int8x8_t controlMask = + vand_s8(vreinterpret_s8_m64(b), vdup_n_s8((int8_t)(0x1 << 7 | 0x07))); + int8x8_t res = vtbl1_s8(vreinterpret_s8_m64(a), controlMask); + return vreinterpret_m64_s8(res); +} + +// Negate packed 16-bit integers in a when the corresponding signed +// 16-bit integer in b is negative, and store the results in dst. +// Element in dst are zeroed out when the corresponding element +// in b is zero. +// +// for i in 0..7 +// if b[i] < 0 +// r[i] := -a[i] +// else if b[i] == 0 +// r[i] := 0 +// else +// r[i] := a[i] +// fi +// done +FORCE_INLINE __m128i _mm_sign_epi16(__m128i _a, __m128i _b) +{ + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFF : 0 + uint16x8_t ltMask = vreinterpretq_u16_s16(vshrq_n_s16(b, 15)); + // (b == 0) ? 0xFFFF : 0 +#if defined(__aarch64__) + int16x8_t zeroMask = vreinterpretq_s16_u16(vceqzq_s16(b)); +#else + int16x8_t zeroMask = vreinterpretq_s16_u16(vceqq_s16(b, vdupq_n_s16(0))); +#endif + + // bitwise select either a or negative 'a' (vnegq_s16(a) equals to negative + // 'a') based on ltMask + int16x8_t masked = vbslq_s16(ltMask, vnegq_s16(a), a); + // res = masked & (~zeroMask) + int16x8_t res = vbicq_s16(masked, zeroMask); + return vreinterpretq_m128i_s16(res); +} + +// Negate packed 32-bit integers in a when the corresponding signed +// 32-bit integer in b is negative, and store the results in dst. +// Element in dst are zeroed out when the corresponding element +// in b is zero. +// +// for i in 0..3 +// if b[i] < 0 +// r[i] := -a[i] +// else if b[i] == 0 +// r[i] := 0 +// else +// r[i] := a[i] +// fi +// done +FORCE_INLINE __m128i _mm_sign_epi32(__m128i _a, __m128i _b) +{ + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFFFFFF : 0 + uint32x4_t ltMask = vreinterpretq_u32_s32(vshrq_n_s32(b, 31)); + + // (b == 0) ? 0xFFFFFFFF : 0 +#if defined(__aarch64__) + int32x4_t zeroMask = vreinterpretq_s32_u32(vceqzq_s32(b)); +#else + int32x4_t zeroMask = vreinterpretq_s32_u32(vceqq_s32(b, vdupq_n_s32(0))); +#endif + + // bitwise select either a or negative 'a' (vnegq_s32(a) equals to negative + // 'a') based on ltMask + int32x4_t masked = vbslq_s32(ltMask, vnegq_s32(a), a); + // res = masked & (~zeroMask) + int32x4_t res = vbicq_s32(masked, zeroMask); + return vreinterpretq_m128i_s32(res); +} + +// Negate packed 8-bit integers in a when the corresponding signed +// 8-bit integer in b is negative, and store the results in dst. +// Element in dst are zeroed out when the corresponding element +// in b is zero. +// +// for i in 0..15 +// if b[i] < 0 +// r[i] := -a[i] +// else if b[i] == 0 +// r[i] := 0 +// else +// r[i] := a[i] +// fi +// done +FORCE_INLINE __m128i _mm_sign_epi8(__m128i _a, __m128i _b) +{ + int8x16_t a = vreinterpretq_s8_m128i(_a); + int8x16_t b = vreinterpretq_s8_m128i(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFF : 0 + uint8x16_t ltMask = vreinterpretq_u8_s8(vshrq_n_s8(b, 7)); + + // (b == 0) ? 0xFF : 0 +#if defined(__aarch64__) + int8x16_t zeroMask = vreinterpretq_s8_u8(vceqzq_s8(b)); +#else + int8x16_t zeroMask = vreinterpretq_s8_u8(vceqq_s8(b, vdupq_n_s8(0))); +#endif + + // bitwise select either a or nagative 'a' (vnegq_s8(a) return nagative 'a') + // based on ltMask + int8x16_t masked = vbslq_s8(ltMask, vnegq_s8(a), a); + // res = masked & (~zeroMask) + int8x16_t res = vbicq_s8(masked, zeroMask); + + return vreinterpretq_m128i_s8(res); +} + +// Negate packed 16-bit integers in a when the corresponding signed 16-bit +// integer in b is negative, and store the results in dst. Element in dst are +// zeroed out when the corresponding element in b is zero. +// +// FOR j := 0 to 3 +// i := j*16 +// IF b[i+15:i] < 0 +// dst[i+15:i] := -(a[i+15:i]) +// ELSE IF b[i+15:i] == 0 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := a[i+15:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi16 +FORCE_INLINE __m64 _mm_sign_pi16(__m64 _a, __m64 _b) +{ + int16x4_t a = vreinterpret_s16_m64(_a); + int16x4_t b = vreinterpret_s16_m64(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFF : 0 + uint16x4_t ltMask = vreinterpret_u16_s16(vshr_n_s16(b, 15)); + + // (b == 0) ? 0xFFFF : 0 +#if defined(__aarch64__) + int16x4_t zeroMask = vreinterpret_s16_u16(vceqz_s16(b)); +#else + int16x4_t zeroMask = vreinterpret_s16_u16(vceq_s16(b, vdup_n_s16(0))); +#endif + + // bitwise select either a or nagative 'a' (vneg_s16(a) return nagative 'a') + // based on ltMask + int16x4_t masked = vbsl_s16(ltMask, vneg_s16(a), a); + // res = masked & (~zeroMask) + int16x4_t res = vbic_s16(masked, zeroMask); + + return vreinterpret_m64_s16(res); +} + +// Negate packed 32-bit integers in a when the corresponding signed 32-bit +// integer in b is negative, and store the results in dst. Element in dst are +// zeroed out when the corresponding element in b is zero. +// +// FOR j := 0 to 1 +// i := j*32 +// IF b[i+31:i] < 0 +// dst[i+31:i] := -(a[i+31:i]) +// ELSE IF b[i+31:i] == 0 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := a[i+31:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi32 +FORCE_INLINE __m64 _mm_sign_pi32(__m64 _a, __m64 _b) +{ + int32x2_t a = vreinterpret_s32_m64(_a); + int32x2_t b = vreinterpret_s32_m64(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFFFFFF : 0 + uint32x2_t ltMask = vreinterpret_u32_s32(vshr_n_s32(b, 31)); + + // (b == 0) ? 0xFFFFFFFF : 0 +#if defined(__aarch64__) + int32x2_t zeroMask = vreinterpret_s32_u32(vceqz_s32(b)); +#else + int32x2_t zeroMask = vreinterpret_s32_u32(vceq_s32(b, vdup_n_s32(0))); +#endif + + // bitwise select either a or nagative 'a' (vneg_s32(a) return nagative 'a') + // based on ltMask + int32x2_t masked = vbsl_s32(ltMask, vneg_s32(a), a); + // res = masked & (~zeroMask) + int32x2_t res = vbic_s32(masked, zeroMask); + + return vreinterpret_m64_s32(res); +} + +// Negate packed 8-bit integers in a when the corresponding signed 8-bit integer +// in b is negative, and store the results in dst. Element in dst are zeroed out +// when the corresponding element in b is zero. +// +// FOR j := 0 to 7 +// i := j*8 +// IF b[i+7:i] < 0 +// dst[i+7:i] := -(a[i+7:i]) +// ELSE IF b[i+7:i] == 0 +// dst[i+7:i] := 0 +// ELSE +// dst[i+7:i] := a[i+7:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi8 +FORCE_INLINE __m64 _mm_sign_pi8(__m64 _a, __m64 _b) +{ + int8x8_t a = vreinterpret_s8_m64(_a); + int8x8_t b = vreinterpret_s8_m64(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFF : 0 + uint8x8_t ltMask = vreinterpret_u8_s8(vshr_n_s8(b, 7)); + + // (b == 0) ? 0xFF : 0 +#if defined(__aarch64__) + int8x8_t zeroMask = vreinterpret_s8_u8(vceqz_s8(b)); +#else + int8x8_t zeroMask = vreinterpret_s8_u8(vceq_s8(b, vdup_n_s8(0))); +#endif + + // bitwise select either a or nagative 'a' (vneg_s8(a) return nagative 'a') + // based on ltMask + int8x8_t masked = vbsl_s8(ltMask, vneg_s8(a), a); + // res = masked & (~zeroMask) + int8x8_t res = vbic_s8(masked, zeroMask); + + return vreinterpret_m64_s8(res); +} + +/* SSE4.1 */ + +// Blend packed 16-bit integers from a and b using control mask imm8, and store +// the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF imm8[j] +// dst[i+15:i] := b[i+15:i] +// ELSE +// dst[i+15:i] := a[i+15:i] +// FI +// ENDFOR +// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b, +// __constrange(0,255) int imm) +#define _mm_blend_epi16(a, b, imm) \ + __extension__({ \ + const uint16_t ones = 0xffff; \ + const uint16_t zeros = 0x0000; \ + const uint16_t _mask[8] = {((imm) & (1 << 0)) ? ones : zeros, \ + ((imm) & (1 << 1)) ? ones : zeros, \ + ((imm) & (1 << 2)) ? ones : zeros, \ + ((imm) & (1 << 3)) ? ones : zeros, \ + ((imm) & (1 << 4)) ? ones : zeros, \ + ((imm) & (1 << 5)) ? ones : zeros, \ + ((imm) & (1 << 6)) ? ones : zeros, \ + ((imm) & (1 << 7)) ? ones : zeros}; \ + uint16x8_t _mask_vec = vld1q_u16(_mask); \ + uint16x8_t _a = vreinterpretq_u16_m128i(a); \ + uint16x8_t _b = vreinterpretq_u16_m128i(b); \ + vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \ + }) + +// Blend packed double-precision (64-bit) floating-point elements from a and b +// using control mask imm8, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blend_pd +#define _mm_blend_pd(a, b, imm) \ + __extension__({ \ + const uint64_t _mask[2] = { \ + ((imm) & (1 << 0)) ? ~UINT64_C(0) : UINT64_C(0), \ + ((imm) & (1 << 1)) ? ~UINT64_C(0) : UINT64_C(0)}; \ + uint64x2_t _mask_vec = vld1q_u64(_mask); \ + uint64x2_t _a = vreinterpretq_u64_m128d(a); \ + uint64x2_t _b = vreinterpretq_u64_m128d(b); \ + vreinterpretq_m128d_u64(vbslq_u64(_mask_vec, _b, _a)); \ + }) + +// Blend packed single-precision (32-bit) floating-point elements from a and b +// using mask, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blend_ps +FORCE_INLINE __m128 _mm_blend_ps(__m128 _a, __m128 _b, const char imm8) +{ + const uint32_t ALIGN_STRUCT(16) + data[4] = {((imm8) & (1 << 0)) ? UINT32_MAX : 0, + ((imm8) & (1 << 1)) ? UINT32_MAX : 0, + ((imm8) & (1 << 2)) ? UINT32_MAX : 0, + ((imm8) & (1 << 3)) ? UINT32_MAX : 0}; + uint32x4_t mask = vld1q_u32(data); + float32x4_t a = vreinterpretq_f32_m128(_a); + float32x4_t b = vreinterpretq_f32_m128(_b); + return vreinterpretq_m128_f32(vbslq_f32(mask, b, a)); +} + +// Blend packed 8-bit integers from a and b using mask, and store the results in +// dst. +// +// FOR j := 0 to 15 +// i := j*8 +// IF mask[i+7] +// dst[i+7:i] := b[i+7:i] +// ELSE +// dst[i+7:i] := a[i+7:i] +// FI +// ENDFOR +FORCE_INLINE __m128i _mm_blendv_epi8(__m128i _a, __m128i _b, __m128i _mask) +{ + // Use a signed shift right to create a mask with the sign bit + uint8x16_t mask = + vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_m128i(_mask), 7)); + uint8x16_t a = vreinterpretq_u8_m128i(_a); + uint8x16_t b = vreinterpretq_u8_m128i(_b); + return vreinterpretq_m128i_u8(vbslq_u8(mask, b, a)); +} + +// Blend packed double-precision (64-bit) floating-point elements from a and b +// using mask, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_pd +FORCE_INLINE __m128d _mm_blendv_pd(__m128d _a, __m128d _b, __m128d _mask) +{ + uint64x2_t mask = + vreinterpretq_u64_s64(vshrq_n_s64(vreinterpretq_s64_m128d(_mask), 63)); +#if defined(__aarch64__) + float64x2_t a = vreinterpretq_f64_m128d(_a); + float64x2_t b = vreinterpretq_f64_m128d(_b); + return vreinterpretq_m128d_f64(vbslq_f64(mask, b, a)); +#else + uint64x2_t a = vreinterpretq_u64_m128d(_a); + uint64x2_t b = vreinterpretq_u64_m128d(_b); + return vreinterpretq_m128d_u64(vbslq_u64(mask, b, a)); +#endif +} + +// Blend packed single-precision (32-bit) floating-point elements from a and b +// using mask, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_ps +FORCE_INLINE __m128 _mm_blendv_ps(__m128 _a, __m128 _b, __m128 _mask) +{ + // Use a signed shift right to create a mask with the sign bit + uint32x4_t mask = + vreinterpretq_u32_s32(vshrq_n_s32(vreinterpretq_s32_m128(_mask), 31)); + float32x4_t a = vreinterpretq_f32_m128(_a); + float32x4_t b = vreinterpretq_f32_m128(_b); + return vreinterpretq_m128_f32(vbslq_f32(mask, b, a)); +} + +// Round the packed double-precision (64-bit) floating-point elements in a up +// to an integer value, and store the results as packed double-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_pd +FORCE_INLINE __m128d _mm_ceil_pd(__m128d a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vrndpq_f64(vreinterpretq_f64_m128d(a))); +#else + double *f = (double *) &a; + return _mm_set_pd(ceil(f[1]), ceil(f[0])); +#endif +} + +// Round the packed single-precision (32-bit) floating-point elements in a up to +// an integer value, and store the results as packed single-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ps +FORCE_INLINE __m128 _mm_ceil_ps(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vrndpq_f32(vreinterpretq_f32_m128(a))); +#else + float *f = (float *) &a; + return _mm_set_ps(ceilf(f[3]), ceilf(f[2]), ceilf(f[1]), ceilf(f[0])); +#endif +} + +// Round the lower double-precision (64-bit) floating-point element in b up to +// an integer value, store the result as a double-precision floating-point +// element in the lower element of dst, and copy the upper element from a to the +// upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_sd +FORCE_INLINE __m128d _mm_ceil_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_ceil_pd(b)); +} + +// Round the lower single-precision (32-bit) floating-point element in b up to +// an integer value, store the result as a single-precision floating-point +// element in the lower element of dst, and copy the upper 3 packed elements +// from a to the upper elements of dst. +// +// dst[31:0] := CEIL(b[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ss +FORCE_INLINE __m128 _mm_ceil_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_ceil_ps(b)); +} + +// Compare packed 64-bit integers in a and b for equality, and store the results +// in dst +FORCE_INLINE __m128i _mm_cmpeq_epi64(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_u64( + vceqq_u64(vreinterpretq_u64_m128i(a), vreinterpretq_u64_m128i(b))); +#else + // ARMv7 lacks vceqq_u64 + // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi) + uint32x4_t cmp = + vceqq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)); + uint32x4_t swapped = vrev64q_u32(cmp); + return vreinterpretq_m128i_u32(vandq_u32(cmp, swapped)); +#endif +} + +// Converts the four signed 16-bit integers in the lower 64 bits to four signed +// 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a) +{ + return vreinterpretq_m128i_s32( + vmovl_s16(vget_low_s16(vreinterpretq_s16_m128i(a)))); +} + +// Converts the two signed 16-bit integers in the lower 32 bits two signed +// 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi16_epi64(__m128i a) +{ + int16x8_t s16x8 = vreinterpretq_s16_m128i(a); /* xxxx xxxx xxxx 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */ + int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_s64(s64x2); +} + +// Converts the two signed 32-bit integers in the lower 64 bits to two signed +// 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepi32_epi64(__m128i a) +{ + return vreinterpretq_m128i_s64( + vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a)))); +} + +// Converts the four unsigned 8-bit integers in the lower 16 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi8_epi16(__m128i a) +{ + int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + return vreinterpretq_m128i_s16(s16x8); +} + +// Converts the four unsigned 8-bit integers in the lower 32 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi8_epi32(__m128i a) +{ + int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */ + return vreinterpretq_m128i_s32(s32x4); +} + +// Converts the two signed 8-bit integers in the lower 32 bits to four +// signed 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepi8_epi64(__m128i a) +{ + int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx xxBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */ + int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_s64(s64x2); +} + +// Converts the four unsigned 16-bit integers in the lower 64 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepu16_epi32(__m128i a) +{ + return vreinterpretq_m128i_u32( + vmovl_u16(vget_low_u16(vreinterpretq_u16_m128i(a)))); +} + +// Converts the two unsigned 16-bit integers in the lower 32 bits to two +// unsigned 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepu16_epi64(__m128i a) +{ + uint16x8_t u16x8 = vreinterpretq_u16_m128i(a); /* xxxx xxxx xxxx 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */ + uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_u64(u64x2); +} + +// Converts the two unsigned 32-bit integers in the lower 64 bits to two +// unsigned 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepu32_epi64(__m128i a) +{ + return vreinterpretq_m128i_u64( + vmovl_u32(vget_low_u32(vreinterpretq_u32_m128i(a)))); +} + +// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers, +// and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepu8_epi16 +FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a) +{ + uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx HGFE DCBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0H0G 0F0E 0D0C 0B0A */ + return vreinterpretq_m128i_u16(u16x8); +} + +// Converts the four unsigned 8-bit integers in the lower 32 bits to four +// unsigned 32-bit integers. +// https://msdn.microsoft.com/en-us/library/bb531467%28v=vs.100%29.aspx +FORCE_INLINE __m128i _mm_cvtepu8_epi32(__m128i a) +{ + uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */ + return vreinterpretq_m128i_u32(u32x4); +} + +// Converts the two unsigned 8-bit integers in the lower 16 bits to two +// unsigned 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepu8_epi64(__m128i a) +{ + uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx xxBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */ + uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_u64(u64x2); +} + +// Conditionally multiply the packed double-precision (64-bit) floating-point +// elements in a and b using the high 4 bits in imm8, sum the four products, and +// conditionally store the sum in dst using the low 4 bits of imm8. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_pd +FORCE_INLINE __m128d _mm_dp_pd(__m128d a, __m128d b, const int imm) +{ + // Generate mask value from constant immediate bit value + const int64_t bit0Mask = imm & 0x01 ? UINT64_MAX : 0; + const int64_t bit1Mask = imm & 0x02 ? UINT64_MAX : 0; +#if !SSE2NEON_PRECISE_DP + const int64_t bit4Mask = imm & 0x10 ? UINT64_MAX : 0; + const int64_t bit5Mask = imm & 0x20 ? UINT64_MAX : 0; +#endif + // Conditional multiplication +#if !SSE2NEON_PRECISE_DP + __m128d mul = _mm_mul_pd(a, b); + const __m128d mulMask = + _mm_castsi128_pd(_mm_set_epi64x(bit5Mask, bit4Mask)); + __m128d tmp = _mm_and_pd(mul, mulMask); +#else +#if defined(__aarch64__) + double d0 = (imm & 0x10) ? vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0) * + vgetq_lane_f64(vreinterpretq_f64_m128d(b), 0) + : 0; + double d1 = (imm & 0x20) ? vgetq_lane_f64(vreinterpretq_f64_m128d(a), 1) * + vgetq_lane_f64(vreinterpretq_f64_m128d(b), 1) + : 0; +#else + double d0 = (imm & 0x10) ? ((double *) &a)[0] * ((double *) &b)[0] : 0; + double d1 = (imm & 0x20) ? ((double *) &a)[1] * ((double *) &b)[1] : 0; +#endif + __m128d tmp = _mm_set_pd(d1, d0); +#endif + // Sum the products +#if defined(__aarch64__) + double sum = vpaddd_f64(vreinterpretq_f64_m128d(tmp)); +#else + double sum = *((double *) &tmp) + *(((double *) &tmp) + 1); +#endif + // Conditionally store the sum + const __m128d sumMask = + _mm_castsi128_pd(_mm_set_epi64x(bit1Mask, bit0Mask)); + __m128d res = _mm_and_pd(_mm_set_pd1(sum), sumMask); + return res; +} + +// Conditionally multiply the packed single-precision (32-bit) floating-point +// elements in a and b using the high 4 bits in imm8, sum the four products, +// and conditionally store the sum in dst using the low 4 bits of imm. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_ps +FORCE_INLINE __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm) +{ +#if defined(__aarch64__) + /* shortcuts */ + if (imm == 0xFF) { + return _mm_set1_ps(vaddvq_f32(_mm_mul_ps(a, b))); + } + if (imm == 0x7F) { + float32x4_t m = _mm_mul_ps(a, b); + m[3] = 0; + return _mm_set1_ps(vaddvq_f32(m)); + } +#endif + + float s = 0, c = 0; + float32x4_t f32a = vreinterpretq_f32_m128(a); + float32x4_t f32b = vreinterpretq_f32_m128(b); + + /* To improve the accuracy of floating-point summation, Kahan algorithm + * is used for each operation. + */ + if (imm & (1 << 4)) + _sse2neon_kadd_f32(&s, &c, f32a[0] * f32b[0]); + if (imm & (1 << 5)) + _sse2neon_kadd_f32(&s, &c, f32a[1] * f32b[1]); + if (imm & (1 << 6)) + _sse2neon_kadd_f32(&s, &c, f32a[2] * f32b[2]); + if (imm & (1 << 7)) + _sse2neon_kadd_f32(&s, &c, f32a[3] * f32b[3]); + s += c; + + float32x4_t res = { + (imm & 0x1) ? s : 0, + (imm & 0x2) ? s : 0, + (imm & 0x4) ? s : 0, + (imm & 0x8) ? s : 0, + }; + return vreinterpretq_m128_f32(res); +} + +// Extracts the selected signed or unsigned 32-bit integer from a and zero +// extends. +// FORCE_INLINE int _mm_extract_epi32(__m128i a, __constrange(0,4) int imm) +#define _mm_extract_epi32(a, imm) \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)) + +// Extracts the selected signed or unsigned 64-bit integer from a and zero +// extends. +// FORCE_INLINE __int64 _mm_extract_epi64(__m128i a, __constrange(0,2) int imm) +#define _mm_extract_epi64(a, imm) \ + vgetq_lane_s64(vreinterpretq_s64_m128i(a), (imm)) + +// Extracts the selected signed or unsigned 8-bit integer from a and zero +// extends. +// FORCE_INLINE int _mm_extract_epi8(__m128i a, __constrange(0,16) int imm) +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_extract_epi8 +#define _mm_extract_epi8(a, imm) vgetq_lane_u8(vreinterpretq_u8_m128i(a), (imm)) + +// Extracts the selected single-precision (32-bit) floating-point from a. +// FORCE_INLINE int _mm_extract_ps(__m128 a, __constrange(0,4) int imm) +#define _mm_extract_ps(a, imm) vgetq_lane_s32(vreinterpretq_s32_m128(a), (imm)) + +// Round the packed double-precision (64-bit) floating-point elements in a down +// to an integer value, and store the results as packed double-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_pd +FORCE_INLINE __m128d _mm_floor_pd(__m128d a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vrndmq_f64(vreinterpretq_f64_m128d(a))); +#else + double *f = (double *) &a; + return _mm_set_pd(floor(f[1]), floor(f[0])); +#endif +} + +// Round the packed single-precision (32-bit) floating-point elements in a down +// to an integer value, and store the results as packed single-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ps +FORCE_INLINE __m128 _mm_floor_ps(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vrndmq_f32(vreinterpretq_f32_m128(a))); +#else + float *f = (float *) &a; + return _mm_set_ps(floorf(f[3]), floorf(f[2]), floorf(f[1]), floorf(f[0])); +#endif +} + +// Round the lower double-precision (64-bit) floating-point element in b down to +// an integer value, store the result as a double-precision floating-point +// element in the lower element of dst, and copy the upper element from a to the +// upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_sd +FORCE_INLINE __m128d _mm_floor_sd(__m128d a, __m128d b) +{ + return _mm_move_sd(a, _mm_floor_pd(b)); +} + +// Round the lower single-precision (32-bit) floating-point element in b down to +// an integer value, store the result as a single-precision floating-point +// element in the lower element of dst, and copy the upper 3 packed elements +// from a to the upper elements of dst. +// +// dst[31:0] := FLOOR(b[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ss +FORCE_INLINE __m128 _mm_floor_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_floor_ps(b)); +} + +// Inserts the least significant 32 bits of b into the selected 32-bit integer +// of a. +// FORCE_INLINE __m128i _mm_insert_epi32(__m128i a, int b, +// __constrange(0,4) int imm) +#define _mm_insert_epi32(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s32( \ + vsetq_lane_s32((b), vreinterpretq_s32_m128i(a), (imm))); \ + }) + +// Inserts the least significant 64 bits of b into the selected 64-bit integer +// of a. +// FORCE_INLINE __m128i _mm_insert_epi64(__m128i a, __int64 b, +// __constrange(0,2) int imm) +#define _mm_insert_epi64(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s64( \ + vsetq_lane_s64((b), vreinterpretq_s64_m128i(a), (imm))); \ + }) + +// Inserts the least significant 8 bits of b into the selected 8-bit integer +// of a. +// FORCE_INLINE __m128i _mm_insert_epi8(__m128i a, int b, +// __constrange(0,16) int imm) +#define _mm_insert_epi8(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s8( \ + vsetq_lane_s8((b), vreinterpretq_s8_m128i(a), (imm))); \ + }) + +// Copy a to tmp, then insert a single-precision (32-bit) floating-point +// element from b into tmp using the control in imm8. Store tmp to dst using +// the mask in imm8 (elements are zeroed out when the corresponding bit is set). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=insert_ps +#define _mm_insert_ps(a, b, imm8) \ + __extension__({ \ + float32x4_t tmp1 = \ + vsetq_lane_f32(vgetq_lane_f32(b, (imm8 >> 6) & 0x3), \ + vreinterpretq_f32_m128(a), 0); \ + float32x4_t tmp2 = \ + vsetq_lane_f32(vgetq_lane_f32(tmp1, 0), vreinterpretq_f32_m128(a), \ + ((imm8 >> 4) & 0x3)); \ + const uint32_t data[4] = {((imm8) & (1 << 0)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 1)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 2)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 3)) ? UINT32_MAX : 0}; \ + uint32x4_t mask = vld1q_u32(data); \ + float32x4_t all_zeros = vdupq_n_f32(0); \ + \ + vreinterpretq_m128_f32( \ + vbslq_f32(mask, all_zeros, vreinterpretq_f32_m128(tmp2))); \ + }) + +// epi versions of min/max +// Computes the pariwise maximums of the four signed 32-bit integer values of a +// and b. +// +// A 128-bit parameter that can be defined with the following equations: +// r0 := (a0 > b0) ? a0 : b0 +// r1 := (a1 > b1) ? a1 : b1 +// r2 := (a2 > b2) ? a2 : b2 +// r3 := (a3 > b3) ? a3 : b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx +FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vmaxq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compare packed signed 8-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epi8 +FORCE_INLINE __m128i _mm_max_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vmaxq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed unsigned 16-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu16 +FORCE_INLINE __m128i _mm_max_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vmaxq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Compare packed unsigned 32-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32 +FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vmaxq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b))); +} + +// Computes the pariwise minima of the four signed 32-bit integer values of a +// and b. +// +// A 128-bit parameter that can be defined with the following equations: +// r0 := (a0 < b0) ? a0 : b0 +// r1 := (a1 < b1) ? a1 : b1 +// r2 := (a2 < b2) ? a2 : b2 +// r3 := (a3 < b3) ? a3 : b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx +FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vminq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compare packed signed 8-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epi8 +FORCE_INLINE __m128i _mm_min_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vminq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed unsigned 16-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epu16 +FORCE_INLINE __m128i _mm_min_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vminq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Compare packed unsigned 32-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32 +FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vminq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b))); +} + +// Horizontally compute the minimum amongst the packed unsigned 16-bit integers +// in a, store the minimum and index in dst, and zero the remaining bits in dst. +// +// index[2:0] := 0 +// min[15:0] := a[15:0] +// FOR j := 0 to 7 +// i := j*16 +// IF a[i+15:i] < min[15:0] +// index[2:0] := j +// min[15:0] := a[i+15:i] +// FI +// ENDFOR +// dst[15:0] := min[15:0] +// dst[18:16] := index[2:0] +// dst[127:19] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_minpos_epu16 +FORCE_INLINE __m128i _mm_minpos_epu16(__m128i a) +{ + __m128i dst; + uint16_t min, idx = 0; + // Find the minimum value +#if defined(__aarch64__) + min = vminvq_u16(vreinterpretq_u16_m128i(a)); +#else + __m64 tmp; + tmp = vreinterpret_m64_u16( + vmin_u16(vget_low_u16(vreinterpretq_u16_m128i(a)), + vget_high_u16(vreinterpretq_u16_m128i(a)))); + tmp = vreinterpret_m64_u16( + vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp))); + tmp = vreinterpret_m64_u16( + vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp))); + min = vget_lane_u16(vreinterpret_u16_m64(tmp), 0); +#endif + // Get the index of the minimum value + int i; + for (i = 0; i < 8; i++) { + if (min == vgetq_lane_u16(vreinterpretq_u16_m128i(a), 0)) { + idx = (uint16_t) i; + break; + } + a = _mm_srli_si128(a, 2); + } + // Generate result + dst = _mm_setzero_si128(); + dst = vreinterpretq_m128i_u16( + vsetq_lane_u16(min, vreinterpretq_u16_m128i(dst), 0)); + dst = vreinterpretq_m128i_u16( + vsetq_lane_u16(idx, vreinterpretq_u16_m128i(dst), 1)); + return dst; +} + +// Compute the sum of absolute differences (SADs) of quadruplets of unsigned +// 8-bit integers in a compared to those in b, and store the 16-bit results in +// dst. Eight SADs are performed using one quadruplet from b and eight +// quadruplets from a. One quadruplet is selected from b starting at on the +// offset specified in imm8. Eight quadruplets are formed from sequential 8-bit +// integers selected from a starting at the offset specified in imm8. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mpsadbw_epu8 +FORCE_INLINE __m128i _mm_mpsadbw_epu8(__m128i a, __m128i b, const int imm) +{ + uint8x16_t _a, _b; + + switch (imm & 0x4) { + case 0: + // do nothing + _a = vreinterpretq_u8_m128i(a); + break; + case 4: + _a = vreinterpretq_u8_u32(vextq_u32(vreinterpretq_u32_m128i(a), + vreinterpretq_u32_m128i(a), 1)); + break; + default: +#if defined(__GNUC__) || defined(__clang__) + __builtin_unreachable(); +#endif + break; + } + + switch (imm & 0x3) { + case 0: + _b = vreinterpretq_u8_u32( + vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 0))); + break; + case 1: + _b = vreinterpretq_u8_u32( + vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 1))); + break; + case 2: + _b = vreinterpretq_u8_u32( + vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 2))); + break; + case 3: + _b = vreinterpretq_u8_u32( + vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 3))); + break; + default: +#if defined(__GNUC__) || defined(__clang__) + __builtin_unreachable(); +#endif + break; + } + + int16x8_t c04, c15, c26, c37; + uint8x8_t low_b = vget_low_u8(_b); + c04 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b))); + _a = vextq_u8(_a, _a, 1); + c15 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b))); + _a = vextq_u8(_a, _a, 1); + c26 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b))); + _a = vextq_u8(_a, _a, 1); + c37 = vabsq_s16(vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(_a), low_b))); +#if defined(__aarch64__) + // |0|4|2|6| + c04 = vpaddq_s16(c04, c26); + // |1|5|3|7| + c15 = vpaddq_s16(c15, c37); + + int32x4_t trn1_c = + vtrn1q_s32(vreinterpretq_s32_s16(c04), vreinterpretq_s32_s16(c15)); + int32x4_t trn2_c = + vtrn2q_s32(vreinterpretq_s32_s16(c04), vreinterpretq_s32_s16(c15)); + return vreinterpretq_m128i_s16(vpaddq_s16(vreinterpretq_s16_s32(trn1_c), + vreinterpretq_s16_s32(trn2_c))); +#else + int16x4_t c01, c23, c45, c67; + c01 = vpadd_s16(vget_low_s16(c04), vget_low_s16(c15)); + c23 = vpadd_s16(vget_low_s16(c26), vget_low_s16(c37)); + c45 = vpadd_s16(vget_high_s16(c04), vget_high_s16(c15)); + c67 = vpadd_s16(vget_high_s16(c26), vget_high_s16(c37)); + + return vreinterpretq_m128i_s16( + vcombine_s16(vpadd_s16(c01, c23), vpadd_s16(c45, c67))); +#endif +} + +// Multiply the low signed 32-bit integers from each packed 64-bit element in +// a and b, and store the signed 64-bit results in dst. +// +// r0 := (int64_t)(int32_t)a0 * (int64_t)(int32_t)b0 +// r1 := (int64_t)(int32_t)a2 * (int64_t)(int32_t)b2 +FORCE_INLINE __m128i _mm_mul_epi32(__m128i a, __m128i b) +{ + // vmull_s32 upcasts instead of masking, so we downcast. + int32x2_t a_lo = vmovn_s64(vreinterpretq_s64_m128i(a)); + int32x2_t b_lo = vmovn_s64(vreinterpretq_s64_m128i(b)); + return vreinterpretq_m128i_s64(vmull_s32(a_lo, b_lo)); +} + +// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or +// unsigned 32-bit integers from b. +// https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx +FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Packs the 8 unsigned 32-bit integers from a and b into unsigned 16-bit +// integers and saturates. +// +// r0 := UnsignedSaturate(a0) +// r1 := UnsignedSaturate(a1) +// r2 := UnsignedSaturate(a2) +// r3 := UnsignedSaturate(a3) +// r4 := UnsignedSaturate(b0) +// r5 := UnsignedSaturate(b1) +// r6 := UnsignedSaturate(b2) +// r7 := UnsignedSaturate(b3) +FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vcombine_u16(vqmovun_s32(vreinterpretq_s32_m128i(a)), + vqmovun_s32(vreinterpretq_s32_m128i(b)))); +} + +// Round the packed double-precision (64-bit) floating-point elements in a using +// the rounding parameter, and store the results as packed double-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_pd +FORCE_INLINE __m128d _mm_round_pd(__m128d a, int rounding) +{ +#if defined(__aarch64__) + switch (rounding) { + case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC): + return vreinterpretq_m128d_f64(vrndnq_f64(vreinterpretq_f64_m128d(a))); + case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC): + return _mm_floor_pd(a); + case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC): + return _mm_ceil_pd(a); + case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC): + return vreinterpretq_m128d_f64(vrndq_f64(vreinterpretq_f64_m128d(a))); + default: //_MM_FROUND_CUR_DIRECTION + return vreinterpretq_m128d_f64(vrndiq_f64(vreinterpretq_f64_m128d(a))); + } +#else + double *v_double = (double *) &a; + + if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) || + (rounding == _MM_FROUND_CUR_DIRECTION && + _MM_GET_ROUNDING_MODE() == _MM_ROUND_NEAREST)) { + double res[2], tmp; + for (int i = 0; i < 2; i++) { + tmp = (v_double[i] < 0) ? -v_double[i] : v_double[i]; + double roundDown = floor(tmp); // Round down value + double roundUp = ceil(tmp); // Round up value + double diffDown = tmp - roundDown; + double diffUp = roundUp - tmp; + if (diffDown < diffUp) { + /* If it's closer to the round down value, then use it */ + res[i] = roundDown; + } else if (diffDown > diffUp) { + /* If it's closer to the round up value, then use it */ + res[i] = roundUp; + } else { + /* If it's equidistant between round up and round down value, + * pick the one which is an even number */ + double half = roundDown / 2; + if (half != floor(half)) { + /* If the round down value is odd, return the round up value + */ + res[i] = roundUp; + } else { + /* If the round up value is odd, return the round down value + */ + res[i] = roundDown; + } + } + res[i] = (v_double[i] < 0) ? -res[i] : res[i]; + } + return _mm_set_pd(res[1], res[0]); + } else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) || + (rounding == _MM_FROUND_CUR_DIRECTION && + _MM_GET_ROUNDING_MODE() == _MM_ROUND_DOWN)) { + return _mm_floor_pd(a); + } else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) || + (rounding == _MM_FROUND_CUR_DIRECTION && + _MM_GET_ROUNDING_MODE() == _MM_ROUND_UP)) { + return _mm_ceil_pd(a); + } + return _mm_set_pd(v_double[1] > 0 ? floor(v_double[1]) : ceil(v_double[1]), + v_double[0] > 0 ? floor(v_double[0]) : ceil(v_double[0])); +#endif +} + +// Round the packed single-precision (32-bit) floating-point elements in a using +// the rounding parameter, and store the results as packed single-precision +// floating-point elements in dst. +// software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ps +FORCE_INLINE __m128 _mm_round_ps(__m128 a, int rounding) +{ +#if defined(__aarch64__) + switch (rounding) { + case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC): + return vreinterpretq_m128_f32(vrndnq_f32(vreinterpretq_f32_m128(a))); + case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC): + return _mm_floor_ps(a); + case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC): + return _mm_ceil_ps(a); + case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC): + return vreinterpretq_m128_f32(vrndq_f32(vreinterpretq_f32_m128(a))); + default: //_MM_FROUND_CUR_DIRECTION + return vreinterpretq_m128_f32(vrndiq_f32(vreinterpretq_f32_m128(a))); + } +#else + float *v_float = (float *) &a; + + if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) || + (rounding == _MM_FROUND_CUR_DIRECTION && + _MM_GET_ROUNDING_MODE() == _MM_ROUND_NEAREST)) { + uint32x4_t signmask = vdupq_n_u32(0x80000000); + float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a), + vdupq_n_f32(0.5f)); /* +/- 0.5 */ + int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32( + vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/ + int32x4_t r_trunc = vcvtq_s32_f32( + vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */ + int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32( + vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */ + int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone), + vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */ + float32x4_t delta = vsubq_f32( + vreinterpretq_f32_m128(a), + vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */ + uint32x4_t is_delta_half = + vceqq_f32(delta, half); /* delta == +/- 0.5 */ + return vreinterpretq_m128_f32( + vcvtq_f32_s32(vbslq_s32(is_delta_half, r_even, r_normal))); + } else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) || + (rounding == _MM_FROUND_CUR_DIRECTION && + _MM_GET_ROUNDING_MODE() == _MM_ROUND_DOWN)) { + return _mm_floor_ps(a); + } else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) || + (rounding == _MM_FROUND_CUR_DIRECTION && + _MM_GET_ROUNDING_MODE() == _MM_ROUND_UP)) { + return _mm_ceil_ps(a); + } + return _mm_set_ps(v_float[3] > 0 ? floorf(v_float[3]) : ceilf(v_float[3]), + v_float[2] > 0 ? floorf(v_float[2]) : ceilf(v_float[2]), + v_float[1] > 0 ? floorf(v_float[1]) : ceilf(v_float[1]), + v_float[0] > 0 ? floorf(v_float[0]) : ceilf(v_float[0])); +#endif +} + +// Round the lower double-precision (64-bit) floating-point element in b using +// the rounding parameter, store the result as a double-precision floating-point +// element in the lower element of dst, and copy the upper element from a to the +// upper element of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_sd +FORCE_INLINE __m128d _mm_round_sd(__m128d a, __m128d b, int rounding) +{ + return _mm_move_sd(a, _mm_round_pd(b, rounding)); +} + +// Round the lower single-precision (32-bit) floating-point element in b using +// the rounding parameter, store the result as a single-precision floating-point +// element in the lower element of dst, and copy the upper 3 packed elements +// from a to the upper elements of dst. Rounding is done according to the +// rounding[3:0] parameter, which can be one of: +// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and +// suppress exceptions +// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and +// suppress exceptions +// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress +// exceptions +// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress +// exceptions _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see +// _MM_SET_ROUNDING_MODE +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ss +FORCE_INLINE __m128 _mm_round_ss(__m128 a, __m128 b, int rounding) +{ + return _mm_move_ss(a, _mm_round_ps(b, rounding)); +} + +// Load 128-bits of integer data from memory into dst using a non-temporal +// memory hint. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// dst[127:0] := MEM[mem_addr+127:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_load_si128 +FORCE_INLINE __m128i _mm_stream_load_si128(__m128i *p) +{ +#if __has_builtin(__builtin_nontemporal_store) + return __builtin_nontemporal_load(p); +#else + return vreinterpretq_m128i_s64(vld1q_s64((int64_t *) p)); +#endif +} + +// Compute the bitwise NOT of a and then AND with a 128-bit vector containing +// all 1's, and return 1 if the result is zero, otherwise return 0. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_ones +FORCE_INLINE int _mm_test_all_ones(__m128i a) +{ + return (uint64_t)(vgetq_lane_s64(a, 0) & vgetq_lane_s64(a, 1)) == + ~(uint64_t) 0; +} + +// Compute the bitwise AND of 128 bits (representing integer data) in a and +// mask, and return 1 if the result is zero, otherwise return 0. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_zeros +FORCE_INLINE int _mm_test_all_zeros(__m128i a, __m128i mask) +{ + int64x2_t a_and_mask = + vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(mask)); + return !(vgetq_lane_s64(a_and_mask, 0) | vgetq_lane_s64(a_and_mask, 1)); +} + +// Compute the bitwise AND of 128 bits (representing integer data) in a and +// mask, and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute +// the bitwise NOT of a and then AND with mask, and set CF to 1 if the result is +// zero, otherwise set CF to 0. Return 1 if both the ZF and CF values are zero, +// otherwise return 0. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_test_mix_ones_zero +FORCE_INLINE int _mm_test_mix_ones_zeros(__m128i a, __m128i mask) +{ + uint64x2_t zf = + vandq_u64(vreinterpretq_u64_m128i(mask), vreinterpretq_u64_m128i(a)); + uint64x2_t cf = + vbicq_u64(vreinterpretq_u64_m128i(mask), vreinterpretq_u64_m128i(a)); + uint64x2_t result = vandq_u64(zf, cf); + return !(vgetq_lane_u64(result, 0) | vgetq_lane_u64(result, 1)); +} + +// Compute the bitwise AND of 128 bits (representing integer data) in a and b, +// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the +// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero, +// otherwise set CF to 0. Return the CF value. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testc_si128 +FORCE_INLINE int _mm_testc_si128(__m128i a, __m128i b) +{ + int64x2_t s64 = + vandq_s64(vreinterpretq_s64_s32(vmvnq_s32(vreinterpretq_s32_m128i(a))), + vreinterpretq_s64_m128i(b)); + return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1)); +} + +// Compute the bitwise AND of 128 bits (representing integer data) in a and b, +// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the +// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero, +// otherwise set CF to 0. Return 1 if both the ZF and CF values are zero, +// otherwise return 0. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testnzc_si128 +#define _mm_testnzc_si128(a, b) _mm_test_mix_ones_zeros(a, b) + +// Compute the bitwise AND of 128 bits (representing integer data) in a and b, +// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the +// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero, +// otherwise set CF to 0. Return the ZF value. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testz_si128 +FORCE_INLINE int _mm_testz_si128(__m128i a, __m128i b) +{ + int64x2_t s64 = + vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)); + return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1)); +} + +/* SSE4.2 */ + +// Compares the 2 signed 64-bit integers in a and the 2 signed 64-bit integers +// in b for greater than. +FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_u64( + vcgtq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b))); +#else + return vreinterpretq_m128i_s64(vshrq_n_s64( + vqsubq_s64(vreinterpretq_s64_m128i(b), vreinterpretq_s64_m128i(a)), + 63)); +#endif +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 16-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb531411(v=vs.100) +FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc = _mm_crc32_u8(crc, v & 0xff); + crc = _mm_crc32_u8(crc, (v >> 8) & 0xff); +#endif + return crc; +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 32-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb531394(v=vs.100) +FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc = _mm_crc32_u16(crc, v & 0xffff); + crc = _mm_crc32_u16(crc, (v >> 16) & 0xffff); +#endif + return crc; +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 64-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb514033(v=vs.100) +FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc = _mm_crc32_u32((uint32_t)(crc), v & 0xffffffff); + crc = _mm_crc32_u32((uint32_t)(crc), (v >> 32) & 0xffffffff); +#endif + return crc; +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 8-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb514036(v=vs.100) +FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t crc, uint8_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc ^= v; + for (int bit = 0; bit < 8; bit++) { + if (crc & 1) + crc = (crc >> 1) ^ UINT32_C(0x82f63b78); + else + crc = (crc >> 1); + } +#endif + return crc; +} + +/* AES */ + +#if !defined(__ARM_FEATURE_CRYPTO) +/* clang-format off */ +#define SSE2NEON_AES_DATA(w) \ + { \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), \ + w(0xc5), w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), \ + w(0xab), w(0x76), w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), \ + w(0x59), w(0x47), w(0xf0), w(0xad), w(0xd4), w(0xa2), w(0xaf), \ + w(0x9c), w(0xa4), w(0x72), w(0xc0), w(0xb7), w(0xfd), w(0x93), \ + w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), w(0x34), w(0xa5), \ + w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), w(0x04), \ + w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), \ + w(0x75), w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), \ + w(0x5a), w(0xa0), w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), \ + w(0xe3), w(0x2f), w(0x84), w(0x53), w(0xd1), w(0x00), w(0xed), \ + w(0x20), w(0xfc), w(0xb1), w(0x5b), w(0x6a), w(0xcb), w(0xbe), \ + w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), w(0xd0), w(0xef), \ + w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), w(0x45), \ + w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), \ + w(0xf5), w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), \ + w(0xf3), w(0xd2), w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), \ + w(0x97), w(0x44), w(0x17), w(0xc4), w(0xa7), w(0x7e), w(0x3d), \ + w(0x64), w(0x5d), w(0x19), w(0x73), w(0x60), w(0x81), w(0x4f), \ + w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), w(0x46), w(0xee), \ + w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), w(0xe0), \ + w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), \ + w(0x79), w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), \ + w(0x4e), w(0xa9), w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), \ + w(0x7a), w(0xae), w(0x08), w(0xba), w(0x78), w(0x25), w(0x2e), \ + w(0x1c), w(0xa6), w(0xb4), w(0xc6), w(0xe8), w(0xdd), w(0x74), \ + w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), w(0x70), w(0x3e), \ + w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), w(0x61), \ + w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), \ + w(0x94), w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), \ + w(0x28), w(0xdf), w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), \ + w(0xe6), w(0x42), w(0x68), w(0x41), w(0x99), w(0x2d), w(0x0f), \ + w(0xb0), w(0x54), w(0xbb), w(0x16) \ + } +/* clang-format on */ + +/* X Macro trick. See https://en.wikipedia.org/wiki/X_Macro */ +#define SSE2NEON_AES_H0(x) (x) +static const uint8_t SSE2NEON_sbox[256] = SSE2NEON_AES_DATA(SSE2NEON_AES_H0); +#undef SSE2NEON_AES_H0 + +// In the absence of crypto extensions, implement aesenc using regular neon +// intrinsics instead. See: +// https://www.workofard.com/2017/01/accelerated-aes-for-the-arm64-linux-kernel/ +// https://www.workofard.com/2017/07/ghash-for-low-end-cores/ and +// https://github.com/ColinIanKing/linux-next-mirror/blob/b5f466091e130caaf0735976648f72bd5e09aa84/crypto/aegis128-neon-inner.c#L52 +// for more information Reproduced with permission of the author. +FORCE_INLINE __m128i _mm_aesenc_si128(__m128i EncBlock, __m128i RoundKey) +{ +#if defined(__aarch64__) + static const uint8_t shift_rows[] = {0x0, 0x5, 0xa, 0xf, 0x4, 0x9, + 0xe, 0x3, 0x8, 0xd, 0x2, 0x7, + 0xc, 0x1, 0x6, 0xb}; + static const uint8_t ror32by8[] = {0x1, 0x2, 0x3, 0x0, 0x5, 0x6, 0x7, 0x4, + 0x9, 0xa, 0xb, 0x8, 0xd, 0xe, 0xf, 0xc}; + + uint8x16_t v; + uint8x16_t w = vreinterpretq_u8_m128i(EncBlock); + + // shift rows + w = vqtbl1q_u8(w, vld1q_u8(shift_rows)); + + // sub bytes + v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(SSE2NEON_sbox), w); + v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(SSE2NEON_sbox + 0x40), w - 0x40); + v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(SSE2NEON_sbox + 0x80), w - 0x80); + v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(SSE2NEON_sbox + 0xc0), w - 0xc0); + + // mix columns + w = (v << 1) ^ (uint8x16_t)(((int8x16_t) v >> 7) & 0x1b); + w ^= (uint8x16_t) vrev32q_u16((uint16x8_t) v); + w ^= vqtbl1q_u8(v ^ w, vld1q_u8(ror32by8)); + + // add round key + return vreinterpretq_m128i_u8(w) ^ RoundKey; + +#else /* ARMv7-A NEON implementation */ +#define SSE2NEON_AES_B2W(b0, b1, b2, b3) \ + (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | \ + (b0)) +#define SSE2NEON_AES_F2(x) ((x << 1) ^ (((x >> 7) & 1) * 0x011b /* WPOLY */)) +#define SSE2NEON_AES_F3(x) (SSE2NEON_AES_F2(x) ^ x) +#define SSE2NEON_AES_U0(p) \ + SSE2NEON_AES_B2W(SSE2NEON_AES_F2(p), p, p, SSE2NEON_AES_F3(p)) +#define SSE2NEON_AES_U1(p) \ + SSE2NEON_AES_B2W(SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p, p) +#define SSE2NEON_AES_U2(p) \ + SSE2NEON_AES_B2W(p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p) +#define SSE2NEON_AES_U3(p) \ + SSE2NEON_AES_B2W(p, p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p)) + static const uint32_t ALIGN_STRUCT(16) aes_table[4][256] = { + SSE2NEON_AES_DATA(SSE2NEON_AES_U0), + SSE2NEON_AES_DATA(SSE2NEON_AES_U1), + SSE2NEON_AES_DATA(SSE2NEON_AES_U2), + SSE2NEON_AES_DATA(SSE2NEON_AES_U3), + }; +#undef SSE2NEON_AES_B2W +#undef SSE2NEON_AES_F2 +#undef SSE2NEON_AES_F3 +#undef SSE2NEON_AES_U0 +#undef SSE2NEON_AES_U1 +#undef SSE2NEON_AES_U2 +#undef SSE2NEON_AES_U3 + + uint32_t x0 = _mm_cvtsi128_si32(EncBlock); + uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0x55)); + uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0xAA)); + uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0xFF)); + + __m128i out = _mm_set_epi32( + (aes_table[0][x3 & 0xff] ^ aes_table[1][(x0 >> 8) & 0xff] ^ + aes_table[2][(x1 >> 16) & 0xff] ^ aes_table[3][x2 >> 24]), + (aes_table[0][x2 & 0xff] ^ aes_table[1][(x3 >> 8) & 0xff] ^ + aes_table[2][(x0 >> 16) & 0xff] ^ aes_table[3][x1 >> 24]), + (aes_table[0][x1 & 0xff] ^ aes_table[1][(x2 >> 8) & 0xff] ^ + aes_table[2][(x3 >> 16) & 0xff] ^ aes_table[3][x0 >> 24]), + (aes_table[0][x0 & 0xff] ^ aes_table[1][(x1 >> 8) & 0xff] ^ + aes_table[2][(x2 >> 16) & 0xff] ^ aes_table[3][x3 >> 24])); + + return _mm_xor_si128(out, RoundKey); +#endif +} + +// Perform the last round of an AES encryption flow on data (state) in a using +// the round key in RoundKey, and store the result in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128 +FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey) +{ + /* FIXME: optimized for NEON */ + uint8_t v[4][4] = { + {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 0)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 5)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 10)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 15)]}, + {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 4)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 9)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 14)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 3)]}, + {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 8)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 13)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 2)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 7)]}, + {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 12)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 1)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 6)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 11)]}, + }; + for (int i = 0; i < 16; i++) + vreinterpretq_nth_u8_m128i(a, i) = + v[i / 4][i % 4] ^ vreinterpretq_nth_u8_m128i(RoundKey, i); + return a; +} + +// Emits the Advanced Encryption Standard (AES) instruction aeskeygenassist. +// This instruction generates a round key for AES encryption. See +// https://kazakov.life/2017/11/01/cryptocurrency-mining-on-ios-devices/ +// for details. +// +// https://msdn.microsoft.com/en-us/library/cc714138(v=vs.120).aspx +FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i key, const int rcon) +{ + uint32_t X1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0x55)); + uint32_t X3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0xFF)); + for (int i = 0; i < 4; ++i) { + ((uint8_t *) &X1)[i] = SSE2NEON_sbox[((uint8_t *) &X1)[i]]; + ((uint8_t *) &X3)[i] = SSE2NEON_sbox[((uint8_t *) &X3)[i]]; + } + return _mm_set_epi32(((X3 >> 8) | (X3 << 24)) ^ rcon, X3, + ((X1 >> 8) | (X1 << 24)) ^ rcon, X1); +} +#undef SSE2NEON_AES_DATA + +#else /* __ARM_FEATURE_CRYPTO */ +// Implements equivalent of 'aesenc' by combining AESE (with an empty key) and +// AESMC and then manually applying the real key as an xor operation. This +// unfortunately means an additional xor op; the compiler should be able to +// optimize this away for repeated calls however. See +// https://blog.michaelbrase.com/2018/05/08/emulating-x86-aes-intrinsics-on-armv8-a +// for more details. +FORCE_INLINE __m128i _mm_aesenc_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vaesmcq_u8(vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0))) ^ + vreinterpretq_u8_m128i(b)); +} + +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128 +FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey) +{ + return _mm_xor_si128(vreinterpretq_m128i_u8(vaeseq_u8( + vreinterpretq_u8_m128i(a), vdupq_n_u8(0))), + RoundKey); +} + +FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i a, const int rcon) +{ + // AESE does ShiftRows and SubBytes on A + uint8x16_t u8 = vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0)); + + uint8x16_t dest = { + // Undo ShiftRows step from AESE and extract X1 and X3 + u8[0x4], u8[0x1], u8[0xE], u8[0xB], // SubBytes(X1) + u8[0x1], u8[0xE], u8[0xB], u8[0x4], // ROT(SubBytes(X1)) + u8[0xC], u8[0x9], u8[0x6], u8[0x3], // SubBytes(X3) + u8[0x9], u8[0x6], u8[0x3], u8[0xC], // ROT(SubBytes(X3)) + }; + uint32x4_t r = {0, (unsigned) rcon, 0, (unsigned) rcon}; + return vreinterpretq_m128i_u8(dest) ^ vreinterpretq_m128i_u32(r); +} +#endif + +/* Others */ + +// Perform a carry-less multiplication of two 64-bit integers, selected from a +// and b according to imm8, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clmulepi64_si128 +FORCE_INLINE __m128i _mm_clmulepi64_si128(__m128i _a, __m128i _b, const int imm) +{ + uint64x2_t a = vreinterpretq_u64_m128i(_a); + uint64x2_t b = vreinterpretq_u64_m128i(_b); + switch (imm & 0x11) { + case 0x00: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_low_u64(a), vget_low_u64(b))); + case 0x01: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_high_u64(a), vget_low_u64(b))); + case 0x10: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_low_u64(a), vget_high_u64(b))); + case 0x11: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_high_u64(a), vget_high_u64(b))); + default: + abort(); + } +} + +FORCE_INLINE unsigned int _sse2neon_mm_get_denormals_zero_mode() +{ + union { + fpcr_bitfield field; +#if defined(__aarch64__) + uint64_t value; +#else + uint32_t value; +#endif + } r; + +#if defined(__aarch64__) + asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */ +#else + asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */ +#endif + + return r.field.bit24 ? _MM_DENORMALS_ZERO_ON : _MM_DENORMALS_ZERO_OFF; +} + +// Count the number of bits set to 1 in unsigned 32-bit integer a, and +// return that count in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u32 +FORCE_INLINE int _mm_popcnt_u32(unsigned int a) +{ +#if defined(__aarch64__) +#if __has_builtin(__builtin_popcount) + return __builtin_popcount(a); +#else + return (int) vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t) a))); +#endif +#else + uint32_t count = 0; + uint8x8_t input_val, count8x8_val; + uint16x4_t count16x4_val; + uint32x2_t count32x2_val; + + input_val = vld1_u8((uint8_t *) &a); + count8x8_val = vcnt_u8(input_val); + count16x4_val = vpaddl_u8(count8x8_val); + count32x2_val = vpaddl_u16(count16x4_val); + + vst1_u32(&count, count32x2_val); + return count; +#endif +} + +// Count the number of bits set to 1 in unsigned 64-bit integer a, and +// return that count in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u64 +FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a) +{ +#if defined(__aarch64__) +#if __has_builtin(__builtin_popcountll) + return __builtin_popcountll(a); +#else + return (int64_t) vaddlv_u8(vcnt_u8(vcreate_u8(a))); +#endif +#else + uint64_t count = 0; + uint8x8_t input_val, count8x8_val; + uint16x4_t count16x4_val; + uint32x2_t count32x2_val; + uint64x1_t count64x1_val; + + input_val = vld1_u8((uint8_t *) &a); + count8x8_val = vcnt_u8(input_val); + count16x4_val = vpaddl_u8(count8x8_val); + count32x2_val = vpaddl_u16(count16x4_val); + count64x1_val = vpaddl_u32(count32x2_val); + vst1_u64(&count, count64x1_val); + return count; +#endif +} + +FORCE_INLINE void _sse2neon_mm_set_denormals_zero_mode(unsigned int flag) +{ + // AArch32 Advanced SIMD arithmetic always uses the Flush-to-zero setting, + // regardless of the value of the FZ bit. + union { + fpcr_bitfield field; +#if defined(__aarch64__) + uint64_t value; +#else + uint32_t value; +#endif + } r; + +#if defined(__aarch64__) + asm volatile("mrs %0, FPCR" : "=r"(r.value)); /* read */ +#else + asm volatile("vmrs %0, FPSCR" : "=r"(r.value)); /* read */ +#endif + + r.field.bit24 = (flag & _MM_DENORMALS_ZERO_MASK) == _MM_DENORMALS_ZERO_ON; + +#if defined(__aarch64__) + asm volatile("msr FPCR, %0" ::"r"(r)); /* write */ +#else + asm volatile("vmsr FPSCR, %0" ::"r"(r)); /* write */ +#endif +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma pop_macro("ALIGN_STRUCT") +#pragma pop_macro("FORCE_INLINE") +#endif + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC pop_options +#endif + +#endif \ No newline at end of file diff --git a/common/simd/avx.h b/common/simd/avx.h index c840e41805..d3100306ee 100644 --- a/common/simd/avx.h +++ b/common/simd/avx.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/simd/avx512.h b/common/simd/avx512.h index 25414ab5b1..d43bbacea1 100644 --- a/common/simd/avx512.h +++ b/common/simd/avx512.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/simd/simd.h b/common/simd/simd.h index c1351c2c88..34e37b08b1 100644 --- a/common/simd/simd.h +++ b/common/simd/simd.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,7 +6,7 @@ #include "../math/math.h" /* include SSE wrapper classes */ -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) # include "sse.h" #endif diff --git a/common/simd/sse.cpp b/common/simd/sse.cpp index 1732cfa421..535d6943d8 100644 --- a/common/simd/sse.cpp +++ b/common/simd/sse.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "sse.h" diff --git a/common/simd/sse.h b/common/simd/sse.h index 67df3ec009..04d90533dd 100644 --- a/common/simd/sse.h +++ b/common/simd/sse.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,7 +11,7 @@ namespace embree { -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) { return _mm_blendv_ps(f,t,mask); } diff --git a/common/simd/varying.h b/common/simd/varying.h index 9a46817da9..9b98d326be 100644 --- a/common/simd/varying.h +++ b/common/simd/varying.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -9,7 +9,7 @@ namespace embree { /* Varying numeric types */ template - struct vfloat + struct vfloat_impl { union { float f[N]; int i[N]; }; __forceinline const float& operator [](size_t index) const { assert(index < N); return f[index]; } @@ -17,7 +17,7 @@ namespace embree }; template - struct vdouble + struct vdouble_impl { union { double f[N]; long long i[N]; }; __forceinline const double& operator [](size_t index) const { assert(index < N); return f[index]; } @@ -25,7 +25,7 @@ namespace embree }; template - struct vint + struct vint_impl { int i[N]; __forceinline const int& operator [](size_t index) const { assert(index < N); return i[index]; } @@ -33,7 +33,7 @@ namespace embree }; template - struct vuint + struct vuint_impl { unsigned int i[N]; __forceinline const unsigned int& operator [](size_t index) const { assert(index < N); return i[index]; } @@ -41,7 +41,7 @@ namespace embree }; template - struct vllong + struct vllong_impl { long long i[N]; __forceinline const long long& operator [](size_t index) const { assert(index < N); return i[index]; } @@ -49,20 +49,13 @@ namespace embree }; /* Varying bool types */ - template struct vboolf { int i[N]; }; // for float/int - template struct vboold { long long i[N]; }; // for double/long long - - /* Aliases to default types */ - template using vreal = vfloat; - template using vbool = vboolf; - + template struct vboolf_impl { int i[N]; }; // for float/int + template struct vboold_impl { long long i[N]; }; // for double/long long + /* Varying size constants */ #if defined(__AVX512VL__) // SKX const int VSIZEX = 8; // default size const int VSIZEL = 16; // large size -#elif defined(__AVX512F__) // KNL - const int VSIZEX = 16; - const int VSIZEL = 16; #elif defined(__AVX__) const int VSIZEX = 8; const int VSIZEL = 8; @@ -71,21 +64,41 @@ namespace embree const int VSIZEL = 4; #endif - /* Extends varying size N to optimal or up to max(N, N2) */ - template - struct vextend - { -#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL - /* use 16-wide SIMD calculations on KNL even for 4 and 8 wide SIMD */ - static const int size = (N2 == VSIZEX) ? VSIZEX : N; - #define SIMD_MODE(N) N, 16 -#else - /* calculate with same SIMD width otherwise */ - static const int size = N; - #define SIMD_MODE(N) N, N -#endif + template + struct vtypes { + using vbool = vboolf_impl; + using vboolf = vboolf_impl; + using vboold = vboold_impl; + using vint = vint_impl; + using vuint = vuint_impl; + using vllong = vllong_impl; + using vfloat = vfloat_impl; + using vdouble = vdouble_impl; + }; + + template<> + struct vtypes<1> { + using vbool = bool; + using vboolf = bool; + using vboold = bool; + using vint = int; + using vuint = unsigned int; + using vllong = long long; + using vfloat = float; + using vdouble = double; }; + /* Aliases to default types */ + template using vbool = typename vtypes::vbool; + template using vboolf = typename vtypes::vboolf; + template using vboold = typename vtypes::vboold; + template using vint = typename vtypes::vint; + template using vuint = typename vtypes::vuint; + template using vllong = typename vtypes::vllong; + template using vreal = typename vtypes::vfloat; + template using vfloat = typename vtypes::vfloat; + template using vdouble = typename vtypes::vdouble; + /* 4-wide shortcuts */ typedef vfloat<4> vfloat4; typedef vdouble<4> vdouble4; diff --git a/common/simd/vboold4_avx.h b/common/simd/vboold4_avx.h index 44e423b001..450bd7a4eb 100644 --- a/common/simd/vboold4_avx.h +++ b/common/simd/vboold4_avx.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide AVX bool type for 64bit data types*/ @@ -49,14 +57,16 @@ namespace embree #endif } - __forceinline vboold(__m128d a, __m128d b) : vl(a), vh(b) {} - //////////////////////////////////////////////////////////////////////////////// /// Constants //////////////////////////////////////////////////////////////////////////////// __forceinline vboold(FalseTy) : v(_mm256_setzero_pd()) {} +#if !defined(__aarch64__) __forceinline vboold(TrueTy) : v(_mm256_cmp_pd(_mm256_setzero_pd(), _mm256_setzero_pd(), _CMP_EQ_OQ)) {} +#else + __forceinline vboold(TrueTy) : v(_mm256_cmpeq_pd(_mm256_setzero_pd(), _mm256_setzero_pd())) {} +#endif //////////////////////////////////////////////////////////////////////////////// /// Array Access @@ -101,9 +111,10 @@ namespace embree /// Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// +#if !defined(__aarch64__) __forceinline vboold4 unpacklo(const vboold4& a, const vboold4& b) { return _mm256_unpacklo_pd(a, b); } __forceinline vboold4 unpackhi(const vboold4& a, const vboold4& b) { return _mm256_unpackhi_pd(a, b); } - +#endif #if defined(__AVX2__) template @@ -153,3 +164,11 @@ namespace embree << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboold4_avx512.h b/common/simd/vboold4_avx512.h index 4fe730d713..ceaad7bba5 100644 --- a/common/simd/vboold4_avx512.h +++ b/common/simd/vboold4_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide AVX-512 bool type */ @@ -138,3 +146,11 @@ namespace embree return cout << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboold8_avx512.h b/common/simd/vboold8_avx512.h index fdf3f00de5..66d2054872 100644 --- a/common/simd/vboold8_avx512.h +++ b/common/simd/vboold8_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX-512 bool type */ @@ -32,25 +40,12 @@ namespace embree /* return int8 mask */ __forceinline __m128i mask8() const { -#if defined(__AVX512BW__) return _mm_movm_epi8(v); -#else - const __m512i f = _mm512_set1_epi64(0); - const __m512i t = _mm512_set1_epi64(-1); - const __m512i m = _mm512_mask_or_epi64(f,v,t,t); - return _mm512_cvtepi64_epi8(m); -#endif } /* return int64 mask */ __forceinline __m512i mask64() const { -#if defined(__AVX512DQ__) return _mm512_movm_epi64(v); -#else - const __m512i f = _mm512_set1_epi64(0); - const __m512i t = _mm512_set1_epi64(-1); - return _mm512_mask_or_epi64(f,v,t,t); -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -146,3 +141,11 @@ namespace embree return cout << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboolf16_avx512.h b/common/simd/vboolf16_avx512.h index 238cdc8eb9..86b718f025 100644 --- a/common/simd/vboolf16_avx512.h +++ b/common/simd/vboolf16_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 16-wide AVX-512 bool type */ @@ -33,25 +41,12 @@ namespace embree /* return int8 mask */ __forceinline __m128i mask8() const { -#if defined(__AVX512BW__) return _mm_movm_epi8(v); -#else - const __m512i f = _mm512_set1_epi32(0); - const __m512i t = _mm512_set1_epi32(-1); - const __m512i m = _mm512_mask_or_epi32(f,v,t,t); - return _mm512_cvtepi32_epi8(m); -#endif } /* return int32 mask */ __forceinline __m512i mask32() const { -#if defined(__AVX512DQ__) return _mm512_movm_epi32(v); -#else - const __m512i f = _mm512_set1_epi32(0); - const __m512i t = _mm512_set1_epi32(-1); - return _mm512_mask_or_epi32(f,v,t,t); -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -121,7 +116,7 @@ namespace embree __forceinline size_t popcnt (const vboolf16& a) { return popcnt(a.v); } //////////////////////////////////////////////////////////////////////////////// - /// Convertion Operations + /// Conversion Operations //////////////////////////////////////////////////////////////////////////////// __forceinline unsigned int toInt (const vboolf16& a) { return mm512_mask2int(a); } @@ -148,3 +143,11 @@ namespace embree return cout << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboolf4_avx512.h b/common/simd/vboolf4_avx512.h index 2ae4c4470e..e65f66b025 100644 --- a/common/simd/vboolf4_avx512.h +++ b/common/simd/vboolf4_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide AVX-512 bool type */ @@ -141,3 +149,11 @@ namespace embree return cout << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboolf4_sse2.h b/common/simd/vboolf4_sse2.h index afec10fd49..9e0fdf5c6f 100644 --- a/common/simd/vboolf4_sse2.h +++ b/common/simd/vboolf4_sse2.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide SSE bool type */ @@ -28,9 +36,11 @@ namespace embree __forceinline vboolf(__m128 input) : v(input) {} __forceinline operator const __m128&() const { return v; } + #if !defined(__EMSCRIPTEN__) __forceinline operator const __m128i() const { return _mm_castps_si128(v); } __forceinline operator const __m128d() const { return _mm_castps_pd(v); } - + #endif + __forceinline vboolf(bool a) : v(mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {} __forceinline vboolf(bool a, bool b) @@ -92,7 +102,7 @@ namespace embree __forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); } __forceinline vboolf4 select(const vboolf4& m, const vboolf4& t, const vboolf4& f) { -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) return _mm_blendv_ps(f, t, m); #else return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f)); @@ -106,6 +116,17 @@ namespace embree __forceinline vboolf4 unpacklo(const vboolf4& a, const vboolf4& b) { return _mm_unpacklo_ps(a, b); } __forceinline vboolf4 unpackhi(const vboolf4& a, const vboolf4& b) { return _mm_unpackhi_ps(a, b); } +#if defined(__aarch64__) + template + __forceinline vboolf4 shuffle(const vboolf4& v) { + return vreinterpretq_f32_u8(vqtbl1q_u8( vreinterpretq_u8_s32(v), _MN_SHUFFLE(i0, i1, i2, i3))); + } + + template + __forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) { + return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3))); + } +#else template __forceinline vboolf4 shuffle(const vboolf4& v) { return _mm_castsi128_ps(_mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0))); @@ -115,6 +136,7 @@ namespace embree __forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) { return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0)); } +#endif template __forceinline vboolf4 shuffle(const vboolf4& v) { @@ -127,7 +149,7 @@ namespace embree template<> __forceinline vboolf4 shuffle<0, 1, 0, 1>(const vboolf4& v) { return _mm_castpd_ps(_mm_movedup_pd(v)); } #endif -#if defined(__SSE4_1__) +#if defined(__SSE4_1__) && !defined(__aarch64__) template __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); } template __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return insert(a, b); } template __forceinline vboolf4 insert(const vboolf4& a, const bool b) { return insert(a, vboolf4(b)); } @@ -149,7 +171,9 @@ namespace embree __forceinline bool none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); } __forceinline size_t movemask(const vboolf4& a) { return _mm_movemask_ps(a); } -#if defined(__SSE4_2__) +#if defined(__aarch64__) + __forceinline size_t popcnt(const vboolf4& a) { return vaddvq_s32(vandq_u32(vreinterpretq_u32_f32(a.v),_mm_set1_epi32(1))); } +#elif defined(__SSE4_2__) __forceinline size_t popcnt(const vboolf4& a) { return popcnt((size_t)_mm_movemask_ps(a)); } #else __forceinline size_t popcnt(const vboolf4& a) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); } @@ -171,3 +195,11 @@ namespace embree return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboolf8_avx.h b/common/simd/vboolf8_avx.h index 5d7c0d68c1..18cede19c6 100644 --- a/common/simd/vboolf8_avx.h +++ b/common/simd/vboolf8_avx.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX bool type */ @@ -68,7 +76,7 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// __forceinline vboolf(FalseTy) : v(_mm256_setzero_ps()) {} - __forceinline vboolf(TrueTy) : v(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {} + __forceinline vboolf(TrueTy) : v(_mm256_castsi256_ps(_mm256_set1_epi32(0xFFFFFFFF))) {} //////////////////////////////////////////////////////////////////////////////// /// Array Access @@ -184,3 +192,11 @@ namespace embree << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vboolf8_avx512.h b/common/simd/vboolf8_avx512.h index 2a52b554c7..73ff5666e1 100644 --- a/common/simd/vboolf8_avx512.h +++ b/common/simd/vboolf8_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX-512 bool type */ @@ -141,3 +149,11 @@ namespace embree return cout << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vdouble4_avx.h b/common/simd/vdouble4_avx.h index eedb04aafb..208bb7ac99 100644 --- a/common/simd/vdouble4_avx.h +++ b/common/simd/vdouble4_avx.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide AVX 64-bit double type */ @@ -181,13 +189,20 @@ namespace embree __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GE); } __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_GT); } __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a, b, _MM_CMPINT_LE); } -#else +#elif !defined(__aarch64__) __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); } __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); } __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LT_OS); } __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLT_US); } __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_NLE_US); } __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a, b, _CMP_LE_OS); } +#else + __forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmpeq_pd(a, b); } + __forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmpneq_pd(a, b); } + __forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmplt_pd(a, b); } + __forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmpnlt_pd(a, b); } + __forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmpnle_pd(a, b); } + __forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmple_pd(a, b); } #endif __forceinline vboold4 operator ==(const vdouble4& a, double b) { return a == vdouble4(b); } @@ -239,18 +254,6 @@ namespace embree #endif } - __forceinline void xchg(const vboold4& m, vdouble4& a, vdouble4& b) { - const vdouble4 c = a; a = select(m,b,a); b = select(m,c,b); - } - - __forceinline vboold4 test(const vdouble4& a, const vdouble4& b) { -#if defined(__AVX512VL__) - return _mm256_test_epi64_mask(_mm256_castpd_si256(a),_mm256_castpd_si256(b)); -#else - return _mm256_testz_si256(_mm256_castpd_si256(a),_mm256_castpd_si256(b)); -#endif - } - //////////////////////////////////////////////////////////////////////////////// // Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -315,3 +318,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vdouble8_avx512.h b/common/simd/vdouble8_avx512.h index 4eec7d2f6a..98d21bfe4a 100644 --- a/common/simd/vdouble8_avx512.h +++ b/common/simd/vdouble8_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX-512 64-bit double type */ @@ -91,15 +99,6 @@ namespace embree _mm512_mask_store_pd(addr, mask, v2); } - /* pass by value to avoid compiler generating inefficient code */ - static __forceinline void storeu_compact(const vboold8 mask,void * addr, const vdouble8& reg) { - _mm512_mask_compressstoreu_pd(addr, mask, reg); - } - - static __forceinline vdouble8 compact64bit(const vboold8& mask, vdouble8& v) { - return _mm512_mask_compress_pd(v, mask, v); - } - static __forceinline vdouble8 compact(const vboold8& mask, vdouble8& v) { return _mm512_mask_compress_pd(v, mask, v); } @@ -260,18 +259,6 @@ namespace embree return _mm512_mask_or_pd(f,m,t,t); } - __forceinline void xchg(const vboold8& m, vdouble8& a, vdouble8& b) { - const vdouble8 c = a; a = select(m,b,a); b = select(m,c,b); - } - - __forceinline vboold8 test(const vboold8& m, const vdouble8& a, const vdouble8& b) { - return _mm512_mask_test_epi64_mask(m,_mm512_castpd_si512(a),_mm512_castpd_si512(b)); - } - - __forceinline vboold8 test(const vdouble8& a, const vdouble8& b) { - return _mm512_test_epi64_mask(_mm512_castpd_si512(a),_mm512_castpd_si512(b)); - } - //////////////////////////////////////////////////////////////////////////////// // Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -354,3 +341,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vfloat16_avx512.h b/common/simd/vfloat16_avx512.h index aed2419b77..75c471cc0c 100644 --- a/common/simd/vfloat16_avx512.h +++ b/common/simd/vfloat16_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 16-wide AVX-512 float type */ @@ -73,11 +81,11 @@ namespace embree } /* WARNING: due to f64x4 the mask is considered as an 8bit mask */ - __forceinline vfloat(const vboolf16& mask, const vfloat8& a, const vfloat8& b) { + /*__forceinline vfloat(const vboolf16& mask, const vfloat8& a, const vfloat8& b) { __m512d aa = _mm512_broadcast_f64x4(_mm256_castps_pd(a)); aa = _mm512_mask_broadcast_f64x4(aa,mask,_mm256_castps_pd(b)); v = _mm512_castpd_ps(aa); - } + }*/ __forceinline explicit vfloat(const vint16& a) { v = _mm512_cvtepi32_ps(a); @@ -123,30 +131,6 @@ namespace embree return _mm512_set1_ps(*f); } - static __forceinline vfloat16 compact(const vboolf16& mask, vfloat16 &v) { - return _mm512_mask_compress_ps(v, mask, v); - } - static __forceinline vfloat16 compact(const vboolf16& mask, vfloat16 &a, const vfloat16& b) { - return _mm512_mask_compress_ps(a, mask, b); - } - - static __forceinline vfloat16 expand(const vboolf16& mask, const vfloat16& a, vfloat16& b) { - return _mm512_mask_expand_ps(b, mask, a); - } - - static __forceinline vfloat16 loadu_compact(const vboolf16& mask, const void* ptr) { - return _mm512_mask_expandloadu_ps(_mm512_setzero_ps(), mask, (float*)ptr); - } - - static __forceinline void storeu_compact(const vboolf16& mask, float *addr, const vfloat16 reg) { - _mm512_mask_compressstoreu_ps(addr, mask, reg); - } - - static __forceinline void storeu_compact_single(const vboolf16& mask, float * addr, const vfloat16& reg) { - //_mm512_mask_compressstoreu_ps(addr,mask,reg); - *addr = mm512_cvtss_f32(_mm512_mask_compress_ps(reg, mask, reg)); - } - template static __forceinline vfloat16 gather(const float* ptr, const vint16& index) { return _mm512_i32gather_ps(index, ptr, scale); @@ -193,13 +177,10 @@ namespace embree __forceinline vfloat16 abs (const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x7FFFFFFF))); } __forceinline vfloat16 signmsk(const vfloat16& a) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); } - __forceinline vfloat16 rcp(const vfloat16& a) { -#if defined(__AVX512ER__) - return _mm512_rcp28_ps(a); -#else + __forceinline vfloat16 rcp(const vfloat16& a) + { const vfloat16 r = _mm512_rcp14_ps(a); - return _mm512_mul_ps(r, _mm512_fnmadd_ps(r, a, vfloat16(2.0f))); -#endif + return _mm512_fmadd_ps(r, _mm512_fnmadd_ps(a, r, vfloat16(1.0)), r); // computes r + r * (1 - a*r) } __forceinline vfloat16 sqr (const vfloat16& a) { return _mm512_mul_ps(a,a); } @@ -207,13 +188,9 @@ namespace embree __forceinline vfloat16 rsqrt(const vfloat16& a) { -#if defined(__AVX512VL__) const vfloat16 r = _mm512_rsqrt14_ps(a); return _mm512_fmadd_ps(_mm512_set1_ps(1.5f), r, _mm512_mul_ps(_mm512_mul_ps(_mm512_mul_ps(a, _mm512_set1_ps(-0.5f)), r), _mm512_mul_ps(r, r))); -#else - return _mm512_rsqrt28_ps(a); -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -242,54 +219,26 @@ namespace embree return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b))); } - __forceinline vfloat16 min(const vfloat16& a, const vfloat16& b) { - return _mm512_min_ps(a,b); - } - __forceinline vfloat16 min(const vfloat16& a, float b) { - return _mm512_min_ps(a,vfloat16(b)); - } - __forceinline vfloat16 min(const float& a, const vfloat16& b) { - return _mm512_min_ps(vfloat16(a),b); - } - - __forceinline vfloat16 max(const vfloat16& a, const vfloat16& b) { - return _mm512_max_ps(a,b); - } - __forceinline vfloat16 max(const vfloat16& a, float b) { - return _mm512_max_ps(a,vfloat16(b)); - } - __forceinline vfloat16 max(const float& a, const vfloat16& b) { - return _mm512_max_ps(vfloat16(a),b); - } + __forceinline vfloat16 min(const vfloat16& a, const vfloat16& b) { return _mm512_min_ps(a,b); } + __forceinline vfloat16 min(const vfloat16& a, float b) { return _mm512_min_ps(a,vfloat16(b)); } + __forceinline vfloat16 min(const float& a, const vfloat16& b) { return _mm512_min_ps(vfloat16(a),b); } - __forceinline vfloat16 mask_add(const vboolf16& mask, const vfloat16& c, const vfloat16& a, const vfloat16& b) { return _mm512_mask_add_ps (c,mask,a,b); } - __forceinline vfloat16 mask_min(const vboolf16& mask, const vfloat16& c, const vfloat16& a, const vfloat16& b) { - return _mm512_mask_min_ps(c,mask,a,b); - }; - __forceinline vfloat16 mask_max(const vboolf16& mask, const vfloat16& c, const vfloat16& a, const vfloat16& b) { - return _mm512_mask_max_ps(c,mask,a,b); - }; + __forceinline vfloat16 max(const vfloat16& a, const vfloat16& b) { return _mm512_max_ps(a,b); } + __forceinline vfloat16 max(const vfloat16& a, float b) { return _mm512_max_ps(a,vfloat16(b)); } + __forceinline vfloat16 max(const float& a, const vfloat16& b) { return _mm512_max_ps(vfloat16(a),b); } __forceinline vfloat16 mini(const vfloat16& a, const vfloat16& b) { -#if !defined(__AVX512ER__) // SKX const vint16 ai = _mm512_castps_si512(a); const vint16 bi = _mm512_castps_si512(b); const vint16 ci = _mm512_min_epi32(ai,bi); return _mm512_castsi512_ps(ci); -#else // KNL - return min(a,b); -#endif } __forceinline vfloat16 maxi(const vfloat16& a, const vfloat16& b) { -#if !defined(__AVX512ER__) // SKX const vint16 ai = _mm512_castps_si512(a); const vint16 bi = _mm512_castps_si512(b); const vint16 ci = _mm512_max_epi32(ai,bi); return _mm512_castsi512_ps(ci); -#else // KNL - return max(a,b); -#endif } //////////////////////////////////////////////////////////////////////////////// @@ -300,43 +249,6 @@ namespace embree __forceinline vfloat16 msub (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(a,b,c); } __forceinline vfloat16 nmadd(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmadd_ps(a,b,c); } __forceinline vfloat16 nmsub(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmsub_ps(a,b,c); } - - __forceinline vfloat16 mask_msub(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_fmsub_ps(a,mask,b,c); } - - __forceinline vfloat16 madd231 (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_ps(c,b,a); } - __forceinline vfloat16 msub213 (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(a,b,c); } - __forceinline vfloat16 msub231 (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmsub_ps(c,b,a); } - __forceinline vfloat16 msubr231(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fnmadd_ps(c,b,a); } - - - //////////////////////////////////////////////////////////////////////////////// - /// Operators with rounding - //////////////////////////////////////////////////////////////////////////////// - - __forceinline vfloat16 madd_round_down(const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 madd_round_up (const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 mul_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 mul_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 add_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 add_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 sub_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 sub_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 div_round_down(const vfloat16& a, const vfloat16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 div_round_up (const vfloat16& a, const vfloat16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 mask_msub_round_down(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 mask_msub_round_up (const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 mask_mul_round_down(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 mask_mul_round_up (const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - - __forceinline vfloat16 mask_sub_round_down(const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); } - __forceinline vfloat16 mask_sub_round_up (const vboolf16& mask,const vfloat16& a, const vfloat16& b, const vfloat16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); } - //////////////////////////////////////////////////////////////////////////////// /// Assignment Operators @@ -404,13 +316,6 @@ namespace embree return madd(t,b-a,a); } - __forceinline void xchg(vboolf16 m, vfloat16& a, vfloat16& b) - { - vfloat16 c = a; - a = select(m,b,a); - b = select(m,c,b); - } - //////////////////////////////////////////////////////////////////////////////// /// Rounding Functions //////////////////////////////////////////////////////////////////////////////// @@ -455,24 +360,6 @@ namespace embree return _mm512_shuffle_f32x4(v, v, _MM_SHUFFLE(i3, i2, i1, i0)); } - __forceinline vfloat16 interleave_even(const vfloat16& a, const vfloat16& b) { - return _mm512_castsi512_ps(_mm512_mask_shuffle_epi32(_mm512_castps_si512(a), mm512_int2mask(0xaaaa), _mm512_castps_si512(b), (_MM_PERM_ENUM)0xb1)); - } - - __forceinline vfloat16 interleave_odd(const vfloat16& a, const vfloat16& b) { - return _mm512_castsi512_ps(_mm512_mask_shuffle_epi32(_mm512_castps_si512(b), mm512_int2mask(0x5555), _mm512_castps_si512(a), (_MM_PERM_ENUM)0xb1)); - } - - __forceinline vfloat16 interleave2_even(const vfloat16& a, const vfloat16& b) { - /* mask should be 8-bit but is 16-bit to reuse for interleave_even */ - return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(a), mm512_int2mask(0xaaaa), _mm512_castps_si512(b), (_MM_PERM_ENUM)0xb1)); - } - - __forceinline vfloat16 interleave2_odd(const vfloat16& a, const vfloat16& b) { - /* mask should be 8-bit but is 16-bit to reuse for interleave_odd */ - return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(b), mm512_int2mask(0x5555), _mm512_castps_si512(a), (_MM_PERM_ENUM)0xb1)); - } - __forceinline vfloat16 interleave4_even(const vfloat16& a, const vfloat16& b) { return _mm512_castsi512_ps(_mm512_mask_permutex_epi64(_mm512_castps_si512(a), mm512_int2mask(0xcc), _mm512_castps_si512(b), (_MM_PERM_ENUM)0x4e)); } @@ -537,17 +424,6 @@ namespace embree __forceinline void transpose(const vfloat16& r0, const vfloat16& r1, const vfloat16& r2, const vfloat16& r3, vfloat16& c0, vfloat16& c1, vfloat16& c2, vfloat16& c3) { -#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL - vfloat16 a0a1_c0c1 = interleave_even(r0, r1); - vfloat16 a2a3_c2c3 = interleave_even(r2, r3); - vfloat16 b0b1_d0d1 = interleave_odd (r0, r1); - vfloat16 b2b3_d2d3 = interleave_odd (r2, r3); - - c0 = interleave2_even(a0a1_c0c1, a2a3_c2c3); - c1 = interleave2_even(b0b1_d0d1, b2b3_d2d3); - c2 = interleave2_odd (a0a1_c0c1, a2a3_c2c3); - c3 = interleave2_odd (b0b1_d0d1, b2b3_d2d3); -#else vfloat16 a0a2_b0b2 = unpacklo(r0, r2); vfloat16 c0c2_d0d2 = unpackhi(r0, r2); vfloat16 a1a3_b1b3 = unpacklo(r1, r3); @@ -557,7 +433,6 @@ namespace embree c1 = unpackhi(a0a2_b0b2, a1a3_b1b3); c2 = unpacklo(c0c2_d0d2, c1c3_d1d3); c3 = unpackhi(c0c2_d0d2, c1c3_d1d3); -#endif } __forceinline void transpose(const vfloat4& r0, const vfloat4& r1, const vfloat4& r2, const vfloat4& r3, @@ -715,44 +590,6 @@ namespace embree return v; } - //////////////////////////////////////////////////////////////////////////////// - /// Memory load and store operations - //////////////////////////////////////////////////////////////////////////////// - - __forceinline vfloat16 loadAOS4to16f(const float& x, const float& y, const float& z) - { - vfloat16 f = zero; - f = select(0x1111,vfloat16::broadcast(&x),f); - f = select(0x2222,vfloat16::broadcast(&y),f); - f = select(0x4444,vfloat16::broadcast(&z),f); - return f; - } - - __forceinline vfloat16 loadAOS4to16f(unsigned int index, - const vfloat16& x, - const vfloat16& y, - const vfloat16& z) - { - vfloat16 f = zero; - f = select(0x1111,vfloat16::broadcast((float*)&x + index),f); - f = select(0x2222,vfloat16::broadcast((float*)&y + index),f); - f = select(0x4444,vfloat16::broadcast((float*)&z + index),f); - return f; - } - - __forceinline vfloat16 loadAOS4to16f(unsigned int index, - const vfloat16& x, - const vfloat16& y, - const vfloat16& z, - const vfloat16& fill) - { - vfloat16 f = fill; - f = select(0x1111,vfloat16::broadcast((float*)&x + index),f); - f = select(0x2222,vfloat16::broadcast((float*)&y + index),f); - f = select(0x4444,vfloat16::broadcast((float*)&z + index),f); - return f; - } - __forceinline vfloat16 rcp_safe(const vfloat16& a) { return rcp(select(a != vfloat16(zero), a, vfloat16(min_rcp_input))); } @@ -769,3 +606,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vfloat4_sse2.h b/common/simd/vfloat4_sse2.h index 96f984cebd..6d7e11fe72 100644 --- a/common/simd/vfloat4_sse2.h +++ b/common/simd/vfloat4_sse2.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide SSE float type */ @@ -34,6 +42,11 @@ namespace embree __forceinline vfloat(float a, float b, float c, float d) : v(_mm_set_ps(d, c, b, a)) {} __forceinline explicit vfloat(const vint4& a) : v(_mm_cvtepi32_ps(a)) {} +#if defined(__aarch64__) + __forceinline explicit vfloat(const vuint4& x) { + v = vcvtq_f32_u32(vreinterpretq_u32_s32(x.v)); + } +#else __forceinline explicit vfloat(const vuint4& x) { const __m128i a = _mm_and_si128(x,_mm_set1_epi32(0x7FFFFFFF)); const __m128i b = _mm_and_si128(_mm_srai_epi32(x,31),_mm_set1_epi32(0x4F000000)); //0x4F000000 = 2^31 @@ -41,7 +54,7 @@ namespace embree const __m128 bf = _mm_castsi128_ps(b); v = _mm_add_ps(af,bf); } - +#endif //////////////////////////////////////////////////////////////////////////////// /// Constants //////////////////////////////////////////////////////////////////////////////// @@ -66,13 +79,6 @@ namespace embree #if defined(__AVX512VL__) - static __forceinline vfloat4 compact(const vboolf4& mask, vfloat4 &v) { - return _mm_mask_compress_ps(v, mask, v); - } - static __forceinline vfloat4 compact(const vboolf4& mask, vfloat4 &a, const vfloat4& b) { - return _mm_mask_compress_ps(a, mask, b); - } - static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_ps (_mm_setzero_ps(),mask,(float*)ptr); } static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_ps(_mm_setzero_ps(),mask,(float*)ptr); } @@ -106,7 +112,11 @@ namespace embree #endif } -#if defined(__SSE4_1__) +#if defined(__aarch64__) + static __forceinline vfloat4 load(const char* ptr) { + return __m128(_mm_load4epi8_f32(((__m128i*)ptr))); + } +#elif defined(__SSE4_1__) static __forceinline vfloat4 load(const char* ptr) { return _mm_cvtepi32_ps(_mm_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr))); } @@ -116,7 +126,11 @@ namespace embree } #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) + static __forceinline vfloat4 load(const unsigned char* ptr) { + return __m128(_mm_load4epu8_f32(((__m128i*)ptr))); + } +#elif defined(__SSE4_1__) static __forceinline vfloat4 load(const unsigned char* ptr) { return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr))); } @@ -127,7 +141,11 @@ namespace embree } #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) + static __forceinline vfloat4 load(const short* ptr) { + return __m128(_mm_load4epi16_f32(((__m128i*)ptr))); + } +#elif defined(__SSE4_1__) static __forceinline vfloat4 load(const short* ptr) { return _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr))); } @@ -144,7 +162,11 @@ namespace embree static __forceinline void store_nt(void* ptr, const vfloat4& v) { #if defined (__SSE4_1__) +#if defined(__aarch64__) _mm_stream_ps((float*)ptr,v); +#else + _mm_stream_ps((float*)ptr,v); +#endif #else _mm_store_ps((float*)ptr,v); #endif @@ -152,7 +174,7 @@ namespace embree template static __forceinline vfloat4 gather(const float* ptr, const vint4& index) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _mm_i32gather_ps(ptr, index, scale); #else return vfloat4( @@ -168,7 +190,7 @@ namespace embree vfloat4 r = zero; #if defined(__AVX512VL__) return _mm_mmask_i32gather_ps(r, mask, index, ptr, scale); -#elif defined(__AVX2__) +#elif defined(__AVX2__) && !defined(__aarch64__) return _mm_mask_i32gather_ps(r, ptr, index, mask, scale); #else if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]); @@ -222,15 +244,27 @@ namespace embree friend __forceinline vfloat4 select(const vboolf4& m, const vfloat4& t, const vfloat4& f) { #if defined(__AVX512VL__) return _mm_mask_blend_ps(m, f, t); -#elif defined(__SSE4_1__) - return _mm_blendv_ps(f, t, m); +#elif defined(__SSE4_1__) || (defined(__aarch64__)) + return _mm_blendv_ps(f, t, m); #else return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f)); #endif } }; + //////////////////////////////////////////////////////////////////////////////// + /// Load/Store + //////////////////////////////////////////////////////////////////////////////// + template<> struct mem + { + static __forceinline vfloat4 load (const vboolf4& mask, const void* ptr) { return vfloat4::load (mask,ptr); } + static __forceinline vfloat4 loadu(const vboolf4& mask, const void* ptr) { return vfloat4::loadu(mask,ptr); } + + static __forceinline void store (const vboolf4& mask, void* ptr, const vfloat4& v) { vfloat4::store (mask,ptr,v); } + static __forceinline void storeu(const vboolf4& mask, void* ptr, const vfloat4& v) { vfloat4::storeu(mask,ptr,v); } + }; + //////////////////////////////////////////////////////////////////////////////// /// Unary Operators //////////////////////////////////////////////////////////////////////////////// @@ -243,18 +277,34 @@ namespace embree __forceinline vfloat4 toFloat(const vint4& a) { return vfloat4(a); } __forceinline vfloat4 operator +(const vfloat4& a) { return a; } +#if defined(__aarch64__) + __forceinline vfloat4 operator -(const vfloat4& a) { + return vnegq_f32(a); + } +#else __forceinline vfloat4 operator -(const vfloat4& a) { return _mm_xor_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); } +#endif +#if defined(__aarch64__) + __forceinline vfloat4 abs(const vfloat4& a) { return _mm_abs_ps(a); } +#else __forceinline vfloat4 abs(const vfloat4& a) { return _mm_and_ps(a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); } +#endif + #if defined(__AVX512VL__) __forceinline vfloat4 sign(const vfloat4& a) { return _mm_mask_blend_ps(_mm_cmp_ps_mask(a, vfloat4(zero), _CMP_LT_OQ), vfloat4(one), -vfloat4(one)); } #else __forceinline vfloat4 sign(const vfloat4& a) { return blendv_ps(vfloat4(one), -vfloat4(one), _mm_cmplt_ps(a, vfloat4(zero))); } #endif + __forceinline vfloat4 signmsk(const vfloat4& a) { return _mm_and_ps(a,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); } - + __forceinline vfloat4 rcp(const vfloat4& a) { +#if defined(__aarch64__) + return vfloat4(vdivq_f32(vdupq_n_f32(1.0f),a.v)); +#else + #if defined(__AVX512VL__) const vfloat4 r = _mm_rcp14_ps(a); #else @@ -262,29 +312,40 @@ namespace embree #endif #if defined(__AVX2__) - return _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f))); + return _mm_fmadd_ps(r, _mm_fnmadd_ps(a, r, vfloat4(1.0f)), r); // computes r + r * (1 - a * r) #else - return _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a))); + return _mm_add_ps(r,_mm_mul_ps(r, _mm_sub_ps(vfloat4(1.0f), _mm_mul_ps(a, r)))); // computes r + r * (1 - a * r) #endif + +#endif //defined(__aarch64__) } __forceinline vfloat4 sqr (const vfloat4& a) { return _mm_mul_ps(a,a); } __forceinline vfloat4 sqrt(const vfloat4& a) { return _mm_sqrt_ps(a); } __forceinline vfloat4 rsqrt(const vfloat4& a) { +#if defined(__aarch64__) + vfloat4 r = _mm_rsqrt_ps(a); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r)); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r)); + r = vmulq_f32(r, vrsqrtsq_f32(vmulq_f32(a, r), r)); + return r; +#else + #if defined(__AVX512VL__) - const vfloat4 r = _mm_rsqrt14_ps(a); + vfloat4 r = _mm_rsqrt14_ps(a); #else - const vfloat4 r = _mm_rsqrt_ps(a); + vfloat4 r = _mm_rsqrt_ps(a); #endif #if defined(__AVX2__) - return _mm_fmadd_ps(_mm_set1_ps(1.5f), r, - _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); + r = _mm_fmadd_ps(_mm_set1_ps(1.5f), r, _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); #else - return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f), r), - _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); + r = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f), r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r))); #endif + +#endif + return r; } __forceinline vboolf4 isnan(const vfloat4& a) { @@ -329,7 +390,8 @@ namespace embree __forceinline vfloat4 max(const vfloat4& a, float b) { return _mm_max_ps(a,vfloat4(b)); } __forceinline vfloat4 max(float a, const vfloat4& b) { return _mm_max_ps(vfloat4(a),b); } -#if defined(__SSE4_1__) +#if defined(__SSE4_1__) || defined(__aarch64__) + __forceinline vfloat4 mini(const vfloat4& a, const vfloat4& b) { const vint4 ai = _mm_castps_si128(a); const vint4 bi = _mm_castps_si128(b); @@ -371,16 +433,17 @@ namespace embree /// Ternary Operators //////////////////////////////////////////////////////////////////////////////// -#if defined(__AVX2__) +#if defined(__AVX2__) || defined(__ARM_NEON) __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmadd_ps(a,b,c); } __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fmsub_ps(a,b,c); } __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmadd_ps(a,b,c); } __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return _mm_fnmsub_ps(a,b,c); } #else __forceinline vfloat4 madd (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b+c; } - __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b-c; } __forceinline vfloat4 nmadd(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b+c;} __forceinline vfloat4 nmsub(const vfloat4& a, const vfloat4& b, const vfloat4& c) { return -a*b-c; } + __forceinline vfloat4 msub (const vfloat4& a, const vfloat4& b, const vfloat4& c) { return a*b-c; } + #endif //////////////////////////////////////////////////////////////////////////////// @@ -414,8 +477,13 @@ namespace embree __forceinline vboolf4 operator ==(const vfloat4& a, const vfloat4& b) { return _mm_cmpeq_ps (a, b); } __forceinline vboolf4 operator !=(const vfloat4& a, const vfloat4& b) { return _mm_cmpneq_ps(a, b); } __forceinline vboolf4 operator < (const vfloat4& a, const vfloat4& b) { return _mm_cmplt_ps (a, b); } +#if defined(__aarch64__) + __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpge_ps (a, b); } + __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpgt_ps (a, b); } +#else __forceinline vboolf4 operator >=(const vfloat4& a, const vfloat4& b) { return _mm_cmpnlt_ps(a, b); } __forceinline vboolf4 operator > (const vfloat4& a, const vfloat4& b) { return _mm_cmpnle_ps(a, b); } +#endif __forceinline vboolf4 operator <=(const vfloat4& a, const vfloat4& b) { return _mm_cmple_ps (a, b); } #endif @@ -469,7 +537,7 @@ namespace embree return select(vboolf4(mask), t, f); #endif } - + __forceinline vfloat4 lerp(const vfloat4& a, const vfloat4& b, const vfloat4& t) { return madd(t,b-a,a); } @@ -490,7 +558,12 @@ namespace embree /// Rounding Functions //////////////////////////////////////////////////////////////////////////////// -#if defined (__SSE4_1__) +#if defined(__aarch64__) + __forceinline vfloat4 floor(const vfloat4& a) { return vrndmq_f32(a.v); } // towards -inf + __forceinline vfloat4 ceil (const vfloat4& a) { return vrndpq_f32(a.v); } // toward +inf + __forceinline vfloat4 trunc(const vfloat4& a) { return vrndq_f32(a.v); } // towards 0 + __forceinline vfloat4 round(const vfloat4& a) { return vrndnq_f32(a.v); } // to nearest, ties to even. NOTE(LTE): arm clang uses vrndnq, old gcc uses vrndqn? +#elif defined (__SSE4_1__) __forceinline vfloat4 floor(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); } __forceinline vfloat4 ceil (const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); } __forceinline vfloat4 trunc(const vfloat4& a) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); } @@ -504,7 +577,9 @@ namespace embree __forceinline vfloat4 frac(const vfloat4& a) { return a-floor(a); } __forceinline vint4 floori(const vfloat4& a) { -#if defined(__SSE4_1__) +#if defined(__aarch64__) + return vcvtq_s32_f32(floor(a)); +#elif defined(__SSE4_1__) return vint4(floor(a)); #else return vint4(a-vfloat4(0.5f)); @@ -518,6 +593,16 @@ namespace embree __forceinline vfloat4 unpacklo(const vfloat4& a, const vfloat4& b) { return _mm_unpacklo_ps(a, b); } __forceinline vfloat4 unpackhi(const vfloat4& a, const vfloat4& b) { return _mm_unpackhi_ps(a, b); } +#if defined(__aarch64__) + template + __forceinline vfloat4 shuffle(const vfloat4& v) { + return vreinterpretq_f32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3))); + } + template + __forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) { + return vreinterpretq_f32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3))); + } +#else template __forceinline vfloat4 shuffle(const vfloat4& v) { return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(v), _MM_SHUFFLE(i3, i2, i1, i0))); @@ -527,14 +612,9 @@ namespace embree __forceinline vfloat4 shuffle(const vfloat4& a, const vfloat4& b) { return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0)); } - -#if defined (__SSSE3__) - __forceinline vfloat4 shuffle8(const vfloat4& a, const vint4& shuf) { - return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf)); - } #endif -#if defined(__SSE3__) +#if defined(__SSE3__) && !defined(__aarch64__) template<> __forceinline vfloat4 shuffle<0, 0, 2, 2>(const vfloat4& v) { return _mm_moveldup_ps(v); } template<> __forceinline vfloat4 shuffle<1, 1, 3, 3>(const vfloat4& v) { return _mm_movehdup_ps(v); } template<> __forceinline vfloat4 shuffle<0, 1, 0, 1>(const vfloat4& v) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(v))); } @@ -545,14 +625,14 @@ namespace embree return shuffle(v); } -#if defined (__SSE4_1__) && !defined(__GNUC__) - template __forceinline float extract(const vfloat4& a) { return _mm_cvtss_f32(_mm_extract_ps(a,i)); } +#if defined(__aarch64__) + template __forceinline float extract(const vfloat4& a) { return a[i]; } #else - template __forceinline float extract(const vfloat4& a) { return _mm_cvtss_f32(shuffle(a)); } + template __forceinline float extract (const vfloat4& a) { return _mm_cvtss_f32(shuffle(a)); } + template<> __forceinline float extract<0>(const vfloat4& a) { return _mm_cvtss_f32(a); } #endif - template<> __forceinline float extract<0>(const vfloat4& a) { return _mm_cvtss_f32(a); } -#if defined (__SSE4_1__) +#if defined (__SSE4_1__) && !defined(__aarch64__) template __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); } template __forceinline vfloat4 insert(const vfloat4& a, const vfloat4& b) { return insert(a, b); } template __forceinline vfloat4 insert(const vfloat4& a, const float b) { return insert(a, _mm_set_ss(b)); } @@ -563,10 +643,6 @@ namespace embree __forceinline float toScalar(const vfloat4& v) { return _mm_cvtss_f32(v); } - __forceinline vfloat4 broadcast4f(const vfloat4& a, size_t k) { - return vfloat4::broadcast(&a[k]); - } - __forceinline vfloat4 shift_right_1(const vfloat4& x) { return _mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(x), 4)); } @@ -658,14 +734,25 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// /// Reductions //////////////////////////////////////////////////////////////////////////////// - +#if defined(__aarch64__) + __forceinline vfloat4 vreduce_min(const vfloat4& v) { float h = vminvq_f32(v); return vdupq_n_f32(h); } + __forceinline vfloat4 vreduce_max(const vfloat4& v) { float h = vmaxvq_f32(v); return vdupq_n_f32(h); } + __forceinline vfloat4 vreduce_add(const vfloat4& v) { float h = vaddvq_f32(v); return vdupq_n_f32(h); } +#else __forceinline vfloat4 vreduce_min(const vfloat4& v) { vfloat4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); } __forceinline vfloat4 vreduce_max(const vfloat4& v) { vfloat4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); } __forceinline vfloat4 vreduce_add(const vfloat4& v) { vfloat4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; } +#endif +#if defined(__aarch64__) + __forceinline float reduce_min(const vfloat4& v) { return vminvq_f32(v); } + __forceinline float reduce_max(const vfloat4& v) { return vmaxvq_f32(v); } + __forceinline float reduce_add(const vfloat4& v) { return vaddvq_f32(v); } +#else __forceinline float reduce_min(const vfloat4& v) { return _mm_cvtss_f32(vreduce_min(v)); } __forceinline float reduce_max(const vfloat4& v) { return _mm_cvtss_f32(vreduce_max(v)); } __forceinline float reduce_add(const vfloat4& v) { return _mm_cvtss_f32(vreduce_add(v)); } +#endif __forceinline size_t select_min(const vboolf4& valid, const vfloat4& v) { @@ -681,7 +768,7 @@ namespace embree } //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators + /// Euclidean Space Operators //////////////////////////////////////////////////////////////////////////////// __forceinline float dot(const vfloat4& a, const vfloat4& b) { @@ -706,3 +793,11 @@ namespace embree } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vfloat8_avx.h b/common/simd/vfloat8_avx.h index 64af5f7526..b09d5e641d 100644 --- a/common/simd/vfloat8_avx.h +++ b/common/simd/vfloat8_avx.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX float type */ @@ -61,20 +69,6 @@ namespace embree return _mm256_broadcast_ss((float*)a); } - static __forceinline vfloat8 broadcast2(const float* a, const float* b) { -#if defined(__INTEL_COMPILER) - const vfloat8 v0 = _mm256_broadcast_ss(a); - const vfloat8 v1 = _mm256_broadcast_ss(b); - return _mm256_blend_ps(v1, v0, 0xf); -#else - return _mm256_set_ps(*b,*b,*b,*b,*a,*a,*a,*a); -#endif - } - - static __forceinline vfloat8 broadcast4f(const vfloat4* ptr) { - return _mm256_broadcast_ps((__m128*)ptr); - } - static __forceinline vfloat8 load(const char* ptr) { #if defined(__AVX2__) return _mm256_cvtepi32_ps(_mm256_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr))); @@ -107,24 +101,17 @@ namespace embree #if defined(__AVX512VL__) - static __forceinline vfloat8 compact(const vboolf8& mask, vfloat8 &v) { - return _mm256_mask_compress_ps(v, mask, v); - } - static __forceinline vfloat8 compact(const vboolf8& mask, vfloat8 &a, const vfloat8& b) { - return _mm256_mask_compress_ps(a, mask, b); - } - static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_ps (_mm256_setzero_ps(),mask,(float*)ptr); } static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_ps(_mm256_setzero_ps(),mask,(float*)ptr); } static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_store_ps ((float*)ptr,mask,v); } static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_mask_storeu_ps((float*)ptr,mask,v); } #else - static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); } - static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,(__m256i)mask); } + static __forceinline vfloat8 load (const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,_mm256_castps_si256(mask.v)); } + static __forceinline vfloat8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_maskload_ps((float*)ptr,_mm256_castps_si256(mask.v)); } - static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); } - static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,v); } + static __forceinline void store (const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),v); } + static __forceinline void storeu(const vboolf8& mask, void* ptr, const vfloat8& v) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),v); } #endif #if defined(__AVX2__) @@ -139,7 +126,7 @@ namespace embree template static __forceinline vfloat8 gather(const float* ptr, const vint8& index) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _mm256_i32gather_ps(ptr, index ,scale); #else return vfloat8( @@ -159,7 +146,7 @@ namespace embree vfloat8 r = zero; #if defined(__AVX512VL__) return _mm256_mmask_i32gather_ps(r, mask, index, ptr, scale); -#elif defined(__AVX2__) +#elif defined(__AVX2__) && !defined(__aarch64__) return _mm256_mask_i32gather_ps(r, ptr, index, mask, scale); #else if (likely(mask[0])) r[0] = *(float*)(((char*)ptr)+scale*index[0]); @@ -208,13 +195,6 @@ namespace embree #endif } - static __forceinline void store(const vboolf8& mask, char* ptr, const vint8& ofs, const vfloat8& v) { - scatter<1>(mask,ptr,ofs,v); - } - static __forceinline void store(const vboolf8& mask, float* ptr, const vint8& ofs, const vfloat8& v) { - scatter<4>(mask,ptr,ofs,v); - } - //////////////////////////////////////////////////////////////////////////////// /// Array Access //////////////////////////////////////////////////////////////////////////////// @@ -235,20 +215,52 @@ namespace embree __forceinline vfloat8 toFloat(const vint8& a) { return vfloat8(a); } __forceinline vfloat8 operator +(const vfloat8& a) { return a; } +#if !defined(__aarch64__) __forceinline vfloat8 operator -(const vfloat8& a) { const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000)); return _mm256_xor_ps(a, mask); } +#else + __forceinline vfloat8 operator -(const vfloat8& a) { + __m256 res; + res.lo = vnegq_f32(a.v.lo); + res.hi = vnegq_f32(a.v.hi); + return res; +} +#endif + +#if !defined(__aarch64__) __forceinline vfloat8 abs(const vfloat8& a) { const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff)); return _mm256_and_ps(a, mask); } +#else +__forceinline vfloat8 abs(const vfloat8& a) { + __m256 res; + res.lo = vabsq_f32(a.v.lo); + res.hi = vabsq_f32(a.v.hi); + return res; +} +#endif + +#if !defined(__aarch64__) __forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmp_ps(a, vfloat8(zero), _CMP_NGE_UQ)); } +#else + __forceinline vfloat8 sign (const vfloat8& a) { return _mm256_blendv_ps(vfloat8(one), -vfloat8(one), _mm256_cmplt_ps(a, vfloat8(zero))); } +#endif __forceinline vfloat8 signmsk(const vfloat8& a) { return _mm256_and_ps(a,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); } - __forceinline vfloat8 rcp(const vfloat8& a) + static __forceinline vfloat8 rcp(const vfloat8& a) { +#if defined(__aarch64__) + vfloat8 ret; + const float32x4_t one = vdupq_n_f32(1.0f); + ret.v.lo = vdivq_f32(one, a.v.lo); + ret.v.hi = vdivq_f32(one, a.v.hi); + return ret; +#endif + #if defined(__AVX512VL__) const vfloat8 r = _mm256_rcp14_ps(a); #else @@ -256,15 +268,18 @@ namespace embree #endif #if defined(__AVX2__) - return _mm256_mul_ps(r, _mm256_fnmadd_ps(r, a, vfloat8(2.0f))); + // First, compute 1 - a * r (which will be very close to 0) + const vfloat8 h_n = _mm256_fnmadd_ps(a, r, vfloat8(1.0f)); + // Then compute r + r * h_n + return _mm256_fmadd_ps(r, h_n, r); #else - return _mm256_mul_ps(r, _mm256_sub_ps(vfloat8(2.0f), _mm256_mul_ps(r, a))); + return _mm256_add_ps(r,_mm256_mul_ps(r, _mm256_sub_ps(vfloat8(1.0f), _mm256_mul_ps(a, r)))); // computes r + r * (1 - a * r) #endif } __forceinline vfloat8 sqr (const vfloat8& a) { return _mm256_mul_ps(a,a); } __forceinline vfloat8 sqrt(const vfloat8& a) { return _mm256_sqrt_ps(a); } - __forceinline vfloat8 rsqrt(const vfloat8& a) + static __forceinline vfloat8 rsqrt(const vfloat8& a) { #if defined(__AVX512VL__) const vfloat8 r = _mm256_rsqrt14_ps(a); @@ -314,30 +329,31 @@ namespace embree __forceinline vfloat8 max(const vfloat8& a, float b) { return _mm256_max_ps(a, vfloat8(b)); } __forceinline vfloat8 max(float a, const vfloat8& b) { return _mm256_max_ps(vfloat8(a), b); } + /* need "static __forceinline for MSVC, otherwise we'll link the wrong version in debug mode */ #if defined(__AVX2__) - __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) { + static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) { const vint8 ai = _mm256_castps_si256(a); const vint8 bi = _mm256_castps_si256(b); const vint8 ci = _mm256_min_epi32(ai,bi); return _mm256_castsi256_ps(ci); } - __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) { + static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) { const vint8 ai = _mm256_castps_si256(a); const vint8 bi = _mm256_castps_si256(b); const vint8 ci = _mm256_max_epi32(ai,bi); return _mm256_castsi256_ps(ci); } - __forceinline vfloat8 minui(const vfloat8& a, const vfloat8& b) { + static __forceinline vfloat8 minui(const vfloat8& a, const vfloat8& b) { const vint8 ai = _mm256_castps_si256(a); const vint8 bi = _mm256_castps_si256(b); const vint8 ci = _mm256_min_epu32(ai,bi); return _mm256_castsi256_ps(ci); } - __forceinline vfloat8 maxui(const vfloat8& a, const vfloat8& b) { + static __forceinline vfloat8 maxui(const vfloat8& a, const vfloat8& b) { const vint8 ai = _mm256_castps_si256(a); const vint8 bi = _mm256_castps_si256(b); const vint8 ci = _mm256_max_epu32(ai,bi); @@ -346,12 +362,12 @@ namespace embree #else - __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) { - return min(a,b); + static __forceinline vfloat8 mini(const vfloat8& a, const vfloat8& b) { + return asFloat(min(asInt(a),asInt(b))); } - __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) { - return max(a,b); + static __forceinline vfloat8 maxi(const vfloat8& a, const vfloat8& b) { + return asFloat(max(asInt(a),asInt(b))); } #endif @@ -361,15 +377,15 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// #if defined(__AVX2__) - __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmadd_ps(a,b,c); } - __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmsub_ps(a,b,c); } - __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmadd_ps(a,b,c); } - __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmsub_ps(a,b,c); } + static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmadd_ps(a,b,c); } + static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fmsub_ps(a,b,c); } + static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmadd_ps(a,b,c); } + static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return _mm256_fnmsub_ps(a,b,c); } #else - __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b+c; } - __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b-c; } - __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b+c;} - __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b-c; } + static __forceinline vfloat8 madd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b+c; } + static __forceinline vfloat8 msub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return a*b-c; } + static __forceinline vfloat8 nmadd (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b+c;} + static __forceinline vfloat8 nmsub (const vfloat8& a, const vfloat8& b, const vfloat8& c) { return -a*b-c; } #endif //////////////////////////////////////////////////////////////////////////////// @@ -393,27 +409,39 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// #if defined(__AVX512VL__) - __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_EQ); } - __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_NE); } - __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LT); } - __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GE); } - __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GT); } - __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LE); } - - __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) { + static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_EQ); } + static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_NE); } + static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LT); } + static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GE); } + static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_GT); } + static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps_mask(a, b, _MM_CMPINT_LE); } + + static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) { return _mm256_mask_blend_ps(m, f, t); } -#else - __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); } - __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); } - __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); } - __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); } - __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); } - __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); } - - __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) { +#elif !defined(__aarch64__) + static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); } + static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); } + static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); } + static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); } + static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); } + static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); } + + static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) { return _mm256_blendv_ps(f, t, m); } +#else + static __forceinline vboolf8 operator ==(const vfloat8& a, const vfloat8& b) { return _mm256_cmpeq_ps(a, b); } + static __forceinline vboolf8 operator !=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpneq_ps(a, b); } + static __forceinline vboolf8 operator < (const vfloat8& a, const vfloat8& b) { return _mm256_cmplt_ps(a, b); } + static __forceinline vboolf8 operator >=(const vfloat8& a, const vfloat8& b) { return _mm256_cmpge_ps(a, b); } + static __forceinline vboolf8 operator > (const vfloat8& a, const vfloat8& b) { return _mm256_cmpgt_ps(a, b); } + static __forceinline vboolf8 operator <=(const vfloat8& a, const vfloat8& b) { return _mm256_cmple_ps(a, b); } + + static __forceinline vfloat8 select(const vboolf8& m, const vfloat8& t, const vfloat8& f) { + return _mm256_blendv_ps(f, t, m); + } + #endif template @@ -447,19 +475,19 @@ namespace embree __forceinline vboolf8 le(const vfloat8& a, const vfloat8& b) { return a <= b; } #if defined(__AVX512VL__) - __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); } - __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); } - __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); } - __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); } - __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); } - __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); } + static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); } + static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); } + static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); } + static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); } + static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); } + static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return _mm256_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); } #else - __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a == b); } - __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a != b); } - __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a < b); } - __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a >= b); } - __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a > b); } - __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a <= b); } + static __forceinline vboolf8 eq(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a == b); } + static __forceinline vboolf8 ne(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a != b); } + static __forceinline vboolf8 lt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a < b); } + static __forceinline vboolf8 ge(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a >= b); } + static __forceinline vboolf8 gt(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a > b); } + static __forceinline vboolf8 le(const vboolf8& mask, const vfloat8& a, const vfloat8& b) { return mask & (a <= b); } #endif __forceinline vfloat8 lerp(const vfloat8& a, const vfloat8& b, const vfloat8& t) { @@ -482,10 +510,17 @@ namespace embree /// Rounding Functions //////////////////////////////////////////////////////////////////////////////// +#if !defined(__aarch64__) __forceinline vfloat8 floor(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); } __forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); } __forceinline vfloat8 trunc(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); } __forceinline vfloat8 round(const vfloat8& a) { return _mm256_round_ps(a, _MM_FROUND_TO_NEAREST_INT); } +#else + __forceinline vfloat8 floor(const vfloat8& a) { return _mm256_floor_ps(a); } + __forceinline vfloat8 ceil (const vfloat8& a) { return _mm256_ceil_ps(a); } +#endif + + __forceinline vfloat8 frac (const vfloat8& a) { return a-floor(a); } //////////////////////////////////////////////////////////////////////////////// @@ -520,9 +555,11 @@ namespace embree return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0)); } +#if !defined(__aarch64__) template<> __forceinline vfloat8 shuffle<0, 0, 2, 2>(const vfloat8& v) { return _mm256_moveldup_ps(v); } template<> __forceinline vfloat8 shuffle<1, 1, 3, 3>(const vfloat8& v) { return _mm256_movehdup_ps(v); } template<> __forceinline vfloat8 shuffle<0, 1, 0, 1>(const vfloat8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); } +#endif __forceinline vfloat8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); } template __forceinline vfloat8 insert4(const vfloat8& a, const vfloat4& b) { return _mm256_insertf128_ps(a, b, i); } @@ -531,46 +568,36 @@ namespace embree __forceinline float toScalar(const vfloat8& v) { return _mm_cvtss_f32(_mm256_castps256_ps128(v)); } - __forceinline vfloat8 assign(const vfloat4& a) { return _mm256_castps128_ps256(a); } - -#if defined (__AVX2__) - __forceinline vfloat8 permute(const vfloat8& a, const __m256i& index) { +#if defined (__AVX2__) && !defined(__aarch64__) + static __forceinline vfloat8 permute(const vfloat8& a, const __m256i& index) { return _mm256_permutevar8x32_ps(a, index); } #endif #if defined(__AVX512VL__) template - __forceinline vfloat8 align_shift_right(const vfloat8& a, const vfloat8& b) { + static __forceinline vfloat8 align_shift_right(const vfloat8& a, const vfloat8& b) { return _mm256_castsi256_ps(_mm256_alignr_epi32(_mm256_castps_si256(a), _mm256_castps_si256(b), i)); } #endif #if defined (__AVX_I__) template - __forceinline vint4 convert_to_hf16(const vfloat8& a) { + static __forceinline vint4 convert_to_hf16(const vfloat8& a) { return _mm256_cvtps_ph(a, mode); } - __forceinline vfloat8 convert_from_hf16(const vint4& a) { + static __forceinline vfloat8 convert_from_hf16(const vint4& a) { return _mm256_cvtph_ps(a); } #endif - __forceinline vfloat4 broadcast4f(const vfloat8& a, const size_t k) { - return vfloat4::broadcast(&a[k]); - } - - __forceinline vfloat8 broadcast8f(const vfloat8& a, const size_t k) { - return vfloat8::broadcast(&a[k]); - } - #if defined(__AVX512VL__) - __forceinline vfloat8 shift_right_1(const vfloat8& x) { + static __forceinline vfloat8 shift_right_1(const vfloat8& x) { return align_shift_right<1>(zero,x); } #else - __forceinline vfloat8 shift_right_1(const vfloat8& x) { + static __forceinline vfloat8 shift_right_1(const vfloat8& x) { const vfloat8 t0 = shuffle<1,2,3,0>(x); const vfloat8 t1 = shuffle4<1,0>(t0); return _mm256_blend_ps(t0,t1,0x88); @@ -638,7 +665,7 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// /// Reductions //////////////////////////////////////////////////////////////////////////////// - +#if !defined(__aarch64__) __forceinline vfloat8 vreduce_min2(const vfloat8& v) { return min(v,shuffle<1,0,3,2>(v)); } __forceinline vfloat8 vreduce_min4(const vfloat8& v) { vfloat8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); } __forceinline vfloat8 vreduce_min (const vfloat8& v) { vfloat8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); } @@ -654,7 +681,14 @@ namespace embree __forceinline float reduce_min(const vfloat8& v) { return toScalar(vreduce_min(v)); } __forceinline float reduce_max(const vfloat8& v) { return toScalar(vreduce_max(v)); } __forceinline float reduce_add(const vfloat8& v) { return toScalar(vreduce_add(v)); } +#else + __forceinline float reduce_min(const vfloat8& v) { return vminvq_f32(_mm_min_ps(v.v.lo,v.v.hi)); } + __forceinline float reduce_max(const vfloat8& v) { return vmaxvq_f32(_mm_max_ps(v.v.lo,v.v.hi)); } + __forceinline vfloat8 vreduce_min(const vfloat8& v) { return vfloat8(reduce_min(v)); } + __forceinline vfloat8 vreduce_max(const vfloat8& v) { return vfloat8(reduce_max(v)); } + __forceinline float reduce_add(const vfloat8& v) { return vaddvq_f32(_mm_add_ps(v.v.lo,v.v.hi)); } +#endif __forceinline size_t select_min(const vboolf8& valid, const vfloat8& v) { const vfloat8 a = select(valid,v,vfloat8(pos_inf)); @@ -671,7 +705,7 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// - /// Euclidian Space Operators (pairs of Vec3fa's) + /// Euclidean Space Operators (pairs of Vec3fa's) //////////////////////////////////////////////////////////////////////////////// //__forceinline vfloat8 dot(const vfloat8& a, const vfloat8& b) { @@ -777,3 +811,11 @@ namespace embree return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vint16_avx512.h b/common/simd/vint16_avx512.h index 34e3d5ca07..3720c3c9d6 100644 --- a/common/simd/vint16_avx512.h +++ b/common/simd/vint16_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 16-wide AVX-512 integer type */ @@ -109,20 +117,6 @@ namespace embree static __forceinline void store_nt(void* __restrict__ ptr, const vint16& a) { _mm512_stream_si512((__m512i*)ptr,a); } - /* pass by value to avoid compiler generating inefficient code */ - static __forceinline void storeu_compact(const vboolf16 mask, void* addr, vint16 reg) { - _mm512_mask_compressstoreu_epi32(addr,mask,reg); - } - - static __forceinline void storeu_compact_single(const vboolf16 mask, void* addr, vint16 reg) { - //_mm512_mask_compressstoreu_epi32(addr,mask,reg); - *(float*)addr = mm512_cvtss_f32(_mm512_mask_compress_ps(_mm512_castsi512_ps(reg),mask,_mm512_castsi512_ps(reg))); - } - - static __forceinline vint16 compact64bit(const vboolf16& mask, vint16 &v) { - return _mm512_mask_compress_epi64(v,mask,v); - } - static __forceinline vint16 compact(const vboolf16& mask, vint16 &v) { return _mm512_mask_compress_epi32(v,mask,v); } @@ -160,10 +154,6 @@ namespace embree _mm512_mask_i32scatter_epi32((int*)ptr,mask,index,v,scale); } - static __forceinline vint16 broadcast64bit(size_t v) { - return _mm512_set1_epi64(v); - } - //////////////////////////////////////////////////////////////////////////////// /// Array Access //////////////////////////////////////////////////////////////////////////////// @@ -313,18 +303,6 @@ namespace embree return _mm512_mask_or_epi32(f,m,t,t); } - __forceinline void xchg(const vboolf16& m, vint16& a, vint16& b) { - const vint16 c = a; a = select(m,b,a); b = select(m,c,b); - } - - __forceinline vboolf16 test(const vboolf16& m, const vint16& a, const vint16& b) { - return _mm512_mask_test_epi32_mask(m,a,b); - } - - __forceinline vboolf16 test(const vint16& a, const vint16& b) { - return _mm512_test_epi32_mask(a,b); - } - //////////////////////////////////////////////////////////////////////////////// // Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -363,10 +341,6 @@ namespace embree template __forceinline vint16 insert4(const vint16& a, const vint4& b) { return _mm512_inserti32x4(a, b, i); } - __forceinline size_t extract64bit(const vint16& v) { - return _mm_cvtsi128_si64(_mm512_castsi512_si128(v)); - } - template vint extractN(const vint16& v); @@ -488,3 +462,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vint4_sse2.h b/common/simd/vint4_sse2.h index 458f8cfaa6..eea03a771e 100644 --- a/common/simd/vint4_sse2.h +++ b/common/simd/vint4_sse2.h @@ -1,10 +1,18 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../math/math.h" +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide SSE integer type */ @@ -98,7 +106,14 @@ namespace embree #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) + static __forceinline vint4 load(const unsigned char* ptr) { + return _mm_load4epu8_epi32(((__m128i*)ptr)); + } + static __forceinline vint4 loadu(const unsigned char* ptr) { + return _mm_load4epu8_epi32(((__m128i*)ptr)); + } +#elif defined(__SSE4_1__) static __forceinline vint4 load(const unsigned char* ptr) { return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); } @@ -119,7 +134,9 @@ namespace embree #endif static __forceinline vint4 load(const unsigned short* ptr) { -#if defined (__SSE4_1__) +#if defined(__aarch64__) + return __m128i(vmovl_u16(vld1_u16(ptr))); +#elif defined (__SSE4_1__) return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); #else return vint4(ptr[0],ptr[1],ptr[2],ptr[3]); @@ -127,7 +144,12 @@ namespace embree } static __forceinline void store(unsigned char* ptr, const vint4& v) { -#if defined(__SSE4_1__) +#if defined(__aarch64__) + int32x4_t x = v; + uint16x4_t y = vqmovn_u32(uint32x4_t(x)); + uint8x8_t z = vqmovn_u16(vcombine_u16(y, y)); + vst1_lane_u32((uint32_t *)ptr,uint32x2_t(z), 0); +#elif defined(__SSE4_1__) __m128i x = v; x = _mm_packus_epi32(x, x); x = _mm_packus_epi16(x, x); @@ -139,20 +161,26 @@ namespace embree } static __forceinline void store(unsigned short* ptr, const vint4& v) { +#if defined(__aarch64__) + uint32x4_t x = uint32x4_t(v.v); + uint16x4_t y = vqmovn_u32(x); + vst1_u16(ptr, y); +#else for (size_t i=0;i<4;i++) ptr[i] = (unsigned short)v[i]; +#endif } static __forceinline vint4 load_nt(void* ptr) { -#if defined(__SSE4_1__) - return _mm_stream_load_si128((__m128i*)ptr); +#if defined(__aarch64__) || defined(__SSE4_1__) + return _mm_stream_load_si128((__m128i*)ptr); #else return _mm_load_si128((__m128i*)ptr); #endif } static __forceinline void store_nt(void* ptr, const vint4& v) { -#if defined(__SSE4_1__) +#if !defined(__aarch64__) && defined(__SSE4_1__) _mm_stream_ps((float*)ptr, _mm_castsi128_ps(v)); #else _mm_store_si128((__m128i*)ptr,v); @@ -161,7 +189,7 @@ namespace embree template static __forceinline vint4 gather(const int* ptr, const vint4& index) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _mm_i32gather_epi32(ptr, index, scale); #else return vint4( @@ -177,7 +205,7 @@ namespace embree vint4 r = zero; #if defined(__AVX512VL__) return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale); -#elif defined(__AVX2__) +#elif defined(__AVX2__) && !defined(__aarch64__) return _mm_mask_i32gather_epi32(r, ptr, index, mask, scale); #else if (likely(mask[0])) r[0] = *(int*)(((char*)ptr)+scale*index[0]); @@ -214,7 +242,7 @@ namespace embree #endif } -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__aarch64__) static __forceinline vint4 broadcast64(long long a) { return _mm_set1_epi64x(a); } #endif @@ -228,6 +256,8 @@ namespace embree friend __forceinline vint4 select(const vboolf4& m, const vint4& t, const vint4& f) { #if defined(__AVX512VL__) return _mm_mask_blend_epi32(m, (__m128i)f, (__m128i)t); +#elif defined(__aarch64__) + return _mm_castps_si128(_mm_blendv_ps((__m128)f.v,(__m128) t.v, (__m128)m.v)); #elif defined(__SSE4_1__) return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m)); #else @@ -248,7 +278,9 @@ namespace embree __forceinline vint4 operator +(const vint4& a) { return a; } __forceinline vint4 operator -(const vint4& a) { return _mm_sub_epi32(_mm_setzero_si128(), a); } -#if defined(__SSSE3__) +#if defined(__aarch64__) + __forceinline vint4 abs(const vint4& a) { return vabsq_s32(a.v); } +#elif defined(__SSSE3__) __forceinline vint4 abs(const vint4& a) { return _mm_abs_epi32(a); } #endif @@ -264,7 +296,7 @@ namespace embree __forceinline vint4 operator -(const vint4& a, int b) { return a - vint4(b); } __forceinline vint4 operator -(int a, const vint4& b) { return vint4(a) - b; } -#if defined(__SSE4_1__) +#if (defined(__aarch64__)) || defined(__SSE4_1__) __forceinline vint4 operator *(const vint4& a, const vint4& b) { return _mm_mullo_epi32(a, b); } #else __forceinline vint4 operator *(const vint4& a, const vint4& b) { return vint4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); } @@ -284,8 +316,8 @@ namespace embree __forceinline vint4 operator ^(const vint4& a, int b) { return a ^ vint4(b); } __forceinline vint4 operator ^(int a, const vint4& b) { return vint4(a) ^ b; } - __forceinline vint4 operator <<(const vint4& a, int n) { return _mm_slli_epi32(a, n); } - __forceinline vint4 operator >>(const vint4& a, int n) { return _mm_srai_epi32(a, n); } + __forceinline vint4 operator <<(const vint4& a, const int n) { return _mm_slli_epi32(a, n); } + __forceinline vint4 operator >>(const vint4& a, const int n) { return _mm_srai_epi32(a, n); } __forceinline vint4 sll (const vint4& a, int b) { return _mm_slli_epi32(a, b); } __forceinline vint4 sra (const vint4& a, int b) { return _mm_srai_epi32(a, b); } @@ -301,7 +333,7 @@ namespace embree __forceinline vint4& operator -=(vint4& a, const vint4& b) { return a = a - b; } __forceinline vint4& operator -=(vint4& a, int b) { return a = a - b; } -#if defined(__SSE4_1__) +#if (defined(__aarch64__)) || defined(__SSE4_1__) __forceinline vint4& operator *=(vint4& a, const vint4& b) { return a = a * b; } __forceinline vint4& operator *=(vint4& a, int b) { return a = a * b; } #endif @@ -385,7 +417,7 @@ namespace embree #endif } -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) __forceinline vint4 min(const vint4& a, const vint4& b) { return _mm_min_epi32(a, b); } __forceinline vint4 max(const vint4& a, const vint4& b) { return _mm_max_epi32(a, b); } @@ -409,6 +441,16 @@ namespace embree __forceinline vint4 unpacklo(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); } __forceinline vint4 unpackhi(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); } +#if defined(__aarch64__) + template + __forceinline vint4 shuffle(const vint4& v) { + return vreinterpretq_s32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3))); + } + template + __forceinline vint4 shuffle(const vint4& a, const vint4& b) { + return vreinterpretq_s32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3))); + } +#else template __forceinline vint4 shuffle(const vint4& v) { return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)); @@ -418,7 +460,7 @@ namespace embree __forceinline vint4 shuffle(const vint4& a, const vint4& b) { return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0))); } - +#endif #if defined(__SSE3__) template<> __forceinline vint4 shuffle<0, 0, 2, 2>(const vint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); } template<> __forceinline vint4 shuffle<1, 1, 3, 3>(const vint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); } @@ -430,7 +472,7 @@ namespace embree return shuffle(v); } -#if defined(__SSE4_1__) +#if defined(__SSE4_1__) && !defined(__aarch64__) template __forceinline int extract(const vint4& b) { return _mm_extract_epi32(b, src); } template __forceinline vint4 insert(const vint4& a, const int b) { return _mm_insert_epi32(a, b, dst); } #else @@ -438,18 +480,27 @@ namespace embree template __forceinline vint4 insert(const vint4& a, int b) { vint4 c = a; c[dst&3] = b; return c; } #endif - template<> __forceinline int extract<0>(const vint4& b) { return _mm_cvtsi128_si32(b); } - + __forceinline int toScalar(const vint4& v) { return _mm_cvtsi128_si32(v); } - - __forceinline size_t toSizeT(const vint4& v) { + +#if defined(__aarch64__) + __forceinline size_t toSizeT(const vint4& v) { + uint64x2_t x = uint64x2_t(v.v); + return x[0]; + } +#else +__forceinline size_t toSizeT(const vint4& v) { #if defined(__WIN32__) && !defined(__X86_64__) // win32 workaround return toScalar(v); +#elif defined(__ARM_NEON) + // FIXME(LTE): Do we need a swap(i.e. use lane 1)? + return vgetq_lane_u64(*(reinterpret_cast(&v)), 0); #else return _mm_cvtsi128_si64(v); #endif } +#endif #if defined(__AVX512VL__) @@ -467,7 +518,17 @@ namespace embree /// Reductions //////////////////////////////////////////////////////////////////////////////// -#if defined(__SSE4_1__) +#if defined(__aarch64__) || defined(__SSE4_1__) + +#if defined(__aarch64__) + __forceinline vint4 vreduce_min(const vint4& v) { int h = vminvq_s32(v); return vdupq_n_s32(h); } + __forceinline vint4 vreduce_max(const vint4& v) { int h = vmaxvq_s32(v); return vdupq_n_s32(h); } + __forceinline vint4 vreduce_add(const vint4& v) { int h = vaddvq_s32(v); return vdupq_n_s32(h); } + + __forceinline int reduce_min(const vint4& v) { return vminvq_s32(v); } + __forceinline int reduce_max(const vint4& v) { return vmaxvq_s32(v); } + __forceinline int reduce_add(const vint4& v) { return vaddvq_s32(v); } +#else __forceinline vint4 vreduce_min(const vint4& v) { vint4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); } __forceinline vint4 vreduce_max(const vint4& v) { vint4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); } __forceinline vint4 vreduce_add(const vint4& v) { vint4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; } @@ -475,6 +536,7 @@ namespace embree __forceinline int reduce_min(const vint4& v) { return toScalar(vreduce_min(v)); } __forceinline int reduce_max(const vint4& v) { return toScalar(vreduce_max(v)); } __forceinline int reduce_add(const vint4& v) { return toScalar(vreduce_add(v)); } +#endif __forceinline size_t select_min(const vint4& v) { return bsf(movemask(v == vreduce_min(v))); } __forceinline size_t select_max(const vint4& v) { return bsf(movemask(v == vreduce_max(v))); } @@ -494,7 +556,7 @@ namespace embree /// Sorting networks //////////////////////////////////////////////////////////////////////////////// -#if defined(__SSE4_1__) +#if (defined(__aarch64__)) || defined(__SSE4_1__) __forceinline vint4 usort_ascending(const vint4& v) { @@ -581,3 +643,10 @@ namespace embree } } +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vint8_avx.h b/common/simd/vint8_avx.h index c373907e9c..48f5a9b203 100644 --- a/common/simd/vint8_avx.h +++ b/common/simd/vint8_avx.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX integer type */ @@ -71,8 +79,8 @@ namespace embree static __forceinline void store (void* ptr, const vint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); } static __forceinline void storeu(void* ptr, const vint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); } - static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); } - static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); } + static __forceinline void store (const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); } + static __forceinline void storeu(const vboolf8& mask, void* ptr, const vint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); } static __forceinline void store_nt(void* ptr, const vint8& v) { _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v)); @@ -310,11 +318,6 @@ namespace embree return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m)); } - __forceinline vint8 notand(const vboolf8& m, const vint8& f) { - return _mm256_castps_si256(_mm256_andnot_ps(m, _mm256_castsi256_ps(f))); - } - - //////////////////////////////////////////////////////////////////////////////// /// Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -457,3 +460,11 @@ namespace embree return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vint8_avx2.h b/common/simd/vint8_avx2.h index 989c85dac7..d48efac3f4 100644 --- a/common/simd/vint8_avx2.h +++ b/common/simd/vint8_avx2.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX integer type */ @@ -183,9 +191,9 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// #if defined(__AVX512VL__) - __forceinline vboolf8 asBool(const vint8& a) { return _mm256_movepi32_mask(a); } + static __forceinline vboolf8 asBool(const vint8& a) { return _mm256_movepi32_mask(a); } #else - __forceinline vboolf8 asBool(const vint8& a) { return _mm256_castsi256_ps(a); } + static __forceinline vboolf8 asBool(const vint8& a) { return _mm256_castsi256_ps(a); } #endif __forceinline vint8 operator +(const vint8& a) { return a; } @@ -272,25 +280,25 @@ namespace embree //////////////////////////////////////////////////////////////////////////////// #if defined(__AVX512VL__) - __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); } - __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_NE); } - __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LT); } - __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GE); } - __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GT); } - __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LE); } - - __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) { + static __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); } + static __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_NE); } + static __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LT); } + static __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GE); } + static __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_GT); } + static __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return _mm256_cmp_epi32_mask(a,b,_MM_CMPINT_LE); } + + static __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) { return _mm256_mask_blend_epi32(m, (__m256i)f, (__m256i)t); } #else - __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); } - __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return !(a == b); } - __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(b, a)); } - __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return !(a < b); } - __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(a, b)); } - __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return !(a > b); } - - __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) { + static __forceinline vboolf8 operator ==(const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); } + static __forceinline vboolf8 operator !=(const vint8& a, const vint8& b) { return !(a == b); } + static __forceinline vboolf8 operator < (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(b, a)); } + static __forceinline vboolf8 operator >=(const vint8& a, const vint8& b) { return !(a < b); } + static __forceinline vboolf8 operator > (const vint8& a, const vint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32(a, b)); } + static __forceinline vboolf8 operator <=(const vint8& a, const vint8& b) { return !(a > b); } + + static __forceinline vint8 select(const vboolf8& m, const vint8& t, const vint8& f) { return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m)); } #endif @@ -326,19 +334,19 @@ namespace embree __forceinline vboolf8 le(const vint8& a, const vint8& b) { return a <= b; } #if defined(__AVX512VL__) - __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); } - __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); } - __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); } - __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); } - __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); } - __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); } + static __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); } + static __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); } + static __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); } + static __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); } + static __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); } + static __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); } #else - __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a == b); } - __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a != b); } - __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a < b); } - __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a >= b); } - __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a > b); } - __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a <= b); } + static __forceinline vboolf8 eq(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a == b); } + static __forceinline vboolf8 ne(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a != b); } + static __forceinline vboolf8 lt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a < b); } + static __forceinline vboolf8 ge(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a >= b); } + static __forceinline vboolf8 gt(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a > b); } + static __forceinline vboolf8 le(const vboolf8& mask, const vint8& a, const vint8& b) { return mask & (a <= b); } #endif //////////////////////////////////////////////////////////////////////////////// @@ -385,6 +393,7 @@ namespace embree __forceinline int toScalar(const vint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); } +#if !defined(__aarch64__) __forceinline vint8 permute(const vint8& v, const __m256i& index) { return _mm256_permutevar8x32_epi32(v, index); } @@ -394,7 +403,7 @@ namespace embree } template - __forceinline vint8 align_shift_right(const vint8& a, const vint8& b) { + static __forceinline vint8 align_shift_right(const vint8& a, const vint8& b) { #if defined(__AVX512VL__) return _mm256_alignr_epi32(a, b, i); #else @@ -402,6 +411,9 @@ namespace embree #endif } +#endif + + //////////////////////////////////////////////////////////////////////////////// /// Reductions //////////////////////////////////////////////////////////////////////////////// @@ -428,9 +440,6 @@ namespace embree __forceinline size_t select_min(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); } __forceinline size_t select_max(const vboolf8& valid, const vint8& v) { const vint8 a = select(valid,v,vint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); } - - __forceinline vint8 assign(const vint4& a) { return _mm256_castsi128_si256(a); } - //////////////////////////////////////////////////////////////////////////////// /// Sorting networks //////////////////////////////////////////////////////////////////////////////// @@ -503,3 +512,11 @@ namespace embree return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vllong4_avx2.h b/common/simd/vllong4_avx2.h index de3ebc16a7..6c86845877 100644 --- a/common/simd/vllong4_avx2.h +++ b/common/simd/vllong4_avx2.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide AVX2 64-bit long long type */ @@ -95,16 +103,6 @@ namespace embree #endif } - static __forceinline vllong4 broadcast64bit(size_t v) { - return _mm256_set1_epi64x(v); - } - - static __forceinline size_t extract64bit(const vllong4& v) - { - return _mm_cvtsi128_si64(_mm256_castsi256_si128(v)); - } - - //////////////////////////////////////////////////////////////////////////////// /// Array Access //////////////////////////////////////////////////////////////////////////////// @@ -276,18 +274,6 @@ namespace embree __forceinline vboold4 le(const vboold4& mask, const vllong4& a, const vllong4& b) { return mask & (a <= b); } #endif - __forceinline void xchg(const vboold4& m, vllong4& a, vllong4& b) { - const vllong4 c = a; a = select(m,b,a); b = select(m,c,b); - } - - __forceinline vboold4 test(const vllong4& a, const vllong4& b) { -#if defined(__AVX512VL__) - return _mm256_test_epi64_mask(a,b); -#else - return _mm256_testz_si256(a,b); -#endif - } - //////////////////////////////////////////////////////////////////////////////// // Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -356,3 +342,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vllong8_avx512.h b/common/simd/vllong8_avx512.h index 4a724de062..ee69411637 100644 --- a/common/simd/vllong8_avx512.h +++ b/common/simd/vllong8_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX-512 64-bit long long type */ @@ -98,19 +106,6 @@ namespace embree _mm512_mask_store_epi64(addr,mask,v2); } - /* pass by value to avoid compiler generating inefficient code */ - static __forceinline void storeu_compact(const vboold8 mask, void* addr, const vllong8& reg) { - _mm512_mask_compressstoreu_epi64(addr,mask,reg); - } - - static __forceinline vllong8 compact64bit(const vboold8& mask, vllong8& v) { - return _mm512_mask_compress_epi64(v,mask,v); - } - - static __forceinline vllong8 compact64bit(const vboold8& mask, vllong8& dest, const vllong8& source) { - return _mm512_mask_compress_epi64(dest,mask,source); - } - static __forceinline vllong8 compact(const vboold8& mask, vllong8& v) { return _mm512_mask_compress_epi64(v,mask,v); } @@ -123,16 +118,6 @@ namespace embree return _mm512_mask_expand_epi64(b,mask,a); } - static __forceinline vllong8 broadcast64bit(size_t v) { - return _mm512_set1_epi64(v); - } - - static __forceinline size_t extract64bit(const vllong8& v) - { - return _mm_cvtsi128_si64(_mm512_castsi512_si128(v)); - } - - //////////////////////////////////////////////////////////////////////////////// /// Array Access //////////////////////////////////////////////////////////////////////////////// @@ -271,18 +256,6 @@ namespace embree return _mm512_mask_or_epi64(f,m,t,t); } - __forceinline void xchg(const vboold8& m, vllong8& a, vllong8& b) { - const vllong8 c = a; a = select(m,b,a); b = select(m,c,b); - } - - __forceinline vboold8 test(const vboold8& m, const vllong8& a, const vllong8& b) { - return _mm512_mask_test_epi64_mask(m,a,b); - } - - __forceinline vboold8 test(const vllong8& a, const vllong8& b) { - return _mm512_test_epi64_mask(a,b); - } - //////////////////////////////////////////////////////////////////////////////// // Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -321,10 +294,6 @@ namespace embree return _mm_cvtsi128_si64(_mm512_castsi512_si128(v)); } - __forceinline vllong8 zeroExtend32Bit(const __m512i& a) { - return _mm512_cvtepu32_epi64(_mm512_castsi512_si256(a)); - } - //////////////////////////////////////////////////////////////////////////////// /// Reductions //////////////////////////////////////////////////////////////////////////////// @@ -379,3 +348,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vuint16_avx512.h b/common/simd/vuint16_avx512.h index c5a2bb0478..c9eb6682ff 100644 --- a/common/simd/vuint16_avx512.h +++ b/common/simd/vuint16_avx512.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 16-wide AVX-512 unsigned integer type */ @@ -113,20 +121,6 @@ namespace embree _mm512_mask_store_epi32(addr,mask,v2); } - /* pass by value to avoid compiler generating inefficient code */ - static __forceinline void storeu_compact(const vboolf16 mask, void* addr, const vuint16 reg) { - _mm512_mask_compressstoreu_epi32(addr,mask,reg); - } - - static __forceinline void storeu_compact_single(const vboolf16 mask, void* addr, vuint16 reg) { - //_mm512_mask_compressstoreu_epi32(addr,mask,reg); - *(float*)addr = mm512_cvtss_f32(_mm512_mask_compress_ps(_mm512_castsi512_ps(reg),mask,_mm512_castsi512_ps(reg))); - } - - static __forceinline vuint16 compact64bit(const vboolf16& mask, vuint16& v) { - return _mm512_mask_compress_epi64(v,mask,v); - } - static __forceinline vuint16 compact(const vboolf16& mask, vuint16& v) { return _mm512_mask_compress_epi32(v,mask,v); } @@ -164,15 +158,6 @@ namespace embree _mm512_mask_i32scatter_epi32((int*)ptr,mask,index,v,scale); } - static __forceinline vuint16 broadcast64bit(size_t v) { - return _mm512_set1_epi64(v); - } - - static __forceinline size_t extract64bit(const vuint16& v) - { - return _mm_cvtsi128_si64(_mm512_castsi512_si128(v)); - } - //////////////////////////////////////////////////////////////////////////////// /// Array Access //////////////////////////////////////////////////////////////////////////////// @@ -315,18 +300,6 @@ namespace embree return _mm512_mask_or_epi32(f,m,t,t); } - __forceinline void xchg(const vboolf16& m, vuint16& a, vuint16& b) { - const vuint16 c = a; a = select(m,b,a); b = select(m,c,b); - } - - __forceinline vboolf16 test(const vboolf16& m, const vuint16& a, const vuint16& b) { - return _mm512_mask_test_epi32_mask(m,a,b); - } - - __forceinline vboolf16 test(const vuint16& a, const vuint16& b) { - return _mm512_test_epi32_mask(a,b); - } - //////////////////////////////////////////////////////////////////////////////// // Movement/Shifting/Shuffling Functions //////////////////////////////////////////////////////////////////////////////// @@ -441,3 +414,11 @@ namespace embree return cout; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vuint4_sse2.h b/common/simd/vuint4_sse2.h index 396eb45d5d..f7817da6be 100644 --- a/common/simd/vuint4_sse2.h +++ b/common/simd/vuint4_sse2.h @@ -1,10 +1,18 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../math/math.h" +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 4-wide SSE integer type */ @@ -87,7 +95,14 @@ namespace embree static __forceinline void storeu(const vboolf4& mask, void* ptr, const vuint4& i) { storeu(ptr,select(mask,i,loadu(ptr))); } #endif -#if defined(__SSE4_1__) +#if defined(__aarch64__) + static __forceinline vuint4 load(const unsigned char* ptr) { + return _mm_load4epu8_epi32(((__m128i*)ptr)); + } + static __forceinline vuint4 loadu(const unsigned char* ptr) { + return _mm_load4epu8_epi32(((__m128i*)ptr)); + } +#elif defined(__SSE4_1__) static __forceinline vuint4 load(const unsigned char* ptr) { return _mm_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); } @@ -99,32 +114,17 @@ namespace embree #endif static __forceinline vuint4 load(const unsigned short* ptr) { -#if defined (__SSE4_1__) +#if defined(__aarch64__) + return _mm_load4epu16_epi32(((__m128i*)ptr)); +#elif defined (__SSE4_1__) return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); #else return vuint4(ptr[0],ptr[1],ptr[2],ptr[3]); #endif } - static __forceinline void store_uchar(unsigned char* ptr, const vuint4& v) { -#if defined(__SSE4_1__) - __m128i x = v; - x = _mm_packus_epi32(x, x); - x = _mm_packus_epi16(x, x); - *(unsigned*)ptr = _mm_cvtsi128_si32(x); -#else - for (size_t i=0;i<4;i++) - ptr[i] = (unsigned char)v[i]; -#endif - } - - static __forceinline void store_uchar(unsigned short* ptr, const vuint4& v) { - for (size_t i=0;i<4;i++) - ptr[i] = (unsigned short)v[i]; - } - static __forceinline vuint4 load_nt(void* ptr) { -#if defined(__SSE4_1__) +#if (defined(__aarch64__)) || defined(__SSE4_1__) return _mm_stream_load_si128((__m128i*)ptr); #else return _mm_load_si128((__m128i*)ptr); @@ -132,8 +132,8 @@ namespace embree } static __forceinline void store_nt(void* ptr, const vuint4& v) { -#if defined(__SSE4_1__) - _mm_stream_ps((float*)ptr,_mm_castsi128_ps(v)); +#if !defined(__aarch64__) && defined(__SSE4_1__) + _mm_stream_ps((float*)ptr, _mm_castsi128_ps(v)); #else _mm_store_si128((__m128i*)ptr,v); #endif @@ -141,7 +141,7 @@ namespace embree template static __forceinline vuint4 gather(const unsigned int* ptr, const vint4& index) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _mm_i32gather_epi32((const int*)ptr, index, scale); #else return vuint4( @@ -157,7 +157,7 @@ namespace embree vuint4 r = zero; #if defined(__AVX512VL__) return _mm_mmask_i32gather_epi32(r, mask, index, ptr, scale); -#elif defined(__AVX2__) +#elif defined(__AVX2__) && !defined(__aarch64__) return _mm_mask_i32gather_epi32(r, (const int*)ptr, index, mask, scale); #else if (likely(mask[0])) r[0] = *(unsigned int*)(((char*)ptr)+scale*index[0]); @@ -353,6 +353,16 @@ namespace embree __forceinline vuint4 unpacklo(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); } __forceinline vuint4 unpackhi(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); } +#if defined(__aarch64__) + template + __forceinline vuint4 shuffle(const vuint4& v) { + return vreinterpretq_s32_u8(vqtbl1q_u8( (uint8x16_t)v.v, _MN_SHUFFLE(i0, i1, i2, i3))); + } + template + __forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) { + return vreinterpretq_s32_u8(vqtbl2q_u8( (uint8x16x2_t){(uint8x16_t)a.v, (uint8x16_t)b.v}, _MF_SHUFFLE(i0, i1, i2, i3))); + } +#else template __forceinline vuint4 shuffle(const vuint4& v) { return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)); @@ -362,7 +372,7 @@ namespace embree __forceinline vuint4 shuffle(const vuint4& a, const vuint4& b) { return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0))); } - +#endif #if defined(__SSE3__) template<> __forceinline vuint4 shuffle<0, 0, 2, 2>(const vuint4& v) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(v))); } template<> __forceinline vuint4 shuffle<1, 1, 3, 3>(const vuint4& v) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(v))); } @@ -374,7 +384,7 @@ namespace embree return shuffle(v); } -#if defined(__SSE4_1__) +#if defined(__SSE4_1__) && !defined(__aarch64__) template __forceinline unsigned int extract(const vuint4& b) { return _mm_extract_epi32(b, src); } template __forceinline vuint4 insert(const vuint4& a, const unsigned b) { return _mm_insert_epi32(a, b, dst); } #else @@ -382,7 +392,6 @@ namespace embree template __forceinline vuint4 insert(const vuint4& a, const unsigned b) { vuint4 c = a; c[dst&3] = b; return c; } #endif - template<> __forceinline unsigned int extract<0>(const vuint4& b) { return _mm_cvtsi128_si32(b); } __forceinline unsigned int toScalar(const vuint4& v) { return _mm_cvtsi128_si32(v); } @@ -426,3 +435,10 @@ namespace embree } } +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vuint8_avx.h b/common/simd/vuint8_avx.h index 437e73c7fb..cb8b5158c1 100644 --- a/common/simd/vuint8_avx.h +++ b/common/simd/vuint8_avx.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX integer type */ @@ -69,8 +77,8 @@ namespace embree static __forceinline void store (void* ptr, const vuint8& f) { _mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f)); } static __forceinline void storeu(void* ptr, const vuint8& f) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f)); } - static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); } - static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f)); } + static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); } + static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& f) { _mm256_maskstore_ps((float*)ptr,_mm256_castps_si256(mask.v),_mm256_castsi256_ps(f)); } static __forceinline void store_nt(void* ptr, const vuint8& v) { _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v)); @@ -290,10 +298,6 @@ namespace embree return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m)); } - __forceinline vuint8 notand(const vboolf8& m, const vuint8& f) { - return _mm256_castps_si256(_mm256_andnot_ps(m, _mm256_castsi256_ps(f))); - } - //////////////////////////////////////////////////////////////////////////////// /// Movement/Shifting/Shuffling Functions @@ -331,7 +335,6 @@ namespace embree template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); } template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); } - __forceinline vuint8 broadcast(const unsigned int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); } template __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); } template __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); } template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); } @@ -373,3 +376,11 @@ namespace embree return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/vuint8_avx2.h b/common/simd/vuint8_avx2.h index ae243ddfb1..959143724b 100644 --- a/common/simd/vuint8_avx2.h +++ b/common/simd/vuint8_avx2.h @@ -1,8 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#define vboolf vboolf_impl +#define vboold vboold_impl +#define vint vint_impl +#define vuint vuint_impl +#define vllong vllong_impl +#define vfloat vfloat_impl +#define vdouble vdouble_impl + namespace embree { /* 8-wide AVX integer type */ @@ -371,14 +379,13 @@ namespace embree template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); } template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); } - __forceinline vuint8 broadcast(const unsigned int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); } - template __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); } template __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); } template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); } __forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); } +#if !defined(__aarch64__) __forceinline vuint8 permute(const vuint8& v, const __m256i& index) { return _mm256_permutevar8x32_epi32(v, index); } @@ -395,6 +402,7 @@ namespace embree return _mm256_alignr_epi8(a, b, 4*i); #endif } +#endif // !defined(__aarch64__) //////////////////////////////////////////////////////////////////////////////// /// Reductions @@ -422,8 +430,6 @@ namespace embree //__forceinline size_t select_min(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); } //__forceinline size_t select_max(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); } - __forceinline vuint8 assign(const vuint4& a) { return _mm256_castsi128_si256(a); } - //////////////////////////////////////////////////////////////////////////////// /// Output Operators //////////////////////////////////////////////////////////////////////////////// @@ -432,3 +438,11 @@ namespace embree return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">"; } } + +#undef vboolf +#undef vboold +#undef vint +#undef vuint +#undef vllong +#undef vfloat +#undef vdouble diff --git a/common/simd/wasm/emulation.h b/common/simd/wasm/emulation.h new file mode 100644 index 0000000000..778ab4ae6a --- /dev/null +++ b/common/simd/wasm/emulation.h @@ -0,0 +1,13 @@ +// Copyright 2009-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +// According to https://emscripten.org/docs/porting/simd.html, _MM_SET_EXCEPTION_MASK and +// _mm_setcsr are unavailable in WebAssembly. + +#define _MM_SET_EXCEPTION_MASK(x) + +__forceinline void _mm_setcsr(unsigned int) +{ +} diff --git a/common/sys/CMakeLists.txt b/common/sys/CMakeLists.txt index a1c35787a3..ce44b14ea7 100644 --- a/common/sys/CMakeLists.txt +++ b/common/sys/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(CMAKE_THREAD_PREFER_PTHREAD TRUE) @@ -23,7 +23,7 @@ SET_PROPERTY(TARGET sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") TARGET_LINK_LIBRARIES(sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS sys EXPORT sys-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT sys-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT sys-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git a/common/sys/alloc.cpp b/common/sys/alloc.cpp index 4e8928242e..1bc30fe9a5 100644 --- a/common/sys/alloc.cpp +++ b/common/sys/alloc.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "alloc.h" diff --git a/common/sys/alloc.h b/common/sys/alloc.h index 5898ecda70..4fa474ec1d 100644 --- a/common/sys/alloc.h +++ b/common/sys/alloc.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/array.h b/common/sys/array.h index 6f6f98eac8..e96939b63d 100644 --- a/common/sys/array.h +++ b/common/sys/array.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -59,8 +59,8 @@ namespace embree /********************** Iterators ****************************/ - __forceinline T* begin() const { return items; }; - __forceinline T* end () const { return items+M; }; + __forceinline T* begin() const { return (T*)items; }; + __forceinline T* end () const { return (T*)items+M; }; /********************** Capacity ****************************/ @@ -101,8 +101,8 @@ namespace embree __forceinline T& at(size_t i) { assert(i < M); return items[i]; } __forceinline const T& at(size_t i) const { assert(i < M); return items[i]; } - __forceinline T& front() const { assert(M > 0); return items[0]; }; - __forceinline T& back () const { assert(M > 0); return items[M-1]; }; + __forceinline T& front() { assert(M > 0); return items[0]; }; + __forceinline T& back () { assert(M > 0); return items[M-1]; }; __forceinline T* data() { return items; }; __forceinline const T* data() const { return items; }; @@ -139,7 +139,7 @@ namespace embree __forceinline Ty& operator[](const unsigned i) { assert(i=0 && i #endif +#if defined(__ARM_NEON) +#include "../simd/arm/emulation.h" +#else #include +#if defined(__EMSCRIPTEN__) +#include "../simd/wasm/emulation.h" +#endif +#endif #if defined(__BMI__) && defined(__GNUC__) && !defined(__INTEL_COMPILER) #if !defined(_tzcnt_u32) @@ -20,17 +27,25 @@ #endif #endif -#if defined(__LZCNT__) +#if defined(__aarch64__) #if !defined(_lzcnt_u32) - #define _lzcnt_u32 __lzcnt32 + #define _lzcnt_u32 __builtin_clz #endif - #if !defined(_lzcnt_u64) - #define _lzcnt_u64 __lzcnt64 +#else + #if defined(__LZCNT__) + #if !defined(_lzcnt_u32) + #define _lzcnt_u32 __lzcnt32 + #endif + #if !defined(_lzcnt_u64) + #define _lzcnt_u64 __lzcnt64 + #endif #endif #endif #if defined(__WIN32__) -# define NOMINMAX +# if !defined(NOMINMAX) +# define NOMINMAX +# endif # include #endif @@ -59,7 +74,7 @@ namespace embree } __forceinline int bsf(int v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _tzcnt_u32(v); #else unsigned long r = 0; _BitScanForward(&r,v); return r; @@ -67,7 +82,7 @@ namespace embree } __forceinline unsigned bsf(unsigned v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _tzcnt_u32(v); #else unsigned long r = 0; _BitScanForward(&r,v); return r; @@ -108,7 +123,7 @@ namespace embree #endif __forceinline int bsr(int v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return 31 - _lzcnt_u32(v); #else unsigned long r = 0; _BitScanReverse(&r,v); return r; @@ -116,7 +131,7 @@ namespace embree } __forceinline unsigned bsr(unsigned v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return 31 - _lzcnt_u32(v); #else unsigned long r = 0; _BitScanReverse(&r,v); return r; @@ -135,7 +150,7 @@ namespace embree __forceinline int lzcnt(const int x) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _lzcnt_u32(x); #else if (unlikely(x == 0)) return 32; @@ -201,52 +216,82 @@ namespace embree : "0" (op1), "2" (op2)); } -#else - +#elif defined(__X86_ASM__) + __forceinline void __cpuid(int out[4], int op) { - asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op)); +#if defined(__ARM_NEON) + if (op == 0) { // Get CPU name + out[0] = 0x41524d20; + out[1] = 0x41524d20; + out[2] = 0x41524d20; + out[3] = 0x41524d20; + } +#else + asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op)); +#endif } - + +#if !defined(__ARM_NEON) __forceinline void __cpuid_count(int out[4], int op1, int op2) { asm volatile ("cpuid" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(op1), "c"(op2)); } - #endif - + +#endif + __forceinline uint64_t read_tsc() { +#if defined(__X86_ASM__) uint32_t high,low; asm volatile ("rdtsc" : "=d"(high), "=a"(low)); return (((uint64_t)high) << 32) + (uint64_t)low; +#else + /* Not supported yet, meaning measuring traversal cost per pixel does not work. */ + return 0; +#endif } __forceinline int bsf(int v) { -#if defined(__AVX2__) - return _tzcnt_u32(v); +#if defined(__ARM_NEON) + return __builtin_ctz(v); #else +#if defined(__AVX2__) + return _tzcnt_u32(v); +#elif defined(__X86_ASM__) int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r; +#else + return __builtin_ctz(v); +#endif #endif } -#if defined(__X86_64__) +#if defined(__64BIT__) __forceinline unsigned bsf(unsigned v) { -#if defined(__AVX2__) - return _tzcnt_u32(v); +#if defined(__ARM_NEON) + return __builtin_ctz(v); #else +#if defined(__AVX2__) + return _tzcnt_u32(v); +#elif defined(__X86_ASM__) unsigned r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r; +#else + return __builtin_ctz(v); +#endif #endif } #endif __forceinline size_t bsf(size_t v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) #if defined(__X86_64__) return _tzcnt_u64(v); #else return _tzcnt_u32(v); #endif -#else +#elif defined(__X86_ASM__) size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r; +#else + return __builtin_ctzl(v); #endif } @@ -257,7 +302,7 @@ namespace embree return i; } -#if defined(__X86_64__) +#if defined(__64BIT__) __forceinline unsigned int bscf(unsigned int& v) { unsigned int i = bsf(v); @@ -274,38 +319,44 @@ namespace embree } __forceinline int bsr(int v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return 31 - _lzcnt_u32(v); -#else +#elif defined(__X86_ASM__) int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r; +#else + return __builtin_clz(v) ^ 31; #endif } -#if defined(__X86_64__) +#if defined(__64BIT__) || defined(__EMSCRIPTEN__) __forceinline unsigned bsr(unsigned v) { #if defined(__AVX2__) return 31 - _lzcnt_u32(v); -#else +#elif defined(__X86_ASM__) unsigned r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r; +#else + return __builtin_clz(v) ^ 31; #endif } #endif __forceinline size_t bsr(size_t v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) #if defined(__X86_64__) return 63 - _lzcnt_u64(v); #else return 31 - _lzcnt_u32(v); #endif -#else +#elif defined(__X86_ASM__) size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r; +#else + return (sizeof(v) * 8 - 1) - __builtin_clzl(v); #endif } __forceinline int lzcnt(const int x) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) return _lzcnt_u32(x); #else if (unlikely(x == 0)) return 32; @@ -314,43 +365,67 @@ namespace embree } __forceinline size_t blsr(size_t v) { -#if defined(__AVX2__) -#if defined(__INTEL_COMPILER) +#if defined(__AVX2__) && !defined(__aarch64__) + #if defined(__INTEL_COMPILER) return _blsr_u64(v); + #else + #if defined(__X86_64__) + return __blsr_u64(v); + #else + return __blsr_u32(v); + #endif + #endif #else -#if defined(__X86_64__) - return __blsr_u64(v); -#else - return __blsr_u32(v); -#endif -#endif -#else - return v & (v-1); + return v & (v-1); #endif } __forceinline int btc(int v, int i) { +#if defined(__X86_ASM__) int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r; +#else + return (v ^ (1 << i)); +#endif } __forceinline int bts(int v, int i) { +#if defined(__X86_ASM__) int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; +#else + return (v | (1 << i)); +#endif } __forceinline int btr(int v, int i) { +#if defined(__X86_ASM__) int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; +#else + return (v & ~(1 << i)); +#endif } __forceinline size_t btc(size_t v, size_t i) { +#if defined(__X86_ASM__) size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r; +#else + return (v ^ (1 << i)); +#endif } __forceinline size_t bts(size_t v, size_t i) { +#if defined(__X86_ASM__) size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; +#else + return (v | (1 << i)); +#endif } __forceinline size_t btr(size_t v, size_t i) { +#if defined(__X86_ASM__) size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; +#else + return (v & ~(1 << i)); +#endif } __forceinline int32_t atomic_cmpxchg(int32_t volatile* value, int32_t comparand, const int32_t input) { @@ -384,8 +459,8 @@ namespace embree #endif #endif -#if defined(__SSE4_2__) - +#if defined(__SSE4_2__) || defined(__ARM_NEON) + __forceinline int popcnt(int in) { return _mm_popcnt_u32(in); } @@ -394,7 +469,7 @@ namespace embree return _mm_popcnt_u32(in); } -#if defined(__X86_64__) +#if defined(__64BIT__) __forceinline size_t popcnt(size_t in) { return _mm_popcnt_u64(in); } @@ -402,6 +477,7 @@ namespace embree #endif +#if defined(__X86_ASM__) __forceinline uint64_t rdtsc() { int dummy[4]; @@ -410,6 +486,7 @@ namespace embree __cpuid(dummy,0); return clock; } +#endif __forceinline void pause_cpu(const size_t N = 8) { @@ -430,14 +507,14 @@ namespace embree #endif } - __forceinline void prefetchL1EX(const void* ptr) { - prefetchEX(ptr); + __forceinline void prefetchL1EX(const void* ptr) { + prefetchEX(ptr); } - - __forceinline void prefetchL2EX(const void* ptr) { - prefetchEX(ptr); + + __forceinline void prefetchL2EX(const void* ptr) { + prefetchEX(ptr); } -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(__aarch64__) __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); } __forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); } #if defined(__X86_64__) diff --git a/common/sys/library.cpp b/common/sys/library.cpp index e448b195d1..fc983dffd5 100644 --- a/common/sys/library.cpp +++ b/common/sys/library.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "library.h" @@ -27,7 +27,7 @@ namespace embree /* returns address of a symbol from the library */ void* getSymbol(lib_t lib, const std::string& sym) { - return GetProcAddress(HMODULE(lib),sym.c_str()); + return (void*)GetProcAddress(HMODULE(lib),sym.c_str()); } /* closes the shared library */ diff --git a/common/sys/library.h b/common/sys/library.h index c2164e9fbe..67e14d2420 100644 --- a/common/sys/library.h +++ b/common/sys/library.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/mutex.cpp b/common/sys/mutex.cpp index 57ef360981..8212deaa49 100644 --- a/common/sys/mutex.cpp +++ b/common/sys/mutex.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "mutex.h" @@ -36,6 +36,7 @@ namespace embree MAYBE_UNUSED bool ok = pthread_mutex_destroy((pthread_mutex_t*)mutex) == 0; assert(ok); delete (pthread_mutex_t*)mutex; + mutex = nullptr; } void MutexSys::lock() diff --git a/common/sys/mutex.h b/common/sys/mutex.h index 1164210f23..4cb3626d92 100644 --- a/common/sys/mutex.h +++ b/common/sys/mutex.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/platform.h b/common/sys/platform.h index 96f9aab016..be3ec36436 100644 --- a/common/sys/platform.h +++ b/common/sys/platform.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -23,9 +23,17 @@ /// detect platform //////////////////////////////////////////////////////////////////////////////// -/* detect 32 or 64 platform */ +/* detect 32 or 64 Intel platform */ #if defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) #define __X86_64__ +#define __X86_ASM__ +#elif defined(__i386__) || defined(_M_IX86) +#define __X86_ASM__ +#endif + +/* detect 64 bit platform */ +#if defined(__X86_64__) || defined(__aarch64__) +#define __64BIT__ #endif /* detect Linux platform */ @@ -84,14 +92,19 @@ //////////////////////////////////////////////////////////////////////////////// #ifdef __WIN32__ -#define dll_export __declspec(dllexport) -#define dll_import __declspec(dllimport) +# if defined(EMBREE_STATIC_LIB) +# define dll_export +# define dll_import +# else +# define dll_export __declspec(dllexport) +# define dll_import __declspec(dllimport) +# endif #else -#define dll_export __attribute__ ((visibility ("default"))) -#define dll_import +# define dll_export __attribute__ ((visibility ("default"))) +# define dll_import #endif -#ifdef __WIN32__ +#if defined(__WIN32__) && !defined(__MINGW32__) #if !defined(__noinline) #define __noinline __declspec(noinline) #endif @@ -141,6 +154,7 @@ #define DELETED = delete #endif +#if !defined(likely) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #define likely(expr) (expr) #define unlikely(expr) (expr) @@ -148,6 +162,7 @@ #define likely(expr) __builtin_expect((bool)(expr),true ) #define unlikely(expr) __builtin_expect((bool)(expr),false) #endif +#endif //////////////////////////////////////////////////////////////////////////////// /// Error handling and debugging @@ -186,7 +201,7 @@ namespace embree { /* windows does not have ssize_t */ #if defined(__WIN32__) -#if defined(__X86_64__) +#if defined(__64BIT__) typedef int64_t ssize_t; #else typedef int32_t ssize_t; @@ -228,6 +243,7 @@ __forceinline std::string toString(long long value) { #pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning) //#pragma warning(disable:4267) // '=' : conversion from 'size_t' to 'unsigned long', possible loss of data #pragma warning(disable:4244) // 'argument' : conversion from 'ssize_t' to 'unsigned int', possible loss of data +#pragma warning(disable:4267) // conversion from 'size_t' to 'const int', possible loss of data //#pragma warning(disable:4355) // 'this' : used in base member initializer list //#pragma warning(disable:391 ) // '<=' : signed / unsigned mismatch //#pragma warning(disable:4018) // '<' : signed / unsigned mismatch diff --git a/common/sys/ref.h b/common/sys/ref.h index 24648e6234..c2b56c1908 100644 --- a/common/sys/ref.h +++ b/common/sys/ref.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/regression.cpp b/common/sys/regression.cpp index d95ff8dfe0..45315b1105 100644 --- a/common/sys/regression.cpp +++ b/common/sys/regression.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "regression.h" diff --git a/common/sys/regression.h b/common/sys/regression.h index 632f8d92cf..bb0bb94006 100644 --- a/common/sys/regression.h +++ b/common/sys/regression.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/string.cpp b/common/sys/string.cpp index 931244383e..f42fdc8536 100644 --- a/common/sys/string.cpp +++ b/common/sys/string.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "string.h" diff --git a/common/sys/string.h b/common/sys/string.h index 2e9b0f88c3..820076b21c 100644 --- a/common/sys/string.h +++ b/common/sys/string.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/sysinfo.cpp b/common/sys/sysinfo.cpp index 403f9986d5..c98f61fa53 100644 --- a/common/sys/sysinfo.cpp +++ b/common/sys/sysinfo.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "sysinfo.h" @@ -21,29 +21,33 @@ namespace embree std::string getPlatformName() { -#if defined(__LINUX__) && !defined(__X86_64__) +#if defined(__ANDROID__) && !defined(__64BIT__) + return "Android (32bit)"; +#elif defined(__ANDROID__) && defined(__64BIT__) + return "Android (64bit)"; +#elif defined(__LINUX__) && !defined(__64BIT__) return "Linux (32bit)"; -#elif defined(__LINUX__) && defined(__X86_64__) +#elif defined(__LINUX__) && defined(__64BIT__) return "Linux (64bit)"; -#elif defined(__FREEBSD__) && !defined(__X86_64__) +#elif defined(__FREEBSD__) && !defined(__64BIT__) return "FreeBSD (32bit)"; -#elif defined(__FREEBSD__) && defined(__X86_64__) +#elif defined(__FREEBSD__) && defined(__64BIT__) return "FreeBSD (64bit)"; -#elif defined(__CYGWIN__) && !defined(__X86_64__) +#elif defined(__CYGWIN__) && !defined(__64BIT__) return "Cygwin (32bit)"; -#elif defined(__CYGWIN__) && defined(__X86_64__) +#elif defined(__CYGWIN__) && defined(__64BIT__) return "Cygwin (64bit)"; -#elif defined(__WIN32__) && !defined(__X86_64__) +#elif defined(__WIN32__) && !defined(__64BIT__) return "Windows (32bit)"; -#elif defined(__WIN32__) && defined(__X86_64__) +#elif defined(__WIN32__) && defined(__64BIT__) return "Windows (64bit)"; -#elif defined(__MACOSX__) && !defined(__X86_64__) +#elif defined(__MACOSX__) && !defined(__64BIT__) return "Mac OS X (32bit)"; -#elif defined(__MACOSX__) && defined(__X86_64__) +#elif defined(__MACOSX__) && defined(__64BIT__) return "Mac OS X (64bit)"; -#elif defined(__UNIX__) && !defined(__X86_64__) +#elif defined(__UNIX__) && !defined(__64BIT__) return "Unix (32bit)"; -#elif defined(__UNIX__) && defined(__X86_64__) +#elif defined(__UNIX__) && defined(__64BIT__) return "Unix (64bit)"; #else return "Unknown"; @@ -79,6 +83,7 @@ namespace embree std::string getCPUVendor() { +#if defined(__X86_ASM__) int cpuinfo[4]; __cpuid (cpuinfo, 0); int name[4]; @@ -87,51 +92,119 @@ namespace embree name[2] = cpuinfo[2]; name[3] = 0; return (char*)name; +#elif defined(__ARM_NEON) + return "ARM"; +#else + return "Unknown"; +#endif } - CPUModel getCPUModel() + CPU getCPUModel() { +#if defined(__X86_ASM__) if (getCPUVendor() != "GenuineIntel") - return CPU_UNKNOWN; + return CPU::UNKNOWN; int out[4]; __cpuid(out, 0); - if (out[0] < 1) return CPU_UNKNOWN; + if (out[0] < 1) return CPU::UNKNOWN; __cpuid(out, 1); - int family = ((out[0] >> 8) & 0x0F) + ((out[0] >> 20) & 0xFF); - int model = ((out[0] >> 4) & 0x0F) | ((out[0] >> 12) & 0xF0); - if (family != 6) return CPU_UNKNOWN; // earlier than P6 - if (model == 0x0E) return CPU_CORE1; // Core 1 - if (model == 0x0F) return CPU_CORE2; // Core 2, 65 nm - if (model == 0x16) return CPU_CORE2; // Core 2, 65 nm Celeron - if (model == 0x17) return CPU_CORE2; // Core 2, 45 nm - if (model == 0x1A) return CPU_CORE_NEHALEM; // Core i7, Nehalem - if (model == 0x1E) return CPU_CORE_NEHALEM; // Core i7 - if (model == 0x1F) return CPU_CORE_NEHALEM; // Core i7 - if (model == 0x2C) return CPU_CORE_NEHALEM; // Core i7, Xeon - if (model == 0x2E) return CPU_CORE_NEHALEM; // Core i7, Xeon - if (model == 0x2A) return CPU_CORE_SANDYBRIDGE; // Core i7, SandyBridge - if (model == 0x2D) return CPU_CORE_SANDYBRIDGE; // Core i7, SandyBridge - if (model == 0x45) return CPU_HASWELL; // Haswell - if (model == 0x3C) return CPU_HASWELL; // Haswell - if (model == 0x55) return CPU_SKYLAKE_SERVER; // Skylake server based CPUs - return CPU_UNKNOWN; + + /* please see CPUID documentation for these formulas */ + uint32_t family_ID = (out[0] >> 8) & 0x0F; + uint32_t extended_family_ID = (out[0] >> 20) & 0xFF; + + uint32_t model_ID = (out[0] >> 4) & 0x0F; + uint32_t extended_model_ID = (out[0] >> 16) & 0x0F; + + uint32_t DisplayFamily = family_ID; + if (family_ID == 0x0F) + DisplayFamily += extended_family_ID; + + uint32_t DisplayModel = model_ID; + if (family_ID == 0x06 || family_ID == 0x0F) + DisplayModel += extended_model_ID << 4; + + uint32_t DisplayFamily_DisplayModel = (DisplayFamily << 8) + (DisplayModel << 0); + + // Data from Intel® 64 and IA-32 Architectures, Volume 4, Chapter 2, Table 2-1 (CPUID Signature Values of DisplayFamily_DisplayModel) + if (DisplayFamily_DisplayModel == 0x067D) return CPU::CORE_ICE_LAKE; + if (DisplayFamily_DisplayModel == 0x067E) return CPU::CORE_ICE_LAKE; + if (DisplayFamily_DisplayModel == 0x068C) return CPU::CORE_TIGER_LAKE; + if (DisplayFamily_DisplayModel == 0x06A5) return CPU::CORE_COMET_LAKE; + if (DisplayFamily_DisplayModel == 0x06A6) return CPU::CORE_COMET_LAKE; + if (DisplayFamily_DisplayModel == 0x0666) return CPU::CORE_CANNON_LAKE; + if (DisplayFamily_DisplayModel == 0x068E) return CPU::CORE_KABY_LAKE; + if (DisplayFamily_DisplayModel == 0x069E) return CPU::CORE_KABY_LAKE; + if (DisplayFamily_DisplayModel == 0x066A) return CPU::XEON_ICE_LAKE; + if (DisplayFamily_DisplayModel == 0x066C) return CPU::XEON_ICE_LAKE; + if (DisplayFamily_DisplayModel == 0x0655) return CPU::XEON_SKY_LAKE; + if (DisplayFamily_DisplayModel == 0x064E) return CPU::CORE_SKY_LAKE; + if (DisplayFamily_DisplayModel == 0x065E) return CPU::CORE_SKY_LAKE; + if (DisplayFamily_DisplayModel == 0x0656) return CPU::XEON_BROADWELL; + if (DisplayFamily_DisplayModel == 0x064F) return CPU::XEON_BROADWELL; + if (DisplayFamily_DisplayModel == 0x0647) return CPU::CORE_BROADWELL; + if (DisplayFamily_DisplayModel == 0x063D) return CPU::CORE_BROADWELL; + if (DisplayFamily_DisplayModel == 0x063F) return CPU::XEON_HASWELL; + if (DisplayFamily_DisplayModel == 0x063C) return CPU::CORE_HASWELL; + if (DisplayFamily_DisplayModel == 0x0645) return CPU::CORE_HASWELL; + if (DisplayFamily_DisplayModel == 0x0646) return CPU::CORE_HASWELL; + if (DisplayFamily_DisplayModel == 0x063E) return CPU::XEON_IVY_BRIDGE; + if (DisplayFamily_DisplayModel == 0x063A) return CPU::CORE_IVY_BRIDGE; + if (DisplayFamily_DisplayModel == 0x062D) return CPU::SANDY_BRIDGE; + if (DisplayFamily_DisplayModel == 0x062F) return CPU::SANDY_BRIDGE; + if (DisplayFamily_DisplayModel == 0x062A) return CPU::SANDY_BRIDGE; + if (DisplayFamily_DisplayModel == 0x062E) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x0625) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x062C) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x061E) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x061F) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x061A) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x061D) return CPU::NEHALEM; + if (DisplayFamily_DisplayModel == 0x0617) return CPU::CORE2; + if (DisplayFamily_DisplayModel == 0x060F) return CPU::CORE2; + if (DisplayFamily_DisplayModel == 0x060E) return CPU::CORE1; + + if (DisplayFamily_DisplayModel == 0x0685) return CPU::XEON_PHI_KNIGHTS_MILL; + if (DisplayFamily_DisplayModel == 0x0657) return CPU::XEON_PHI_KNIGHTS_LANDING; + +#elif defined(__ARM_NEON) + return CPU::ARM; +#endif + + return CPU::UNKNOWN; } - std::string stringOfCPUModel(CPUModel model) + std::string stringOfCPUModel(CPU model) { switch (model) { - case CPU_CORE1 : return "Core1"; - case CPU_CORE2 : return "Core2"; - case CPU_CORE_NEHALEM : return "Nehalem"; - case CPU_CORE_SANDYBRIDGE: return "SandyBridge"; - case CPU_HASWELL : return "Haswell"; - case CPU_KNIGHTS_LANDING : return "Knights Landing"; - case CPU_SKYLAKE_SERVER : return "Skylake Server"; - default : return "Unknown CPU"; + case CPU::XEON_ICE_LAKE : return "Xeon Ice Lake"; + case CPU::CORE_ICE_LAKE : return "Core Ice Lake"; + case CPU::CORE_TIGER_LAKE : return "Core Tiger Lake"; + case CPU::CORE_COMET_LAKE : return "Core Comet Lake"; + case CPU::CORE_CANNON_LAKE : return "Core Cannon Lake"; + case CPU::CORE_KABY_LAKE : return "Core Kaby Lake"; + case CPU::XEON_SKY_LAKE : return "Xeon Sky Lake"; + case CPU::CORE_SKY_LAKE : return "Core Sky Lake"; + case CPU::XEON_PHI_KNIGHTS_MILL : return "Xeon Phi Knights Mill"; + case CPU::XEON_PHI_KNIGHTS_LANDING: return "Xeon Phi Knights Landing"; + case CPU::XEON_BROADWELL : return "Xeon Broadwell"; + case CPU::CORE_BROADWELL : return "Core Broadwell"; + case CPU::XEON_HASWELL : return "Xeon Haswell"; + case CPU::CORE_HASWELL : return "Core Haswell"; + case CPU::XEON_IVY_BRIDGE : return "Xeon Ivy Bridge"; + case CPU::CORE_IVY_BRIDGE : return "Core Ivy Bridge"; + case CPU::SANDY_BRIDGE : return "Sandy Bridge"; + case CPU::NEHALEM : return "Nehalem"; + case CPU::CORE2 : return "Core2"; + case CPU::CORE1 : return "Core"; + case CPU::ARM : return "ARM"; + case CPU::UNKNOWN : return "Unknown CPU"; } + return "Unknown CPU (error)"; } +#if defined(__X86_ASM__) /* constants to access destination registers of CPUID instruction */ static const int EAX = 0; static const int EBX = 1; @@ -174,10 +247,12 @@ namespace embree /* cpuid[eax=7,ecx=0].ecx */ static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions) +#endif +#if defined(__X86_ASM__) __noinline int64_t get_xcr0() { -#if defined (__WIN32__) +#if defined (__WIN32__) && !defined (__MINGW32__) && defined(_XCR_XFEATURE_ENABLED_MASK) int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32 xcr0 = _xgetbv(0); return xcr0; @@ -187,9 +262,11 @@ namespace embree return xcr0; #endif } +#endif int getCPUFeatures() { +#if defined(__X86_ASM__) /* cache CPU features access */ static int cpu_features = 0; if (cpu_features) @@ -242,7 +319,7 @@ namespace embree if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42; if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT; - if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX | CPU_FEATURE_PSEUDO_HIFREQ256BIT; + if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX; if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C; if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND; if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2; @@ -261,10 +338,29 @@ namespace embree if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL; if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI; - if (getCPUModel() == CPU_SKYLAKE_SERVER) - cpu_features &= ~CPU_FEATURE_PSEUDO_HIFREQ256BIT; + return cpu_features; +#elif defined(__ARM_NEON) || defined(__EMSCRIPTEN__) + + int cpu_features = CPU_FEATURE_NEON|CPU_FEATURE_SSE|CPU_FEATURE_SSE2; + cpu_features |= CPU_FEATURE_SSE3|CPU_FEATURE_SSSE3|CPU_FEATURE_SSE42; + cpu_features |= CPU_FEATURE_XMM_ENABLED; + cpu_features |= CPU_FEATURE_YMM_ENABLED; + cpu_features |= CPU_FEATURE_SSE41 | CPU_FEATURE_RDRAND | CPU_FEATURE_F16C; + cpu_features |= CPU_FEATURE_POPCNT; + cpu_features |= CPU_FEATURE_AVX; + cpu_features |= CPU_FEATURE_AVX2; + cpu_features |= CPU_FEATURE_FMA3; + cpu_features |= CPU_FEATURE_LZCNT; + cpu_features |= CPU_FEATURE_BMI1; + cpu_features |= CPU_FEATURE_BMI2; + cpu_features |= CPU_FEATURE_NEON_2X; return cpu_features; + +#else + /* Unknown CPU. */ + return 0; +#endif } std::string stringOfCPUFeatures(int features) @@ -297,6 +393,8 @@ namespace embree if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL "; if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA "; if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI "; + if (features & CPU_FEATURE_NEON) str += "NEON "; + if (features & CPU_FEATURE_NEON_2X) str += "2xNEON "; return str; } @@ -310,8 +408,10 @@ namespace embree if (isa == SSE42) return "SSE4.2"; if (isa == AVX) return "AVX"; if (isa == AVX2) return "AVX2"; - if (isa == AVX512KNL) return "AVX512KNL"; - if (isa == AVX512SKX) return "AVX512SKX"; + if (isa == AVX512) return "AVX512"; + + if (isa == NEON) return "NEON"; + if (isa == NEON_2X) return "2xNEON"; return "UNKNOWN"; } @@ -331,8 +431,10 @@ namespace embree if (hasISA(features,AVX)) v += "AVX "; if (hasISA(features,AVXI)) v += "AVXI "; if (hasISA(features,AVX2)) v += "AVX2 "; - if (hasISA(features,AVX512KNL)) v += "AVX512KNL "; - if (hasISA(features,AVX512SKX)) v += "AVX512SKX "; + if (hasISA(features,AVX512)) v += "AVX512 "; + + if (hasISA(features,NEON)) v += "NEON "; + if (hasISA(features,NEON_2X)) v += "2xNEON "; return v; } } @@ -536,6 +638,10 @@ namespace embree #include #include +#if defined(__EMSCRIPTEN__) +#include +#endif + namespace embree { unsigned int getNumberOfLogicalThreads() @@ -543,9 +649,25 @@ namespace embree static int nThreads = -1; if (nThreads != -1) return nThreads; -#if defined(__MACOSX__) +#if defined(__MACOSX__) || defined(__ANDROID__) nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container assert(nThreads); +#elif defined(__EMSCRIPTEN__) + // WebAssembly supports pthreads, but not pthread_getaffinity_np. Get the number of logical + // threads from the browser or Node.js using JavaScript. + nThreads = MAIN_THREAD_EM_ASM_INT({ + const isBrowser = typeof window !== 'undefined'; + const isNode = typeof process !== 'undefined' && process.versions != null && + process.versions.node != null; + if (isBrowser) { + // Return 1 if the browser does not expose hardwareConcurrency. + return window.navigator.hardwareConcurrency || 1; + } else if (isNode) { + return require('os').cpus().length; + } else { + return 1; + } + }); #else cpu_set_t set; if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0) diff --git a/common/sys/sysinfo.h b/common/sys/sysinfo.h index 4f2c27cd29..cefd39a0f6 100644 --- a/common/sys/sysinfo.h +++ b/common/sys/sysinfo.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -16,13 +16,9 @@ /* define isa namespace and ISA bitvector */ #if defined (__AVX512VL__) -# define isa avx512skx -# define ISA AVX512SKX -# define ISA_STR "AVX512SKX" -#elif defined (__AVX512F__) -# define isa avx512knl -# define ISA AVX512KNL -# define ISA_STR "AVX512KNL" +# define isa avx512 +# define ISA AVX512 +# define ISA_STR "AVX512" #elif defined (__AVX2__) # define isa avx2 # define ISA AVX2 @@ -59,23 +55,43 @@ # define isa sse # define ISA SSE # define ISA_STR "SSE" -#else +#elif defined(__ARM_NEON) +// NOTE(LTE): Use sse2 for `isa` for the compatibility at the moment. +#define isa sse2 +#define ISA NEON +#define ISA_STR "NEON" +#else #error Unknown ISA #endif namespace embree { - enum CPUModel { - CPU_UNKNOWN, - CPU_CORE1, - CPU_CORE2, - CPU_CORE_NEHALEM, - CPU_CORE_SANDYBRIDGE, - CPU_HASWELL, - CPU_KNIGHTS_LANDING, - CPU_SKYLAKE_SERVER + enum class CPU + { + XEON_ICE_LAKE, + CORE_ICE_LAKE, + CORE_TIGER_LAKE, + CORE_COMET_LAKE, + CORE_CANNON_LAKE, + CORE_KABY_LAKE, + XEON_SKY_LAKE, + CORE_SKY_LAKE, + XEON_PHI_KNIGHTS_MILL, + XEON_PHI_KNIGHTS_LANDING, + XEON_BROADWELL, + CORE_BROADWELL, + XEON_HASWELL, + CORE_HASWELL, + XEON_IVY_BRIDGE, + CORE_IVY_BRIDGE, + SANDY_BRIDGE, + NEHALEM, + CORE2, + CORE1, + ARM, + UNKNOWN, }; - + /*! get the full path to the running executable */ std::string getExecutableFileName(); @@ -89,10 +105,10 @@ namespace embree std::string getCPUVendor(); /*! get microprocessor model */ - CPUModel getCPUModel(); + CPU getCPUModel(); /*! converts CPU model into string */ - std::string stringOfCPUModel(CPUModel model); + std::string stringOfCPUModel(CPU model); /*! CPU features */ static const int CPU_FEATURE_SSE = 1 << 0; @@ -122,9 +138,9 @@ namespace embree static const int CPU_FEATURE_XMM_ENABLED = 1 << 25; static const int CPU_FEATURE_YMM_ENABLED = 1 << 26; static const int CPU_FEATURE_ZMM_ENABLED = 1 << 27; - - static const int CPU_FEATURE_PSEUDO_HIFREQ256BIT = 1 << 30; - + static const int CPU_FEATURE_NEON = 1 << 28; + static const int CPU_FEATURE_NEON_2X = 1 << 29; + /*! get CPU features */ int getCPUFeatures(); @@ -144,18 +160,16 @@ namespace embree static const int AVX = SSE42 | CPU_FEATURE_AVX | CPU_FEATURE_YMM_ENABLED; static const int AVXI = AVX | CPU_FEATURE_F16C | CPU_FEATURE_RDRAND; static const int AVX2 = AVXI | CPU_FEATURE_AVX2 | CPU_FEATURE_FMA3 | CPU_FEATURE_BMI1 | CPU_FEATURE_BMI2 | CPU_FEATURE_LZCNT; - static const int AVX512KNL = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512PF | CPU_FEATURE_AVX512ER | CPU_FEATURE_AVX512CD | CPU_FEATURE_ZMM_ENABLED; - static const int AVX512SKX = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512DQ | CPU_FEATURE_AVX512CD | CPU_FEATURE_AVX512BW | CPU_FEATURE_AVX512VL | CPU_FEATURE_ZMM_ENABLED; - - static const int AVX_FAST = AVX | CPU_FEATURE_PSEUDO_HIFREQ256BIT; - static const int AVX2_FAST = AVX2 | CPU_FEATURE_PSEUDO_HIFREQ256BIT; + static const int AVX512 = AVX2 | CPU_FEATURE_AVX512F | CPU_FEATURE_AVX512DQ | CPU_FEATURE_AVX512CD | CPU_FEATURE_AVX512BW | CPU_FEATURE_AVX512VL | CPU_FEATURE_ZMM_ENABLED; + static const int NEON = CPU_FEATURE_NEON | CPU_FEATURE_SSE | CPU_FEATURE_SSE2; + static const int NEON_2X = CPU_FEATURE_NEON_2X | AVX2; /*! converts ISA bitvector into a string */ std::string stringOfISA(int features); /*! return the number of logical threads of the system */ unsigned int getNumberOfLogicalThreads(); - + /*! returns the size of the terminal window in characters */ int getTerminalWidth(); diff --git a/common/sys/thread.cpp b/common/sys/thread.cpp index c034c9fb05..2a13ab775f 100644 --- a/common/sys/thread.cpp +++ b/common/sys/thread.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "thread.h" @@ -6,7 +6,14 @@ #include "string.h" #include +#if defined(__ARM_NEON) +#include "../simd/arm/emulation.h" +#else #include +#if defined(__EMSCRIPTEN__) +#include "../simd/wasm/emulation.h" +#endif +#endif #if defined(PTHREADS_WIN32) #pragma comment (lib, "pthreadVC.lib") @@ -154,7 +161,7 @@ namespace embree /// Linux Platform //////////////////////////////////////////////////////////////////////////////// -#if defined(__LINUX__) +#if defined(__LINUX__) && !defined(__ANDROID__) #include #include @@ -213,6 +220,8 @@ namespace embree /* find correct thread to affinitize to */ cpu_set_t set; + CPU_ZERO(&set); + if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0) { for (int i=0, j=0; i= 0) { cpu_set_t cset; CPU_ZERO(&cset); threadID = mapThreadID(threadID); CPU_SET(threadID, &cset); - if (pthread_setaffinity_np(*tid, sizeof(cset), &cset)) - WARNING("pthread_setaffinity_np failed to set affinity to thread "+std::to_string(threadID)); // on purpose only a warning + pthread_setaffinity_np(*tid, sizeof(cset), &cset); } #elif defined(__FreeBSD__) if (threadID >= 0) { cpuset_t cset; CPU_ZERO(&cset); CPU_SET(threadID, &cset); - if (pthread_setaffinity_np(*tid, sizeof(cset), &cset)) - WARNING("pthread_setaffinity_np failed"); // on purpose only a warning + pthread_setaffinity_np(*tid, sizeof(cset), &cset); + } +#elif defined(__ANDROID__) + if (threadID >= 0) { + cpu_set_t cset; + CPU_ZERO(&cset); + CPU_SET(threadID, &cset); + sched_setaffinity(pthread_gettid_np(*tid), sizeof(cset), &cset); } #endif @@ -385,8 +436,12 @@ namespace embree /*! destroy a hardware thread by its handle */ void destroyThread(thread_t tid) { +#if defined(__ANDROID__) + FATAL("Can't destroy threads on Android."); // pthread_cancel not implemented. +#else pthread_cancel(*(pthread_t*)tid); delete (pthread_t*)tid; +#endif } /*! creates thread local storage */ diff --git a/common/sys/thread.h b/common/sys/thread.h index 5261a985ee..92a10d5c5d 100644 --- a/common/sys/thread.h +++ b/common/sys/thread.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/sys/vector.h b/common/sys/vector.h index e41794de7c..f832626789 100644 --- a/common/sys/vector.h +++ b/common/sys/vector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/tasking/CMakeLists.txt b/common/tasking/CMakeLists.txt index 71ef296129..2aeb73698a 100644 --- a/common/tasking/CMakeLists.txt +++ b/common/tasking/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (TASKING_INTERNAL) @@ -8,18 +8,50 @@ ELSEIF (TASKING_TBB) # Find TBB ############################################################## if (NOT ${EMBREE_TBB_ROOT} STREQUAL "") + set(TBB_FIND_PACKAGE_OPTION "NO_DEFAULT_PATH") set(TBB_ROOT ${EMBREE_TBB_ROOT}) + list(APPEND CMAKE_PREFIX_PATH ${EMBREE_TBB_ROOT}) endif() - FIND_PACKAGE(TBB REQUIRED tbb) - ############################################################## - # Create tasking target and link against TBB. Also set include directory - # information on tasking target to provide the "algorithms" object library - # with the TBB header files - ############################################################## ADD_LIBRARY(tasking STATIC taskschedulertbb.cpp) - TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) - TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC "${TBB_INCLUDE_DIRS}") + + if (TARGET TBB::${EMBREE_TBB_COMPONENT}) + message("-- TBB: reuse existing TBB::${TBB_COMPONENT} target") + TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) + else() + # Try getting TBB via config first + find_package(TBB 2021 COMPONENTS ${EMBREE_TBB_COMPONENT} CONFIG ${TBB_FIND_PACKAGE_OPTION}) + if (TBB_FOUND) + TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) + message("-- Found TBB: ${TBB_VERSION} at ${TBB_DIR} via TBBConfig.cmake") + else() + # If not found try getting older TBB via module (FindTBB.cmake) + unset(TBB_DIR CACHE) + find_package(TBB 4.1 REQUIRED ${EMBREE_TBB_COMPONENT}) + if (TBB_FOUND) + TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) + TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC "${TBB_INCLUDE_DIRS}") + endif() + if (NOT TBB_FOUND) + message("-- Not found TBB") + endif() + endif() + endif() + + IF(WIN32) + GET_TARGET_PROPERTY(DLL_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_RELEASE) + GET_TARGET_PROPERTY(DLL_PATH_DEBUG TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_DEBUG) + SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) + SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) + ENDIF() + + ############################################################### + ## Create tasking target and link against TBB. Also set include directory + ## information on tasking target to provide the "algorithms" object library + ## with the TBB header files + ############################################################### + #TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) + #TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC "${TBB_INCLUDE_DIRS}") include(installTBB) @@ -32,6 +64,6 @@ SET_PROPERTY(TARGET tasking PROPERTY FOLDER common) SET_PROPERTY(TARGET tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS tasking EXPORT tasking-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT tasking-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git a/common/tasking/taskscheduler.h b/common/tasking/taskscheduler.h index 298d09255b..8f3dd87689 100644 --- a/common/tasking/taskscheduler.h +++ b/common/tasking/taskscheduler.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/tasking/taskschedulerinternal.cpp b/common/tasking/taskschedulerinternal.cpp index 2152e92f44..dca835a716 100644 --- a/common/tasking/taskschedulerinternal.cpp +++ b/common/tasking/taskschedulerinternal.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "taskschedulerinternal.h" diff --git a/common/tasking/taskschedulerinternal.h b/common/tasking/taskschedulerinternal.h index ef4d65f6fd..61a0e57c5b 100644 --- a/common/tasking/taskschedulerinternal.h +++ b/common/tasking/taskschedulerinternal.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -137,7 +137,7 @@ namespace embree /* allocate new task on right side of stack */ size_t oldStackPtr = stackPtr; TaskFunction* func = new (alloc(sizeof(ClosureTaskFunction))) ClosureTaskFunction(closure); - new (&tasks[right]) Task(func,thread.task,oldStackPtr,size); + new (&(tasks[right.load()])) Task(func,thread.task,oldStackPtr,size); right++; /* also move left pointer */ diff --git a/common/tasking/taskschedulerppl.cpp b/common/tasking/taskschedulerppl.cpp index 8a16da912a..b039a8db19 100644 --- a/common/tasking/taskschedulerppl.cpp +++ b/common/tasking/taskschedulerppl.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "taskschedulerppl.h" diff --git a/common/tasking/taskschedulerppl.h b/common/tasking/taskschedulerppl.h index 776f98cdac..cbc2ecdbb8 100644 --- a/common/tasking/taskschedulerppl.h +++ b/common/tasking/taskschedulerppl.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/common/tasking/taskschedulertbb.cpp b/common/tasking/taskschedulertbb.cpp index 1633fd6b73..23ee355a3c 100644 --- a/common/tasking/taskschedulertbb.cpp +++ b/common/tasking/taskschedulertbb.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "taskschedulertbb.h" diff --git a/common/tasking/taskschedulertbb.h b/common/tasking/taskschedulertbb.h index 98dba26871..042ba7bc4c 100644 --- a/common/tasking/taskschedulertbb.h +++ b/common/tasking/taskschedulertbb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,7 +11,7 @@ #include "../sys/condition.h" #include "../sys/ref.h" -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(NOMINMAX) # define NOMINMAX #endif diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000000..c982b014d2 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,25 @@ +## Copyright 2009-2021 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.11) + +execute_process(COMMAND git config --get remote.origin.url + RESULT_VARIABLE result + OUTPUT_VARIABLE intelstyle_url) +if (result) + return() +endif() + +string(REGEX REPLACE "\n$" "" intelstyle_url "${intelstyle_url}") +string(REPLACE "embree" "intelstyle" intelstyle_url "${intelstyle_url}") + +message(STATUS "Fetch intelstyle repository ${intelstyle_url}") +include(FetchContent) +FetchContent_Declare(IntelStyle + GIT_REPOSITORY ${intelstyle_url} + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/intelstyle") + +FetchContent_GetProperties(IntelStyle) +if(NOT IntelStyle_POPULATED) + FetchContent_Populate(IntelStyle) +endif() diff --git a/doc/Makefile b/doc/Makefile index e23a60b39d..8ec59c3de0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,3 +1,6 @@ +## Copyright 2009-2021 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + images_jpg := $(addprefix images/, $(addsuffix .jpg, displacement_geometry instanced_geometry pathtracer dynamic_scene subdivision_geometry user_geometry hair_geometry intersection_filter triangle_geometry viewer viewer_stream interpolation motion_blur_geometry curve_geometry voronoi closest_point multi_level_instancing point_geometry grid_geometry quaternion_motion_blur collide)) images_png := $(addprefix images/, $(addsuffix .png, quad_uv triangle_uv half_edges)) images_pdf := $(addprefix images/, $(addsuffix .pdf, quad_uv triangle_uv half_edges)) @@ -5,14 +8,15 @@ images_pdf := $(addprefix images/, $(addsuffix .pdf, quad_uv triangle_uv half_ed webpages := $(addprefix www/, $(addsuffix .html, index api tutorials downloads renderer related legal)) webimages := $(addprefix www/, $(images_jpg)) docfiles := $(addprefix doc/, README.md CHANGELOG.md readme.pdf) - +spec := embree-spec.rst man_src := $(wildcard src/api/*.md) manfiles := $(patsubst src/api/%.md,man/man3/%.3embree3,$(man_src)) -all: www images man doc +all: www images man doc spec www: $(webpages) $(webimages) doc: $(docfiles) man: $(manfiles) +spec: $(spec) images: $(images_jpg) $(images_png) $(images_pdf) .PHONY: all www doc images @@ -71,7 +75,7 @@ markdown2web = $(PANDOC) --email-obfuscation=none -f markdown $(filter-out tmp/w #markdown2web = $(PANDOC) $(filter-out tmp/webtemplate.html,$+) --template tmp/webtemplate -V select_$(basename $(@F)) -o $@ -s --mathjax=https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML -$(webpages): tmp/links_web.md tmp/images_local_png.md tmp/webtemplate.html +$(spec) $(webpages): tmp/links_web.md tmp/images_local_png.md tmp/webtemplate.html www/%.html: $(markdown2web) @@ -88,6 +92,11 @@ www/api.html: tmp/api.md $(PANDOC) $(filter-out tmp/webtemplate.html,$+) --filter src/IncludeFilter.py -t markdown | $(convertbsp) > tmp/api_webinc.md $(PANDOC) --email-obfuscation=none -f markdown --template tmp/webtemplate tmp/api_webinc.md tmp/links_web.md tmp/images_local_png.md --indented-code-classes=cpp -V select_$(basename $(@F)) -o $@ +embree-spec.rst: tmp/spec.md + $(PANDOC) $(filter-out tmp/webtemplate.html,$+) --filter src/IncludeFilter.py -t markdown | $(convertbsp) > tmp/spec_webinc.md + $(PANDOC) --email-obfuscation=none -f markdown tmp/spec_webinc.md tmp/links_web.md tmp/images_local_png.md --indented-code-classes=cpp -V select_$(basename $(@F)) --to rst -o embree-spec.rst + + www/images/%.jpg: images/%.jpg cp $< $@ @@ -174,4 +183,4 @@ man/man3/%.3embree3: src/api/%.md ######################################################################## clean: - rm -rf doc tmp man www + rm -rf doc tmp man www embree-spec.rst diff --git a/doc/images/curve_geometry.jpg b/doc/images/curve_geometry.jpg index 5201f43bb2..b121d21221 100644 Binary files a/doc/images/curve_geometry.jpg and b/doc/images/curve_geometry.jpg differ diff --git a/doc/images/quad_uv.pdf b/doc/images/quad_uv.pdf index 1f6d18b070..94899bfb43 100644 Binary files a/doc/images/quad_uv.pdf and b/doc/images/quad_uv.pdf differ diff --git a/doc/images/triangle_uv.png b/doc/images/triangle_uv.png index 7b158f0a0f..5065895c37 100644 Binary files a/doc/images/triangle_uv.png and b/doc/images/triangle_uv.png differ diff --git a/doc/intelstyle b/doc/intelstyle deleted file mode 160000 index f5def28047..0000000000 --- a/doc/intelstyle +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f5def280473f3ca799dcef8cdb011cf020d3e21b diff --git a/doc/preamble.tex b/doc/preamble.tex index 7fb79909b3..4732b28f18 100644 --- a/doc/preamble.tex +++ b/doc/preamble.tex @@ -1,3 +1,6 @@ +%% Copyright 2009-2021 Intel Corporation +%% SPDX-License-Identifier: Apache-2.0 + \usepackage{polyglossia} \setdefaultlanguage{english} @@ -26,6 +29,7 @@ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts }{} +\PassOptionsToPackage{hyphens}{url} % url is loaded by hyperref \usepackage{tabu,booktabs} \tabulinesep=3pt @@ -35,39 +39,41 @@ \newcommand{\VerbBar}{|} \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} +% fix issue with linebreaks and letter spacing in non-cpp blocks +\DefineVerbatimEnvironment{verbatim}{Verbatim}{} % Add ',fontsize=\small' for more characters per line \newenvironment{Shaded}{}{} -\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} -\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} -\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} -\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} -\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} -\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{{#1}}} -\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} -\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} -\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} -\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} -\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{{#1}}} -\newcommand{\ImportTok}[1]{{#1}} -\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} -\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{{#1}}}} -\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} -\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} -\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} -\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} -\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{{#1}}} -\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} -\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{{#1}}} -\newcommand{\BuiltInTok}[1]{{#1}} -\newcommand{\ExtensionTok}[1]{{#1}} -\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{{#1}}} -\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{{#1}}} -\newcommand{\RegionMarkerTok}[1]{{#1}} -\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} -\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} -\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} -\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} -\newcommand{\NormalTok}[1]{{#1}} +\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} +\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} +\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} +\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} +\newcommand{\ImportTok}[1]{#1} +\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} +\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} +\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} +\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} +\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} +\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} +\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} +\newcommand{\BuiltInTok}[1]{#1} +\newcommand{\ExtensionTok}[1]{#1} +\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} +\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} +\newcommand{\RegionMarkerTok}[1]{#1} +\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} +\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} +\newcommand{\NormalTok}[1]{#1} \providecommand{\tightlist}{% \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} @@ -75,6 +81,7 @@ \makeatletter \def\maxwidth{\ifdim\Gin@nat@width>\columnwidth\columnwidth\else\Gin@nat@width\fi} \def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} +\def\fps@figure{htp}% set default figure placement \makeatother % Scale images if necessary, so that they will not overflow the page % margins by default, and it is still possible to overwrite the defaults @@ -139,6 +146,9 @@ \catcode`\¾\active \def¾{\nicefrac34} +\catcode`\∙\active +\def∙{\ensuremath{\cdot}} + % fix overfull hboxes, somehow required for xelatex % pdflatex and lualatex is fine without \emergencystretch=0.5em diff --git a/doc/src/IncludeFilter.py b/doc/src/IncludeFilter.py index f27cd22127..f86217c7ec 100755 --- a/doc/src/IncludeFilter.py +++ b/doc/src/IncludeFilter.py @@ -1,6 +1,6 @@ -#!/usr/bin/python +#!/usr/bin/env python3 -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 import sys diff --git a/doc/src/api-ref.md b/doc/src/api-ref.md new file mode 100644 index 0000000000..40792f7bf2 --- /dev/null +++ b/doc/src/api-ref.md @@ -0,0 +1,558 @@ +## rtcNewDevice +``` {include=src/api/rtcNewDevice.md} +``` +\pagebreak + +## rtcRetainDevice +``` {include=src/api/rtcRetainDevice.md} +``` +\pagebreak + +## rtcReleaseDevice +``` {include=src/api/rtcReleaseDevice.md} +``` +\pagebreak + +## rtcGetDeviceProperty +``` {include=src/api/rtcGetDeviceProperty.md} +``` +\pagebreak + +## rtcGetDeviceError +``` {include=src/api/rtcGetDeviceError.md} +``` +\pagebreak + +## rtcSetDeviceErrorFunction +``` {include=src/api/rtcSetDeviceErrorFunction.md} +``` +\pagebreak + +## rtcSetDeviceMemoryMonitorFunction +``` {include=src/api/rtcSetDeviceMemoryMonitorFunction.md} +``` +\pagebreak + +## rtcNewScene +``` {include=src/api/rtcNewScene.md} +``` +\pagebreak + +## rtcGetSceneDevice +``` {include=src/api/rtcGetSceneDevice.md} +``` +\pagebreak + +## rtcRetainScene +``` {include=src/api/rtcRetainScene.md} +``` +\pagebreak + +## rtcReleaseScene +``` {include=src/api/rtcReleaseScene.md} +``` +\pagebreak + +## rtcAttachGeometry +``` {include=src/api/rtcAttachGeometry.md} +``` +\pagebreak + +## rtcAttachGeometryByID +``` {include=src/api/rtcAttachGeometryByID.md} +``` +\pagebreak + +## rtcDetachGeometry +``` {include=src/api/rtcDetachGeometry.md} +``` +\pagebreak + +## rtcGetGeometry +``` {include=src/api/rtcGetGeometry.md} +``` +\pagebreak + +## rtcGetGeometryThreadSafe +``` {include=src/api/rtcGetGeometryThreadSafe.md} +``` +\pagebreak + +## rtcCommitScene +``` {include=src/api/rtcCommitScene.md} +``` +\pagebreak + +## rtcJoinCommitScene +``` {include=src/api/rtcJoinCommitScene.md} +``` +\pagebreak + +## rtcSetSceneProgressMonitorFunction +``` {include=src/api/rtcSetSceneProgressMonitorFunction.md} +``` +\pagebreak + +## rtcSetSceneBuildQuality +``` {include=src/api/rtcSetSceneBuildQuality.md} +``` +\pagebreak + +## rtcSetSceneFlags +``` {include=src/api/rtcSetSceneFlags.md} +``` +\pagebreak + +## rtcGetSceneFlags +``` {include=src/api/rtcGetSceneFlags.md} +``` +\pagebreak + + +## rtcGetSceneBounds +``` {include=src/api/rtcGetSceneBounds.md} +``` +\pagebreak + +## rtcGetSceneLinearBounds +``` {include=src/api/rtcGetSceneLinearBounds.md} +``` +\pagebreak + +## rtcNewGeometry +``` {include=src/api/rtcNewGeometry.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_TRIANGLE +``` {include=src/api/RTC_GEOMETRY_TYPE_TRIANGLE.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_QUAD +``` {include=src/api/RTC_GEOMETRY_TYPE_QUAD.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_GRID +``` {include=src/api/RTC_GEOMETRY_TYPE_GRID.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_SUBDIVISION +``` {include=src/api/RTC_GEOMETRY_TYPE_SUBDIVISION.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_CURVE +``` {include=src/api/RTC_GEOMETRY_TYPE_CURVE.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_POINT +``` {include=src/api/RTC_GEOMETRY_TYPE_POINT.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_USER +``` {include=src/api/RTC_GEOMETRY_TYPE_USER.md} +``` +\pagebreak + +## RTC_GEOMETRY_TYPE_INSTANCE +``` {include=src/api/RTC_GEOMETRY_TYPE_INSTANCE.md} +``` +\pagebreak + +## RTCCurveFlags +``` {include=src/api/RTCCurveFlags.md} +``` +\pagebreak + +## rtcRetainGeometry +``` {include=src/api/rtcRetainGeometry.md} +``` +\pagebreak + +## rtcReleaseGeometry +``` {include=src/api/rtcReleaseGeometry.md} +``` +\pagebreak + +## rtcCommitGeometry +``` {include=src/api/rtcCommitGeometry.md} +``` +\pagebreak + +## rtcEnableGeometry +``` {include=src/api/rtcEnableGeometry.md} +``` +\pagebreak + +## rtcDisableGeometry +``` {include=src/api/rtcDisableGeometry.md} +``` +\pagebreak + +## rtcSetGeometryTimeStepCount +``` {include=src/api/rtcSetGeometryTimeStepCount.md} +``` +\pagebreak + +## rtcSetGeometryTimeRange +``` {include=src/api/rtcSetGeometryTimeRange.md} +``` +\pagebreak + +## rtcSetGeometryVertexAttributeCount +``` {include=src/api/rtcSetGeometryVertexAttributeCount.md} +``` +\pagebreak + +## rtcSetGeometryMask +``` {include=src/api/rtcSetGeometryMask.md} +``` +\pagebreak + +## rtcSetGeometryBuildQuality +``` {include=src/api/rtcSetGeometryBuildQuality.md} +``` +\pagebreak + +## rtcSetGeometryBuffer +``` {include=src/api/rtcSetGeometryBuffer.md} +``` +\pagebreak + +## rtcSetSharedGeometryBuffer +``` {include=src/api/rtcSetSharedGeometryBuffer.md} +``` +\pagebreak + +## rtcSetNewGeometryBuffer +``` {include=src/api/rtcSetNewGeometryBuffer.md} +``` +\pagebreak + +## RTCFormat +``` {include=src/api/RTCFormat.md} +``` +\pagebreak + +## RTCBufferType +``` {include=src/api/RTCBufferType.md} +``` +\pagebreak + +## rtcGetGeometryBufferData +``` {include=src/api/rtcGetGeometryBufferData.md} +``` +\pagebreak + +## rtcUpdateGeometryBuffer +``` {include=src/api/rtcUpdateGeometryBuffer.md} +``` +\pagebreak + +## rtcSetGeometryIntersectFilterFunction +``` {include=src/api/rtcSetGeometryIntersectFilterFunction.md} +``` +\pagebreak + +## rtcSetGeometryOccludedFilterFunction +``` {include=src/api/rtcSetGeometryOccludedFilterFunction.md} +``` +\pagebreak + +## rtcFilterIntersection +``` {include=src/api/rtcFilterIntersection.md} +``` +\pagebreak + +## rtcFilterOcclusion +``` {include=src/api/rtcFilterOcclusion.md} +``` +\pagebreak + +## rtcSetGeometryUserData +``` {include=src/api/rtcSetGeometryUserData.md} +``` +\pagebreak + +## rtcGetGeometryUserData +``` {include=src/api/rtcGetGeometryUserData.md} +``` +\pagebreak + + +## rtcSetGeometryUserPrimitiveCount +``` {include=src/api/rtcSetGeometryUserPrimitiveCount.md} +``` +\pagebreak + +## rtcSetGeometryBoundsFunction +``` {include=src/api/rtcSetGeometryBoundsFunction.md} +``` +\pagebreak + +## rtcSetGeometryIntersectFunction +``` {include=src/api/rtcSetGeometryIntersectFunction.md} +``` +\pagebreak + +## rtcSetGeometryOccludedFunction +``` {include=src/api/rtcSetGeometryOccludedFunction.md} +``` +\pagebreak + +## rtcSetGeometryPointQueryFunction +``` {include=src/api/rtcSetGeometryPointQueryFunction.md} +``` +\pagebreak + +## rtcSetGeometryInstancedScene +``` {include=src/api/rtcSetGeometryInstancedScene.md} +``` +\pagebreak + +## rtcSetGeometryTransform +``` {include=src/api/rtcSetGeometryTransform.md} +``` +\pagebreak + +## rtcSetGeometryTransformQuaternion +``` {include=src/api/rtcSetGeometryTransformQuaternion.md} +``` +\pagebreak + +## rtcGetGeometryTransform +``` {include=src/api/rtcGetGeometryTransform.md} +``` +\pagebreak + + +## rtcSetGeometryTessellationRate +``` {include=src/api/rtcSetGeometryTessellationRate.md} +``` +\pagebreak + +## rtcSetGeometryTopologyCount +``` {include=src/api/rtcSetGeometryTopologyCount.md} +``` +\pagebreak + +## rtcSetGeometrySubdivisionMode +``` {include=src/api/rtcSetGeometrySubdivisionMode.md} +``` +\pagebreak + +## rtcSetGeometryVertexAttributeTopology +``` {include=src/api/rtcSetGeometryVertexAttributeTopology.md} +``` +\pagebreak + +## rtcSetGeometryDisplacementFunction +``` {include=src/api/rtcSetGeometryDisplacementFunction.md} +``` +\pagebreak + +## rtcGetGeometryFirstHalfEdge +``` {include=src/api/rtcGetGeometryFirstHalfEdge.md} +``` +\pagebreak + +## rtcGetGeometryFace +``` {include=src/api/rtcGetGeometryFace.md} +``` +\pagebreak + +## rtcGetGeometryNextHalfEdge +``` {include=src/api/rtcGetGeometryNextHalfEdge.md} +``` +\pagebreak + +## rtcGetGeometryPreviousHalfEdge +``` {include=src/api/rtcGetGeometryPreviousHalfEdge.md} +``` +\pagebreak + +## rtcGetGeometryOppositeHalfEdge +``` {include=src/api/rtcGetGeometryOppositeHalfEdge.md} +``` +\pagebreak + +## rtcInterpolate +``` {include=src/api/rtcInterpolate.md} +``` +\pagebreak + +## rtcInterpolateN +``` {include=src/api/rtcInterpolateN.md} +``` +\pagebreak + + +## rtcNewBuffer +``` {include=src/api/rtcNewBuffer.md} +``` +\pagebreak + +## rtcNewSharedBuffer +``` {include=src/api/rtcNewSharedBuffer.md} +``` +\pagebreak + +## rtcRetainBuffer +``` {include=src/api/rtcRetainBuffer.md} +``` +\pagebreak + +## rtcReleaseBuffer +``` {include=src/api/rtcReleaseBuffer.md} +``` +\pagebreak + +## rtcGetBufferData +``` {include=src/api/rtcGetBufferData.md} +``` +\pagebreak + +## RTCRay +``` {include=src/api/RTCRay.md} +``` +\pagebreak + +## RTCHit +``` {include=src/api/RTCHit.md} +``` +\pagebreak + +## RTCRayHit +``` {include=src/api/RTCRayHit.md} +``` +\pagebreak + +## RTCRayN +``` {include=src/api/RTCRayN.md} +``` +\pagebreak + +## RTCHitN +``` {include=src/api/RTCHitN.md} +``` +\pagebreak + +## RTCRayHitN +``` {include=src/api/RTCRayHitN.md} +``` +\pagebreak + +## rtcInitIntersectContext +``` {include=src/api/rtcInitIntersectContext.md} +``` +\pagebreak + +## rtcIntersect1 +``` {include=src/api/rtcIntersect1.md} +``` +\pagebreak + +## rtcOccluded1 +``` {include=src/api/rtcOccluded1.md} +``` +\pagebreak + +## rtcIntersect4/8/16 +``` {include=src/api/rtcIntersect4.md} +``` +\pagebreak + +## rtcOccluded4/8/16 +``` {include=src/api/rtcOccluded4.md} +``` +\pagebreak + +## rtcIntersect1M +``` {include=src/api/rtcIntersect1M.md} +``` +\pagebreak + +## rtcOccluded1M +``` {include=src/api/rtcOccluded1M.md} +``` +\pagebreak + +## rtcIntersect1Mp +``` {include=src/api/rtcIntersect1Mp.md} +``` +\pagebreak + +## rtcOccluded1Mp +``` {include=src/api/rtcOccluded1Mp.md} +``` +\pagebreak + +## rtcIntersectNM +``` {include=src/api/rtcIntersectNM.md} +``` +\pagebreak + +## rtcOccludedNM +``` {include=src/api/rtcOccludedNM.md} +``` +\pagebreak + +## rtcIntersectNp +``` {include=src/api/rtcIntersectNp.md} +``` +\pagebreak + +## rtcOccludedNp +``` {include=src/api/rtcOccludedNp.md} +``` +\pagebreak + +## rtcInitPointQueryContext +``` {include=src/api/rtcInitPointQueryContext.md} +``` +\pagebreak + +## rtcPointQuery +``` {include=src/api/rtcPointQuery.md} +``` +\pagebreak + +## rtcCollide +``` {include=src/api/rtcCollide.md} +``` +\pagebreak + +## rtcNewBVH +``` {include=src/api/rtcNewBVH.md} +``` +\pagebreak + +## rtcRetainBVH +``` {include=src/api/rtcRetainBVH.md} +``` +\pagebreak + +## rtcReleaseBVH +``` {include=src/api/rtcReleaseBVH.md} +``` +\pagebreak + +## rtcBuildBVH +``` {include=src/api/rtcBuildBVH.md} +``` +\pagebreak + +## RTCQuaternionDecomposition +``` {include=src/api/RTCQuaternionDecomposition.md} +``` +\pagebreak + +## rtcInitQuaternionDecomposition +``` {include=src/api/rtcInitQuaternionDecomposition.md} +``` +\pagebreak diff --git a/doc/src/api.md b/doc/src/api.md index 6e271c3674..0d2e5eea43 100644 --- a/doc/src/api.md +++ b/doc/src/api.md @@ -1,216 +1,8 @@ Embree API ========== -The Embree API is a low-level C99 ray tracing API which can be used to -construct 3D scenes and perform ray queries of different types inside -these scenes. All API calls carry the prefix `rtc` (or `RTC` for -types) which stands for **r**ay **t**racing **c**ore. - -The API also exists in an ISPC version, which is almost identical but -contains additional functions that operate on ray packets with a size -of the native SIMD width used by ISPC. For simplicity this document -refers to the C99 version of the API functions. For changes when -upgrading from the Embree 2 to the current Embree 3 API see Section -[Upgrading from Embree 2 to Embree 3]. - -The API supports scenes consisting of different geometry types such as -triangle meshes, quad meshes (triangle pairs), grid meshes, flat -curves, round curves, oriented curves, subdivision meshes, instances, -and user-defined geometries. See Section [Scene Object] for more -information. - -Finding the closest hit of a ray segment with the scene -(`rtcIntersect`-type functions), and determining whether any hit -between a ray segment and the scene exists (`rtcOccluded`-type -functions) are both supported. The API supports queries for single -rays, ray packets, and ray streams. See Section [Ray Queries] for -more information. - -The API is designed in an object-oriented manner, e.g. it contains -device objects (`RTCDevice` type), scene objects (`RTCScene` type), -geometry objects (`RTCGeometry` type), buffer objects (`RTCBuffer` -type), and BVH objects (`RTCBVH` type). All objects are reference -counted, and handles can be released by calling the appropriate release -function (e.g. `rtcReleaseDevice`) or retained by incrementing the -reference count (e.g. `rtcRetainDevice`). In general, API calls that -access the same object are not thread-safe, unless specified -differently. However, attaching geometries to the same scene and -performing ray queries in a scene is thread-safe. - -Device Object -------------- - -Embree supports a device concept, which allows different components of -the application to use the Embree API without interfering with each -other. An application typically first creates a device using the -[rtcNewDevice] function. This device can then be used to construct -further objects, such as scenes and geometries. Before the application -exits, it should release all devices by invoking [rtcReleaseDevice]. An -application typically creates only a single device. If required -differently, it should only use a small number of devices at any given -time. - -Each user thread has its own error flag per device. If an error occurs -when invoking an API function, this flag is set to an error code (if -it isn't already set by a previous error). See Section -[rtcGetDeviceError] for information on how to read the error code -and Section [rtcSetDeviceErrorFunction] on how to register a -callback that is invoked for each error encountered. It is recommended -to always set a error callback function, to detect all errors. - -Scene Object ------------- - -A scene is a container for a set of geometries, and contains a spatial -acceleration structure which can be used to perform different types of -ray queries. - -A scene is created using the `rtcNewScene` function call, and released -using the `rtcReleaseScene` function call. To populate a scene with -geometries use the `rtcAttachGeometry` call, and to detach them use the -`rtcDetachGeometry` call. Once all scene geometries are attached, an -`rtcCommitScene` call (or `rtcJoinCommitScene` call) will finish the -scene description and trigger building of internal data structures. -After the scene got committed, it is safe to perform ray queries (see -Section [Ray Queries]) or to query the scene bounding box (see -[rtcGetSceneBounds] and [rtcGetSceneLinearBounds]). - -If scene geometries get modified or attached or detached, the -`rtcCommitScene` call must be invoked before performing any further -ray queries for the scene; otherwise the effect of the ray query is -undefined. The modification of a geometry, committing the scene, and -tracing of rays must always happen sequentially, and never at the same -time. Any API call that sets a property of the scene or geometries -contained in the scene count as scene modification, e.g. including -setting of intersection filter functions. - -Scene flags can be used to configure a scene to use less memory -(`RTC_SCENE_FLAG_COMPACT`), use more robust traversal algorithms -(`RTC_SCENE_FLAG_ROBUST`), and to optimize for dynamic content. See -Section [rtcSetSceneFlags] for more details. - -A build quality can be specified for a scene to balance between -acceleration structure build performance and ray query performance. -See Section [rtcSetSceneBuildQuality] for more details on build -quality. - -Geometry Object ---------------- - -A new geometry is created using the `rtcNewGeometry` function. -Depending on the geometry type, different buffers must be bound (e.g. -using `rtcSetSharedGeometryBuffer`) to set up the geometry data. In -most cases, binding of a vertex and index buffer is required. The -number of primitives and vertices of that geometry is typically -inferred from the size of these bound buffers. - -Changes to the geometry always must be committed using the -`rtcCommitGeometry` call before using the geometry. After committing, -a geometry is not included in any scene. A geometry can be added to -a scene by using the `rtcAttachGeometry` function (to automatically -assign a geometry ID) or using the `rtcAttachGeometryById` function -(to specify the geometry ID manually). A geometry can get attached -to multiple scenes. - -All geometry types support multi-segment motion blur with an arbitrary -number of equidistant time steps (in the range of 2 to 129) inside a -user specified time range. Each geometry can have a different number -of time steps and a different time range. The motion blur geometry is -defined by linearly interpolating the geometries of neighboring time -steps. To construct a motion blur geometry, first the number of time -steps of the geometry must be specified using the -`rtcSetGeometryTimeStepCount` function, and then a vertex buffer for -each time step must be bound, e.g. using the -`rtcSetSharedGeometryBuffer` function. Optionally, a time range -defining the start (and end time) of the first (and last) time step -can be set using the `rtcSetGeometryTimeRange` function. This feature -will also allow geometries to appear and disappear during the camera -shutter time if the time range is a sub range of [0,1]. - -The API supports per-geometry filter callback functions (see -`rtcSetGeometryIntersectFilterFunction` and -`rtcSetGeometryOccludedFilterFunction`) that are invoked for each -intersection found during the `rtcIntersect`-type or -`rtcOccluded`-type calls. The former ones are called geometry -intersection filter functions, the latter ones geometry occlusion -filter functions. These filter functions are designed to be used to -ignore intersections outside of a user-defined silhouette of a -primitive, e.g. to model tree leaves using transparency textures. - -Ray Queries ------------ - -The API supports finding the closest hit of a ray segment with the -scene (`rtcIntersect`-type functions), and determining whether any hit -between a ray segment and the scene exists (`rtcOccluded`-type -functions). - -Supported are single ray queries (`rtcIntersect1` and `rtcOccluded1`) -as well as ray packet queries for ray packets of size 4 -(`rtcIntersect4` and `rtcOccluded4`), ray packets of size 8 -(`rtcIntersect8` and `rtcOccluded8`), and ray packets of size 16 -(`rtcIntersect16` and `rtcOccluded16`). - -Ray streams in a variety of layouts are supported as well, such as -streams of single rays (`rtcIntersect1M` and `rtcOccluded1M`), streams -of pointers to single rays (`rtcIntersect1p` and `rtcOccluded1p`), -streams of ray packets (`rtcIntersectNM` and `rtcOccludedNM`), and -large packet-like streams in structure of pointer layout -(`rtcIntersectNp` and `rtcOccludedNp`). - -See Sections [rtcIntersect1] and [rtcOccluded1] for a detailed -description of how to set up and trace a ray. - -See tutorial [Triangle Geometry] for a complete example of how to -trace single rays and ray packets. Also have a look at the tutorial -[Stream Viewer] for an example of how to trace ray streams. - -Point Queries -------------- - -The API supports traversal of the BVH using a point query object that -specifies a location and a query radius. For all primitives intersecting the -according domain, a user defined callback function is called which allows -queries such as finding the closest point on the surface geometries of the -scene (see Tutorial [Closest Point]) or nearest neighbour queries (see -Tutorial [Voronoi]). - -See Section [rtcPointQuery] for a detailed description of how to set up -point queries. - -Collision Detection -------------------- - -The Embree API also supports collision detection queries between two -scenes consisting only of user geometries. Embree only performs -broadphase collision detection, the narrow phase detection can be -performed through a callback function. - -See Section [rtcCollide] for a detailed description of how to set up collision -detection. - -Seen tutorial [Collision Detection] for a complete example of collsion -detection being used on a simple cloth solver. - - -Miscellaneous -------------- - -A context filter function, which can be set per ray query is supported -(see `rtcInitIntersectContext`). This filter function is designed to -change the semantics of the ray query, e.g. to accumulate opacity for -transparent shadows, count the number of surfaces along a ray, -collect all hits along a ray, etc. - -The internal algorithms to build a BVH are exposed through the `RTCBVH` -object and `rtcBuildBVH` call. This call makes it possible to build a -BVH in a user-specified format over user-specified primitives. See the -documentation of the `rtcBuildBVH` call for more details. - -For getting the most performance out of Embree, see the Section -[Performance Recommendations]. - -\pagebreak +``` {include=src/intro.md} +``` Upgrading from Embree 2 to Embree 3 =================================== @@ -230,7 +22,7 @@ way for CPP files: ./scripts/cpp-patch.py --patch embree2_to_embree3.patch --in infile.cpp --out outfile.cpp -When invoked for ISPC files, add the `--ispc` option: +When invoked for Intel® ISPC files, add the `--ispc` option: ./scripts/cpp-patch.py --ispc --patch embree2_to_embree3.patch --in infile.ispc --out outfile.ispc @@ -478,17 +270,17 @@ Miscellaneous change from the initial size and ordering when entering a filter callback. -* We no longer export ISPC-specific symbols. This has the advantage +* We no longer export Intel® ISPC-specific symbols. This has the advantage that certain linking issues went away, e.g. it is now possible to - link an ISPC application compiled for any combination of ISAs, and + link an Intel® ISPC application compiled for any combination of ISAs, and link this to an Embree library compiled with a different set of ISAs. Previously the ISAs of the application had to be a subset of the ISAs of Embree, and when the user enabled exactly one ISA, they had to do this in Embree and the application. -* We no longer export the ISPC tasking system, which means that the - application has the responsibility to implement the ISPC tasking - system itself. ISPC comes with example code on how to do this. This +* We no longer export the Intel® ISPC tasking system, which means that the + application has the responsibility to implement the Intel® ISPC tasking + system itself. Intel® ISPC comes with example code on how to do this. This change is not performed by the script and must be done manually. * Fixed many naming inconsistencies, and changed names of further API @@ -500,560 +292,8 @@ Miscellaneous Embree API Reference ==================== -## rtcNewDevice -``` {include=src/api/rtcNewDevice.md} -``` -\pagebreak - -## rtcRetainDevice -``` {include=src/api/rtcRetainDevice.md} -``` -\pagebreak - -## rtcReleaseDevice -``` {include=src/api/rtcReleaseDevice.md} -``` -\pagebreak - -## rtcGetDeviceProperty -``` {include=src/api/rtcGetDeviceProperty.md} -``` -\pagebreak - -## rtcGetDeviceError -``` {include=src/api/rtcGetDeviceError.md} -``` -\pagebreak - -## rtcSetDeviceErrorFunction -``` {include=src/api/rtcSetDeviceErrorFunction.md} -``` -\pagebreak - -## rtcSetDeviceMemoryMonitorFunction -``` {include=src/api/rtcSetDeviceMemoryMonitorFunction.md} -``` -\pagebreak - -## rtcNewScene -``` {include=src/api/rtcNewScene.md} -``` -\pagebreak - -## rtcGetSceneDevice -``` {include=src/api/rtcGetSceneDevice.md} -``` -\pagebreak - -## rtcRetainScene -``` {include=src/api/rtcRetainScene.md} -``` -\pagebreak - -## rtcReleaseScene -``` {include=src/api/rtcReleaseScene.md} -``` -\pagebreak - -## rtcAttachGeometry -``` {include=src/api/rtcAttachGeometry.md} -``` -\pagebreak - -## rtcAttachGeometryByID -``` {include=src/api/rtcAttachGeometryByID.md} -``` -\pagebreak - -## rtcDetachGeometry -``` {include=src/api/rtcDetachGeometry.md} -``` -\pagebreak - -## rtcGetGeometry -``` {include=src/api/rtcGetGeometry.md} -``` -\pagebreak - -## rtcCommitScene -``` {include=src/api/rtcCommitScene.md} -``` -\pagebreak - -## rtcJoinCommitScene -``` {include=src/api/rtcJoinCommitScene.md} -``` -\pagebreak - -## rtcSetSceneProgressMonitorFunction -``` {include=src/api/rtcSetSceneProgressMonitorFunction.md} -``` -\pagebreak - -## rtcSetSceneBuildQuality -``` {include=src/api/rtcSetSceneBuildQuality.md} -``` -\pagebreak - -## rtcSetSceneFlags -``` {include=src/api/rtcSetSceneFlags.md} -``` -\pagebreak - -## rtcGetSceneFlags -``` {include=src/api/rtcGetSceneFlags.md} -``` -\pagebreak - - -## rtcGetSceneBounds -``` {include=src/api/rtcGetSceneBounds.md} -``` -\pagebreak - -## rtcGetSceneLinearBounds -``` {include=src/api/rtcGetSceneLinearBounds.md} -``` -\pagebreak - -## rtcNewGeometry -``` {include=src/api/rtcNewGeometry.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_TRIANGLE -``` {include=src/api/RTC_GEOMETRY_TYPE_TRIANGLE.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_QUAD -``` {include=src/api/RTC_GEOMETRY_TYPE_QUAD.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_GRID -``` {include=src/api/RTC_GEOMETRY_TYPE_GRID.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_SUBDIVISION -``` {include=src/api/RTC_GEOMETRY_TYPE_SUBDIVISION.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_CURVE -``` {include=src/api/RTC_GEOMETRY_TYPE_CURVE.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_POINT -``` {include=src/api/RTC_GEOMETRY_TYPE_POINT.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_USER -``` {include=src/api/RTC_GEOMETRY_TYPE_USER.md} -``` -\pagebreak - -## RTC_GEOMETRY_TYPE_INSTANCE -``` {include=src/api/RTC_GEOMETRY_TYPE_INSTANCE.md} -``` -\pagebreak - -## RTCCurveFlags -``` {include=src/api/RTCCurveFlags.md} -``` -\pagebreak - -## rtcRetainGeometry -``` {include=src/api/rtcRetainGeometry.md} -``` -\pagebreak - -## rtcReleaseGeometry -``` {include=src/api/rtcReleaseGeometry.md} -``` -\pagebreak - -## rtcCommitGeometry -``` {include=src/api/rtcCommitGeometry.md} -``` -\pagebreak - -## rtcEnableGeometry -``` {include=src/api/rtcEnableGeometry.md} -``` -\pagebreak - -## rtcDisableGeometry -``` {include=src/api/rtcDisableGeometry.md} -``` -\pagebreak - -## rtcSetGeometryTimeStepCount -``` {include=src/api/rtcSetGeometryTimeStepCount.md} -``` -\pagebreak - -## rtcSetGeometryTimeRange -``` {include=src/api/rtcSetGeometryTimeRange.md} -``` -\pagebreak - -## rtcSetGeometryVertexAttributeCount -``` {include=src/api/rtcSetGeometryVertexAttributeCount.md} -``` -\pagebreak - -## rtcSetGeometryMask -``` {include=src/api/rtcSetGeometryMask.md} -``` -\pagebreak - -## rtcSetGeometryBuildQuality -``` {include=src/api/rtcSetGeometryBuildQuality.md} -``` -\pagebreak - -## rtcSetGeometryBuffer -``` {include=src/api/rtcSetGeometryBuffer.md} -``` -\pagebreak - -## rtcSetSharedGeometryBuffer -``` {include=src/api/rtcSetSharedGeometryBuffer.md} -``` -\pagebreak - -## rtcSetNewGeometryBuffer -``` {include=src/api/rtcSetNewGeometryBuffer.md} -``` -\pagebreak - -## RTCFormat -``` {include=src/api/RTCFormat.md} -``` -\pagebreak - -## RTCBufferType -``` {include=src/api/RTCBufferType.md} -``` -\pagebreak - -## rtcGetGeometryBufferData -``` {include=src/api/rtcGetGeometryBufferData.md} -``` -\pagebreak - -## rtcUpdateGeometryBuffer -``` {include=src/api/rtcUpdateGeometryBuffer.md} -``` -\pagebreak - -## rtcSetGeometryIntersectFilterFunction -``` {include=src/api/rtcSetGeometryIntersectFilterFunction.md} -``` -\pagebreak - -## rtcSetGeometryOccludedFilterFunction -``` {include=src/api/rtcSetGeometryOccludedFilterFunction.md} -``` -\pagebreak - -## rtcFilterIntersection -``` {include=src/api/rtcFilterIntersection.md} +``` {include=src/api-ref.md} ``` -\pagebreak - -## rtcFilterOcclusion -``` {include=src/api/rtcFilterOcclusion.md} -``` -\pagebreak - -## rtcSetGeometryUserData -``` {include=src/api/rtcSetGeometryUserData.md} -``` -\pagebreak - -## rtcGetGeometryUserData -``` {include=src/api/rtcGetGeometryUserData.md} -``` -\pagebreak - - -## rtcSetGeometryUserPrimitiveCount -``` {include=src/api/rtcSetGeometryUserPrimitiveCount.md} -``` -\pagebreak - -## rtcSetGeometryBoundsFunction -``` {include=src/api/rtcSetGeometryBoundsFunction.md} -``` -\pagebreak - -## rtcSetGeometryIntersectFunction -``` {include=src/api/rtcSetGeometryIntersectFunction.md} -``` -\pagebreak - -## rtcSetGeometryOccludedFunction -``` {include=src/api/rtcSetGeometryOccludedFunction.md} -``` -\pagebreak - -## rtcSetGeometryPointQueryFunction -``` {include=src/api/rtcSetGeometryPointQueryFunction.md} -``` -\pagebreak - -## rtcSetGeometryInstancedScene -``` {include=src/api/rtcSetGeometryInstancedScene.md} -``` -\pagebreak - -## rtcSetGeometryTransform -``` {include=src/api/rtcSetGeometryTransform.md} -``` -\pagebreak - -## rtcSetGeometryTransformQuaternion -``` {include=src/api/rtcSetGeometryTransformQuaternion.md} -``` -\pagebreak - -## rtcGetGeometryTransform -``` {include=src/api/rtcGetGeometryTransform.md} -``` -\pagebreak - - -## rtcSetGeometryTessellationRate -``` {include=src/api/rtcSetGeometryTessellationRate.md} -``` -\pagebreak - -## rtcSetGeometryTopologyCount -``` {include=src/api/rtcSetGeometryTopologyCount.md} -``` -\pagebreak - -## rtcSetGeometrySubdivisionMode -``` {include=src/api/rtcSetGeometrySubdivisionMode.md} -``` -\pagebreak - -## rtcSetGeometryVertexAttributeTopology -``` {include=src/api/rtcSetGeometryVertexAttributeTopology.md} -``` -\pagebreak - -## rtcSetGeometryDisplacementFunction -``` {include=src/api/rtcSetGeometryDisplacementFunction.md} -``` -\pagebreak - -## rtcGetGeometryFirstHalfEdge -``` {include=src/api/rtcGetGeometryFirstHalfEdge.md} -``` -\pagebreak - -## rtcGetGeometryFace -``` {include=src/api/rtcGetGeometryFace.md} -``` -\pagebreak - -## rtcGetGeometryNextHalfEdge -``` {include=src/api/rtcGetGeometryNextHalfEdge.md} -``` -\pagebreak - -## rtcGetGeometryPreviousHalfEdge -``` {include=src/api/rtcGetGeometryPreviousHalfEdge.md} -``` -\pagebreak - -## rtcGetGeometryOppositeHalfEdge -``` {include=src/api/rtcGetGeometryOppositeHalfEdge.md} -``` -\pagebreak - -## rtcInterpolate -``` {include=src/api/rtcInterpolate.md} -``` -\pagebreak - -## rtcInterpolateN -``` {include=src/api/rtcInterpolateN.md} -``` -\pagebreak - - -## rtcNewBuffer -``` {include=src/api/rtcNewBuffer.md} -``` -\pagebreak - -## rtcNewSharedBuffer -``` {include=src/api/rtcNewSharedBuffer.md} -``` -\pagebreak - -## rtcRetainBuffer -``` {include=src/api/rtcRetainBuffer.md} -``` -\pagebreak - -## rtcReleaseBuffer -``` {include=src/api/rtcReleaseBuffer.md} -``` -\pagebreak - -## rtcGetBufferData -``` {include=src/api/rtcGetBufferData.md} -``` -\pagebreak - -## RTCRay -``` {include=src/api/RTCRay.md} -``` -\pagebreak - -## RTCHit -``` {include=src/api/RTCHit.md} -``` -\pagebreak - -## RTCRayHit -``` {include=src/api/RTCRayHit.md} -``` -\pagebreak - -## RTCRayN -``` {include=src/api/RTCRayN.md} -``` -\pagebreak - -## RTCHitN -``` {include=src/api/RTCHitN.md} -``` -\pagebreak - -## RTCRayHitN -``` {include=src/api/RTCRayHitN.md} -``` -\pagebreak - -## rtcInitIntersectContext -``` {include=src/api/rtcInitIntersectContext.md} -``` -\pagebreak - -## rtcIntersect1 -``` {include=src/api/rtcIntersect1.md} -``` -\pagebreak - -## rtcOccluded1 -``` {include=src/api/rtcOccluded1.md} -``` -\pagebreak - -## rtcIntersect4/8/16 -``` {include=src/api/rtcIntersect4.md} -``` -\pagebreak - -## rtcOccluded4/8/16 -``` {include=src/api/rtcOccluded4.md} -``` -\pagebreak - -## rtcIntersect1M -``` {include=src/api/rtcIntersect1M.md} -``` -\pagebreak - -## rtcOccluded1M -``` {include=src/api/rtcOccluded1M.md} -``` -\pagebreak - -## rtcIntersect1Mp -``` {include=src/api/rtcIntersect1Mp.md} -``` -\pagebreak - -## rtcOccluded1Mp -``` {include=src/api/rtcOccluded1Mp.md} -``` -\pagebreak - -## rtcIntersectNM -``` {include=src/api/rtcIntersectNM.md} -``` -\pagebreak - -## rtcOccludedNM -``` {include=src/api/rtcOccludedNM.md} -``` -\pagebreak - -## rtcIntersectNp -``` {include=src/api/rtcIntersectNp.md} -``` -\pagebreak - -## rtcOccludedNp -``` {include=src/api/rtcOccludedNp.md} -``` -\pagebreak - -## rtcInitPointQueryContext -``` {include=src/api/rtcInitPointQueryContext.md} -``` -\pagebreak -## rtcPointQuery -``` {include=src/api/rtcPointQuery.md} -``` - -\pagebreak - -## rtcCollide -``` {include=src/api/rtcCollide.md} -``` - -\pagebreak - -## rtcNewBVH -``` {include=src/api/rtcNewBVH.md} -``` -\pagebreak - -## rtcRetainBVH -``` {include=src/api/rtcRetainBVH.md} -``` -\pagebreak - -## rtcReleaseBVH -``` {include=src/api/rtcReleaseBVH.md} -``` -\pagebreak - -## rtcBuildBVH -``` {include=src/api/rtcBuildBVH.md} -``` -\pagebreak - -## RTCQuaternionDecomposition -``` {include=src/api/RTCQuaternionDecomposition.md} -``` -\pagebreak - -## rtcInitQuaternionDecomposition -``` {include=src/api/rtcInitQuaternionDecomposition.md} -``` -\pagebreak Performance Recommendations =========================== diff --git a/doc/src/api/RTCQuaternionDecomposition.md b/doc/src/api/RTCQuaternionDecomposition.md index 64f165f17f..8fb9458d94 100644 --- a/doc/src/api/RTCQuaternionDecomposition.md +++ b/doc/src/api/RTCQuaternionDecomposition.md @@ -49,7 +49,6 @@ $quaternion_r + quaternion_i \ \mathbf{i} + quaternion_j \ \mathbf{i} + quaterni where $\mathbf{i}$, $\mathbf{j}$ $\mathbf{k}$ are the imaginary quaternion units. The passed quaternion will be normalized internally. -\noindent The affine transformation matrix corresponding to a `RTCQuaternionDecomposition` is $TRS$ and a point $p = (p_x, p_y, p_z, 1)^T$ will be transformed as $$p' = T \ R \ S \ p.$$ diff --git a/doc/src/api/RTCRay.md b/doc/src/api/RTCRay.md index 5eebfd8151..3126d3d236 100644 --- a/doc/src/api/RTCRay.md +++ b/doc/src/api/RTCRay.md @@ -35,7 +35,7 @@ and `tfar` members). The ray direction does not have to be normalized, and only the parameter range specified by the `tnear`/`tfar` interval is considered valid. -The ray segment must be in the range $[0, ∞]$, thus ranges that +The ray segment must be in the range $[0, \infty]$, thus ranges that start behind the ray origin are not allowed, but ranges can reach to infinity. For rays inside a ray stream, `tfar` < `tnear` identifies an inactive ray. diff --git a/doc/src/api/RTC_GEOMETRY_TYPE_CURVE.md b/doc/src/api/RTC_GEOMETRY_TYPE_CURVE.md index 06e99f12f1..a2c8ac0fe9 100644 --- a/doc/src/api/RTC_GEOMETRY_TYPE_CURVE.md +++ b/doc/src/api/RTC_GEOMETRY_TYPE_CURVE.md @@ -29,6 +29,9 @@ 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_ROUND_LINEAR_CURVE - capped cone curve geometry with linear basis and spherical ending @@ -57,6 +60,7 @@ rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE); + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE); @@ -76,6 +80,7 @@ created by passing `RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BSPLINE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_HERMITE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_CATMULL_ROM_CURVE`, +`RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE`, @@ -125,14 +130,14 @@ neighbor bits are automatically calculated base on the index buffer segment exists if segment(id+1)-1 == segment(id)). A left neighbor segment is assumed to end at the start vertex of the -current segement, and to start at the previous vertex in the vertex +current segment, and to start at the previous vertex in the vertex buffer. Similarly, the right neighbor segment is assumed to start at the end vertex of the current segment, and to end at the next vertex in the vertex buffer. Only when the left and right bits are properly specified the current segment can properly attach to the left and/or right neighbor, -otherwise the touching area may not get rendererd properly. +otherwise the touching area may not get rendered properly. ##### Bézier Basis @@ -152,8 +157,8 @@ vector). This basis is not interpolating, thus the curve does in general not go through any of the control points directly. 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 make this basis a -good choise to construct continuous multi-segment curves, as memory +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. ##### Hermite Basis @@ -167,7 +172,7 @@ 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 usig the Hermite basis, by calculating a proper tangent +constructed using the Hermite basis, by calculating a proper tangent buffer from the control points. ##### Catmull-Rom Basis @@ -212,7 +217,10 @@ cross product of the normal from the normal spline and tangent of the vertex spline. Note that this construction does not work when the provided normals are parallel to the curve direction. For this reason the provided normals should best be kept as perpendicular to the curve -direction as possible. +direction as possible. We further assume second order derivatives of +the center curve to be zero for this construction, as otherwise very +large curvatures occurring in corner cases, can thicken the constructed +curve significantly. ##### Round Curves @@ -225,7 +233,7 @@ 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 segment are clipped away (if that next segment exists). This way a curve is -closed on both ends and the interiour will render properly as long as +closed on both ends and the interior will render properly as long as only neighboring segments penetrate into a segment. For this to work properly it is important that the flags buffer is properly populated with neighbor information. diff --git a/doc/src/api/RTC_GEOMETRY_TYPE_USER.md b/doc/src/api/RTC_GEOMETRY_TYPE_USER.md index b384435442..d317597aea 100644 --- a/doc/src/api/RTC_GEOMETRY_TYPE_USER.md +++ b/doc/src/api/RTC_GEOMETRY_TYPE_USER.md @@ -45,6 +45,10 @@ Please have a look at the `rtcSetGeometryBoundsFunction`, `rtcSetGeometryIntersectFunction`, and `rtcSetGeometryOccludedFunction` functions on the implementation of the callback functions. +Primitives of a user geometry are ignored during rendering when their +bounds are empty, thus bounds have lower>upper in at least one +dimension. + See tutorial [User Geometry] for an example of how to use the user-defined geometries. diff --git a/doc/src/api/rtcAttachGeometry.md b/doc/src/api/rtcAttachGeometry.md index d230bbdefc..387b148a5d 100644 --- a/doc/src/api/rtcAttachGeometry.md +++ b/doc/src/api/rtcAttachGeometry.md @@ -18,7 +18,7 @@ The `rtcAttachGeometry` function attaches a geometry (`geometry` argument) to a scene (`scene` argument) and assigns a geometry ID to that geometry. All geometries attached to a scene are defined to be -included inside the scene. A geometry can get attached to multiplee scene. +included inside the scene. 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. diff --git a/doc/src/api/rtcBuildBVH.md b/doc/src/api/rtcBuildBVH.md index 4a5079188b..b99ba10512 100644 --- a/doc/src/api/rtcBuildBVH.md +++ b/doc/src/api/rtcBuildBVH.md @@ -144,7 +144,7 @@ performance for dynamic scenes is improved at the cost of higher memory requirements. To spatially split primitives in high quality mode, the builder needs -extra space at the end of the build primitive array to store splitted +extra space at the end of the build primitive array to store split primitives. The total capacity of the build primitive array is passed using the `primitiveArrayCapacity` member, and should be about twice the number of primitives when using spatial splits. diff --git a/doc/src/api/rtcGetDeviceProperty.md b/doc/src/api/rtcGetDeviceProperty.md index 0f456ead32..6a18b2a0bd 100644 --- a/doc/src/api/rtcGetDeviceProperty.md +++ b/doc/src/api/rtcGetDeviceProperty.md @@ -52,8 +52,8 @@ Possible properties to query are: `rtcIntersect16` and `rtcOccluded16` functions preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with `EMBREE_RAY_PACKETS` and - `AVX512SKX` (or `AVX512KNL`) enabled, and if the machine it is - running on supports `AVX512SKX` (or `AVX512KNL`). + `AVX512` enabled, and if the machine it is + running on supports `AVX512`. + `RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED`: Queries whether `rtcIntersect1M`, `rtcIntersect1Mp`, `rtcIntersectNM`, @@ -112,7 +112,7 @@ Possible properties to query are: 1. Intel Threading Building Blocks (TBB) 2. Parallel Patterns Library (PPL) -+ `RTC_DEVICE_PROPERTY_COMMIT_JOIN_SUPPORTED`: Queries whether ++ `RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED`: Queries whether `rtcJoinCommitScene` is supported. This is not the case when Embree is compiled with PPL or older versions of TBB. diff --git a/doc/src/api/rtcGetGeometry.md b/doc/src/api/rtcGetGeometry.md index 6ea4a2986c..5ff8896c88 100644 --- a/doc/src/api/rtcGetGeometry.md +++ b/doc/src/api/rtcGetGeometry.md @@ -17,12 +17,16 @@ The `rtcGetGeometry` function returns the geometry that is bound to the specified geometry ID (`geomID` argument) for the specified scene (`scene` argument). This function just looks up the handle and does *not* increment the reference count. If you want to get ownership of -the handle, you need to additionally call `rtcRetainGeometry`. For this -reason, this function is fast and can be used during rendering. +the handle, you need to additionally call `rtcRetainGeometry`. + +This function is not thread safe and thus can be used during rendering. However, it is generally recommended to store the geometry handle inside the application's geometry representation and look up the geometry handle from that representation directly. +If you need a thread safe version of this function please use +[rtcGetGeometryThreadSafe]. + #### EXIT STATUS On failure `NULL` is returned and an error code is set that can be @@ -30,4 +34,4 @@ queried using `rtcGetDeviceError`. #### SEE ALSO -[rtcAttachGeometry], [rtcAttachGeometryByID] +[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometryThreadSafe] diff --git a/doc/src/api/rtcGetGeometryThreadSafe.md b/doc/src/api/rtcGetGeometryThreadSafe.md new file mode 100644 index 0000000000..c3431554ae --- /dev/null +++ b/doc/src/api/rtcGetGeometryThreadSafe.md @@ -0,0 +1,34 @@ +% rtcGetGeometryThreadSafe(3) | Embree Ray Tracing Kernels 3 + +#### NAME + + rtcGetGeometryThreadSafe - returns the geometry bound to + the specified geometry ID + +#### SYNOPSIS + + #include + + RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID); + +#### DESCRIPTION + +The `rtcGetGeometryThreadSafe` function returns the geometry that is bound to +the specified geometry ID (`geomID` argument) for the specified scene +(`scene` argument). This function just looks up the handle and does +*not* increment the reference count. If you want to get ownership of +the handle, you need to additionally call `rtcRetainGeometry`. + +This function is thread safe and should NOT get used during rendering. +If you need a fast non-thread safe version during rendering please use +the [rtcGetGeometry] function. + + +#### EXIT STATUS + +On failure `NULL` is returned and an error code is set that can be +queried using `rtcGetDeviceError`. + +#### SEE ALSO + +[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometry] diff --git a/doc/src/api/rtcInitPointQueryContext.md b/doc/src/api/rtcInitPointQueryContext.md index 96c40f9279..578d128966 100644 --- a/doc/src/api/rtcInitPointQueryContext.md +++ b/doc/src/api/rtcInitPointQueryContext.md @@ -46,7 +46,7 @@ tutorial [ClosestPoint] for a reference implementation of point queries with user defined instancing). The context is an necessary argument to [rtcPointQuery] and Embree internally -uses the topmost instance tranformation of the stack to transform the point +uses the topmost instance transformation of the stack to transform the point query into instance space. #### EXIT STATUS diff --git a/doc/src/api/rtcIntersect1.md b/doc/src/api/rtcIntersect1.md index 1d6f0015f3..e1c43fc850 100644 --- a/doc/src/api/rtcIntersect1.md +++ b/doc/src/api/rtcIntersect1.md @@ -28,7 +28,7 @@ scene contains motion blur geometries, also the ray time (`time` ray member) must be initialized to a value in the range $[0, 1]$. If ray masks are enabled at compile time, the ray mask (`mask` ray member) must be initialized as well. The ray segment has to be in the -range $[0, ∞]$, thus ranges that start behind the ray origin are not +range $[0, \infty]$, thus ranges that start behind the ray origin are not valid, but ranges can reach to infinity. See Section [RTCRay] for the ray layout description. diff --git a/doc/src/api/rtcNewDevice.md b/doc/src/api/rtcNewDevice.md index 37d3e470cd..b2e25e5e57 100644 --- a/doc/src/api/rtcNewDevice.md +++ b/doc/src/api/rtcNewDevice.md @@ -30,19 +30,6 @@ A configuration string (`config` argument) can be passed to the device construction. This configuration string can be `NULL` to use the default configuration. -When creating the device, Embree reads configurations for the device -from the following locations in order: - -1) `config` string passed to the `rtcNewDevice` function -2) `.embree3` file in the application folder -3) `.embree3` file in the home folder - -Settings performed later overwrite previous settings. This way the -configuration for the application can be changed globally (either -through the `rtcNewDevice` call or through the `.embree3` file in the -application folder), and each user has the option to modify the -configuration to fit their needs. - The following configuration is supported: + `threads=[int]`: Specifies a number of build threads to use. A value @@ -65,10 +52,10 @@ The following configuration is supported: upfront. This can be useful for benchmarking to exclude thread creation time. This option is disabled by default. -+ `isa=[sse2,sse4.2,avx,avx2,avx512knl,avx512skx]`: Use specified ++ `isa=[sse2,sse4.2,avx,avx2,avx512]`: Use specified ISA. By default the ISA is selected automatically. -+ `max_isa=[sse2,sse4.2,avx,avx2,avx512knl,avx512skx]`: Configures the ++ `max_isa=[sse2,sse4.2,avx,avx2,avx512]`: Configures the automated ISA selection to use maximally the specified ISA. + `hugepages=[0/1]`: Enables or disables usage of huge pages. Under @@ -81,28 +68,26 @@ The following configuration is supported: ignored on other platforms. See Section [Huge Page Support] for more details. -+ `ignore_config_files=[0/1]`: When set to 1, configuration files are - ignored. Default is 0. - + `verbose=[0,1,2,3]`: Sets the verbosity of the output. When set to 0, no output is printed by Embree, when set to a higher level more output is printed. By default Embree does not print anything on the console. -+ `frequency_level=[simd128,simd256,simd512]`: Specifies the - frequency level the application want to run on, which can be - either: a) simd128 for apps that do not use AVX instructions, b) - simd256 for apps that use heavy AVX instruction, c) simd512 for - apps that use heavy AVX-512 instructions. When some frequency level - is specified, Embree will avoid doing optimizations that may reduce - the frequency level below the level specified. E.g. if your app - does not use AVX instructions setting "frequency_level=simd128" - will cause some CPUs to run at highest frequency, which may result - in higher application performance. However, this will prevent - Embree from using AVX optimizations to achieve higher ray tracing - performance, thus applications that trace many rays may still - perform better with the default setting of simd256, even though - this reduces frequency on some CPUs. ++ `frequency_level=[simd128,simd256,simd512]`: Specifies the frequency + level the application want to run on, which can be either: + a) simd128 to run at highest frequency + b) simd256 to run at AVX2-heavy frequency level + c) simd512 to run at heavy AVX512 frequency level. + When some frequency level is specified, Embree will avoid doing + optimizations that may reduce the frequency level below the level + specified. E.g. if your app does not use AVX instructions setting + "frequency_level=simd128" will cause some CPUs to run at highest + frequency, which may result in higher application performance if + you do much shading. If you application heavily uses + AVX code, you should best set the frequency level to simd256. + Per default Embree tries to avoid reducing the frequency of the + CPU by setting the simd256 level only when the CPU has no significant + down clocking. Different configuration options should be separated by commas, e.g.: diff --git a/doc/src/api/rtcNewGeometry.md b/doc/src/api/rtcNewGeometry.md index 2fb6596ac9..2028d22f85 100644 --- a/doc/src/api/rtcNewGeometry.md +++ b/doc/src/api/rtcNewGeometry.md @@ -22,6 +22,7 @@ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE, + RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, @@ -58,7 +59,7 @@ bases (`RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_FLAT_BEZIER_CUR `RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE`, `RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE`, `RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE`, `RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE`, -`RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE`, +`RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE`, `RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE`, `RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE` types) grid meshes (`RTC_GEOMETRY_TYPE_GRID`), point geometries (`RTC_GEOMETRY_TYPE_SPHERE_POINT`, `RTC_GEOMETRY_TYPE_DISC_POINT`, diff --git a/doc/src/api/rtcOccluded1.md b/doc/src/api/rtcOccluded1.md index c321e4febf..59adeb6304 100644 --- a/doc/src/api/rtcOccluded1.md +++ b/doc/src/api/rtcOccluded1.md @@ -26,7 +26,7 @@ the scene contains motion blur geometries, also the ray time (`time` ray member) must be initialized to a value in the range $[0, 1]$. If ray masks are enabled at compile time, the ray mask (`mask` ray member) must be initialized as well. The ray segment must be in the range -$[0, ∞]$, thus ranges that start behind the ray origin are not valid, +$[0, \infty]$, thus ranges that start behind the ray origin are not valid, but ranges can reach to infinity. See Section [RTCRay] for the ray layout description. diff --git a/doc/src/api/rtcPointQuery.md b/doc/src/api/rtcPointQuery.md index 3ba6feb095..09ca4a39aa 100644 --- a/doc/src/api/rtcPointQuery.md +++ b/doc/src/api/rtcPointQuery.md @@ -36,7 +36,7 @@ The `rtcPointQuery` function traverses the BVH using a `RTCPointQuery` object intersects the query domain. The user has to initialize the query location (`x`, `y` and `z` member) and -query radius in the range $[0, ∞]$. If the scene contains motion blur +query radius in the range $[0, \infty]$. If the scene contains motion blur geometries, also the query time (`time` member) must be initialized to a value in the range $[0, 1]$. @@ -75,7 +75,7 @@ Point queries can be used with (multilevel)-instancing. However, care has to be taken when the instance transformation contains anisotropic scaling or sheering. In these cases distance computations have to be performed in world space to ensure correctness and the ellipsoidal query domain (in instance -space) will be approximated with its axis aligned bounding box interally. +space) will be approximated with its axis aligned bounding box internally. Therefore, the callback function might be invoked even for primitives in inner BVH nodes that do not intersect the query domain. See [rtcSetGeometryPointQueryFunction] for details. @@ -84,7 +84,7 @@ The point query structure must be aligned to 16 bytes. #### SUPPORTED PRIMITIVES -Currenly, all primitive types are supported by the point query API except of +Currently, all primitive types are supported by the point query API except of points (see [RTC_GEOMETRY_TYPE_POINT]), curves (see [RTC_GEOMETRY_TYPE_CURVE]) and sudivision surfaces (see [RTC_GEOMETRY_SUBDIVISION]). diff --git a/doc/src/api/rtcSetGeometryPointQueryFunction.md b/doc/src/api/rtcSetGeometryPointQueryFunction.md index 4ad8119f53..577bc80eaa 100644 --- a/doc/src/api/rtcSetGeometryPointQueryFunction.md +++ b/doc/src/api/rtcSetGeometryPointQueryFunction.md @@ -87,17 +87,17 @@ transformed into instance space which can be more efficient. If there is no instance transform, the similarity scale is 1. The callback function will potentially be called for primitives outside the -query domain for two resons: First, the callback is invoked for all +query domain for two reasons: First, the callback is invoked for all primitives inside a BVH leaf node since no geometry data of primitives is determined internally and therefore individual primitives are not culled (only their (aggregated) bounding boxes). Second, in case non similarity transformations are used, the resulting ellipsoidal query domain (in instance space) is approximated by its axis aligned bounding box internally and therefore inner nodes that do not intersect the original domain might -intersect the approximative bounding box which results in unneccessary +intersect the approximative bounding box which results in unnecessary callbacks. In any case, the callbacks are conservative, i.e. if a primitive is inside the query domain a callback will be invoked but the reverse is not -neccessarily true. +necessarily true. For efficiency, the radius of the `query` object can be decreased (in world space) inside the callback function to improve culling of geometry during BVH diff --git a/doc/src/api/rtcSetSharedGeometryBuffer.md b/doc/src/api/rtcSetSharedGeometryBuffer.md index 1d37ccd676..af8c7098fa 100644 --- a/doc/src/api/rtcSetSharedGeometryBuffer.md +++ b/doc/src/api/rtcSetSharedGeometryBuffer.md @@ -34,7 +34,7 @@ elements (`byteStride` argument), the format of the buffer elements The start address (`byteOffset` argument) and stride (`byteStride` argument) must be both aligned to 4 bytes; otherwise the -`rtcSetGeometryBuffer` function will fail. +`rtcSetSharedGeometryBuffer` function will fail. ``` {include=src/api/inc/buffer_padding.md} ``` @@ -45,7 +45,7 @@ longer required. Sharing buffers can significantly reduce the memory required by the application, thus we recommend using this feature. When enabling the -`RTC_SCENE_COMPACT` scene flag, the spatial index structures index +`RTC_SCENE_FLAG_COMPACT` scene flag, the spatial index structures index into the vertex buffer, resulting in even higher memory savings. #### EXIT STATUS diff --git a/doc/src/changelog.md b/doc/src/changelog.md index f820fdb548..4aaffd25f2 100644 --- a/doc/src/changelog.md +++ b/doc/src/changelog.md @@ -1,6 +1,74 @@ Version History --------------- +### Embree 3.13.4 +- Using 8-wide BVH and double pumped NEON instructions on Apple M1 gives 8% performance boost. +- Fixed binning related crash in SAH BVH builder. +- Added EMBREE_TBB_COMPONENT cmake option to define the component/library name of Intel® TBB (default: tbb). +- Embree supports now Intel® oneAPI DPC++/C++ Compiler 2022.0.0 + +### Embree 3.13.3 +- Invalid multi segment motion blurred normal oriented curves are properly excluded from BVH build. +- Fixing issue with normal oriented curve construction when center curve curvature is very large. + Due to this change normal oriented curve shape changes slightly. +- Fixed crash caused by disabling a geometry and then detaching it from the scene. +- Bugfix in emulated ray packet intersection when EMBREE_RAY_PACKETS is turned off. +- Bugfix for linear quaternion interpolation fallback. +- Fixed issues with spaces in path to Embree build folder. +- Some fixes to compile Embree in SSE mode using WebAssembly. +- Bugfix for occlusion rays with grids and ray packets. +- We do no longer provide installers for Windows and macOS, please use the ZIP files instead. +- Upgrading to Intel® ISPC 1.17.0 for release build. +- Upgrading to Intel® oneTBB 2021.5.0 for release build. + +### Embree 3.13.2 +- Avoiding spatial split positions that are slightly out of geometry bounds. +- Introduced rtcGetGeometryThreadSafe function, which is a thread safe version of rtcGetGeometry. +- Using more accurate rcp implementation. +- Bugfix to rare corner case of high quality BVH builder. + +### Embree 3.13.1 +- Added support for Intel® ISPC ARM target. +- Releases upgrade to Intel® TBB 2021.3.0 and Intel® ISPC 1.16.1 + +### Embree 3.13.0 +- Added support for Apple M1 CPUs. +- RTC_SUBDIVISION_MODE_NO_BOUNDARY now works properly for non-manifold edges. +- CMake target 'uninstall' is not defined if it already exists. +- Embree no longer reads the .embree3 config files, thus all configuration has + to get passed through the config string to rtcNewDevice. +- Releases upgrade to Intel® TBB 2021.2.0 and Intel® ISPC 1.15.0 +- Intel® TBB dll is automatically copied into build folder after build on windows. + +### Embree 3.12.2 +- Fixed wrong uv and Ng for grid intersector in robust mode for AVX. +- Removed optimizations for Knights Landing. +- Upgrading release builds to use Intel® oneTBB 2021.1.1 + +### Embree 3.12.1 + +- Changed default frequency level to SIMD128 for Skylake, Cannon Lake, Comet Lake and Tiger Lake CPUs. + This change typically improves performance for renderers that just use SSE by maintaining higher + CPU frequencies. In case your renderer is AVX optimized you can get higher ray tracing performance + by configuring the frequency level to simd256 through passing frequency_level=simd256 to rtcNewDevice. + +### Embree 3.12.0 + +- Added linear cone curve geometry support. In this mode a real geometric surface for curves + with linear basis is rendered using capped cones. They are discontinuous at edge boundaries. +- Enabled fast two level builder for instances when low quality build is requested. +- Bugfix for BVH build when geometries got disabled. +- Added EMBREE_BACKFACE_CULLING_CURVES cmake option. This allows for a cheaper round + linear curve intersection when correct internal tracking and back hits are not required. + The new cmake option defaults to OFF. +- User geometries with invalid bounds with lower>upper in some dimension will be ignored. +- Increased robustness for grid interpolation code and fixed returned out of range u/v + coordinates for grid primitive. +- Fixed handling of motion blur time range for sphere, discs, and oriented disc geometries. +- Fixed missing model data in releases. +- Ensure compatibility to newer versions of Intel® oneTBB. +- Motion blur BVH nodes no longer store NaN values. + ### Embree 3.11.0 - Round linear curves now automatically check for the existence of left and right @@ -19,9 +87,9 @@ Version History - Added EMBREE_COMPACT_POLYS CMake option which enables double indexed triangle and quad leaves to reduce memory consumption in compact mode by an additional 40% at about 15% performance impact. This new mode is disabled by default. -- Compile fix for oneTBB 2021.1-beta05 -- Releases upgrade to TBB 2020.2 -- Compile fix for ISPC v1.13.0 +- Compile fix for Intel® oneTBB 2021.1-beta05 +- Releases upgrade to Intel® TBB 2020.2 +- Compile fix for Intel® ISPC v1.13.0 - Adding RPATH to libembree.so in releases - Increased required CMake version to 3.1.0 - Made instID member for array of pointers ray stream layout optional again. @@ -33,7 +101,7 @@ Version History the curve segments. - Added rtcGetSceneDevice API function, that returns the device a scene got created in. - Improved performance of round curve rendering by up to 1.8x. -- Bugfix to sphere intersection filter invokation for back hit. +- Bugfix to sphere intersection filter invocation for back hit. - Fixed wrong assertion that triggered for invalid curves which anyway get filtered out. - RelWithDebInfo mode no longer enables assertions. - Fixed an issue in FindTBB.cmake that caused compile error with Debug build under Linux. @@ -57,7 +125,7 @@ Version History instantiate a motion blurred scene. - In robust mode the depth test consistently uses tnear <= t <= tfar now in order to robustly continue traversal at a previous hit point - in a way that guarentees reaching all hits, even hits at the same place. + in a way that guarantees reaching all hits, even hits at the same place. - Fixed depth test in robust mode to be precise at tnear and tfar. - Added next_hit tutorial to demonstrate robustly collecting all hits along a ray using multiple ray queries. @@ -68,18 +136,18 @@ Version History for SAH heuristic were counted wrong due to some numerical issues. - Fixed an accuracy issue with rendering very short fat curves. - rtcCommitScene can now get called during rendering from multiple threads - to lazily build geometry. When TBB is used this causes a much lower overhead + to lazily build geometry. When Intel® TBB is used this causes a much lower overhead than using rtcJoinCommitScene. - Geometries can now get attached to multiple scenes at the same time, which simplifies mapping general scene graphs to API. -- Updated to TBB 2019.9 for release builds. +- Updated to Intel® TBB 2019.9 for release builds. - Fixed a bug in the BVH builder for Grid geometries. - Added macOS Catalina support to Embree releases. ### New Features in Embree 3.6.1 - Restored binary compatibility between Embree 3.6 and 3.5 when single-level instancing is used. - Fixed bug in subgrid intersector -- Removed point query alignment in ISPC header +- Removed point query alignment in Intel® ISPC header ### New Features in Embree 3.6 - Added Catmull-Rom curve types. @@ -89,7 +157,7 @@ Version History specified. - Fixed bug in external BVH builder when configured for dynamic build. - Added support for new config flag "user_threads=N" to device initialization - which sets the number of threads used by TBB but created by the user. + which sets the number of threads used by Intel® TBB but created by the user. - Fixed automatic vertex buffer padding when using rtcSetNewGeometry API function. ### New Features in Embree 3.5.2 @@ -123,7 +191,7 @@ Version History - Added point primitives (spheres, ray-oriented discs, normal-oriented discs). - Fixed crash triggered by scenes with only invalid primitives. - Improved robustness of quad/grid-based intersectors. -- Upgraded to TBB 2019.2 for release builds. +- Upgraded to Intel® TBB 2019.2 for release builds. ### New Features in Embree 3.3.0 - Added support for motion blur time range per geometry. This way geometries @@ -281,7 +349,7 @@ Version History by 5-15%. - Fixed tbb_debug.lib linking error under Windows. - Fast coherent ray stream and packet code paths now also work in robust mode. -- Using less agressive prefetching for large BVH nodes which +- Using less aggressive prefetching for large BVH nodes which results in 1-2% higher ray tracing performance. - Precompiled binaries have stack-protector enabled, except for traversal kernels. BVH builders can be slightly slower due to this @@ -292,7 +360,7 @@ Version History fixed, and one can enable only AVX2 and still get best performance by using an 8-wide BVH. - Fixed rtcOccluded1 and rtcOccluded1Ex API functions which were - broken in ISPC. + broken in Intel® ISPC. - Providing MSI installer for Windows. ### New Features in Embree 2.16.5 @@ -318,7 +386,7 @@ Version History cracks when using displacement mapping but reduces performance at irregular vertices. - Fixed a bug where subdivision geometry was not properly updated - when modifying only the tesselation rate and vertex array. + when modifying only the tessellation rate and vertex array. ### New Features in Embree 2.16.2 - Fixed bug that caused NULL intersection context in intersection @@ -481,14 +549,14 @@ Version History If you use Embree v2.11.0 please upgrade to Embree v2.12.0. - Reduced memory consumption for dynamic scenes containing small meshes. -- Added support to start and affinitize TBB worker threads by passing +- Added support to start and affinitize Intel® TBB worker threads by passing "`start_threads=1,set_affinity=1`" to `rtcNewDevice`. These settings are recommended on systems with a high thread count. - `rtcInterpolate2` can now be called within a displacement shader. - Added initial support for Microsoft's Parallel Pattern Library (PPL) - as tasking system alternative (for optimal performance TBB is + as tasking system alternative (for optimal performance Intel® TBB is highly recommended). -- Updated to TBB 2017 which is released under the Apache v2.0 license. +- Updated to Intel® TBB 2017 which is released under the Apache v2.0 license. - Dropped support for Visual Studio 2012 Win32 compiler. Visual Studio 2012 x64 is still supported. @@ -552,14 +620,14 @@ Version History - Added support for quad geometry (replaces triangle-pairs feature). - Added support for linear motion blur of user geometries. - Improved performance through AVX-512 optimizations. -- Improved performance of lazy scene build (when using TBB 4.4 update +- Improved performance of lazy scene build (when using Intel® TBB 4.4 update 2). - Improved performance through huge page support under linux. ### New Features in Embree 2.7.1 - Internal tasking system supports cancellation of build operations. -- ISPC mode for robust and compact scenes got significantly faster +- Intel® ISPC mode for robust and compact scenes got significantly faster (implemented hybrid traversal for bvh4.triangle4v and bvh4.triangle4i). - Hair rendering got faster as we fixed some issues with the SAH @@ -584,7 +652,7 @@ Version History - Added device concept to Embree to allow different components of an application to use Embree without interfering with each other. - Fixed memory leak in twolevel builder used for dynamic scenes. -- Fixed bug in tesselation cache that caused crashes for subdivision +- Fixed bug in tessellation cache that caused crashes for subdivision surfaces. - Fixed bug in internal task scheduler that caused deadlocks when using `rtcCommitThread`. @@ -658,10 +726,10 @@ Version History progress and cancel long build operations - BVH builders can be used to build user defined hierarchies inside the application (see tutorial [BVH Builder]) -- Switched to TBB as default tasking system on Xeon to get even faster +- Switched to Intel® TBB as default tasking system on Xeon to get even faster hierarchy build times and better integration for applications that - also use TBB -- `rtcCommit` can get called from multiple TBB threads to join the + also use Intel® TBB +- `rtcCommit` can get called from multiple Intel® TBB threads to join the hierarchy build operations ### New Features in Embree 2.4 @@ -749,7 +817,6 @@ Version History - Support for the Intel® Xeon Phi™ coprocessor platform - Support for high-performance "packet" kernels on SSE, AVX, and Xeon Phi -- Integration with the Intel® SPMD Program Compiler (ISPC) +- Integration with the Intel® Implicit SPMD Program Compiler (Intel® ISPC) - Instantiation and fast BVH reconstruction -- Example photo-realistic rendering engine for both C++ and ISPC - +- Example photo-realistic rendering engine for both C++ and Intel® ISPC diff --git a/doc/src/compilation.md b/doc/src/compilation.md index 1d534c7e3c..962f1e3de0 100644 --- a/doc/src/compilation.md +++ b/doc/src/compilation.md @@ -12,6 +12,7 @@ C++11. Embree is tested with the following compilers: Linux + - Intel® oneAPI DPC++/C++ Compiler 2022.0.0 - Intel® Compiler 2020 Update 1 - Intel® Compiler 2019 Update 4 - Intel® Compiler 2017 Update 1 @@ -19,33 +20,37 @@ Linux - Intel® Compiler 2015 Update 3 - Clang 5.0.0 - Clang 4.0.0 - - GCC 10.0.1 (Fedora 32) - - GCC 8.3.1 (Fedora 28) - - GCC 7.3.1 (Fedora 27) - - GCC 7.3.1 (Fedora 26) - - GCC 6.4.1 (Fedora 25) + - GCC 10.0.1 (Fedora 32) AVX512 support + - GCC 8.3.1 (Fedora 28) AVX512 support + - GCC 7.3.1 (Fedora 27) AVX2 support + - GCC 7.3.1 (Fedora 26) AVX2 support + - GCC 6.4.1 (Fedora 25) AVX2 support -macOS +macOS x86 - Intel® Compiler 2020 Update 1 - Intel® Compiler 2019 Update 4 - Apple LLVM 10.0.1 (macOS 10.14.6) +macOS M1 + + - Apple Clang 12.0.0 + Embree supports using the Intel® Threading Building Blocks (TBB) as the tasking system. For performance and flexibility reasons we recommend to use Embree with the Intel® Threading Building Blocks (TBB) and best also use TBB inside your application. Optionally you can disable TBB in Embree through the `EMBREE_TASKING_SYSTEM` CMake variable. -Embree supports the Intel® SPMD Program Compiler (ISPC), which allows +Embree supports the Intel® Implicit SPMD Program Compiler (Intel® ISPC), which allows straightforward parallelization of an entire renderer. If you do not -want to use ISPC then you can disable `EMBREE_ISPC_SUPPORT` in -CMake. Otherwise, download and install the ISPC binaries (we have -tested ISPC version 1.9.1) from +want to use Intel® ISPC then you can disable `EMBREE_ISPC_SUPPORT` in +CMake. Otherwise, download and install the Intel® ISPC binaries (we have +tested Intel® ISPC version 1.9.1) from [ispc.github.io](https://ispc.github.io/downloads.html). After installation, put the path to `ispc` permanently into your `PATH` environment variable or you need to correctly set the -`ISPC_EXECUTABLE` variable during CMake configuration. +`EMBREE_ISPC_EXECUTABLE` variable during CMake configuration. You additionally have to install CMake 3.1.0 or higher and the developer version of GLUT. @@ -128,6 +133,7 @@ Embree is tested using the following compilers under Windows: - Visual Studio 2019 - Visual Studio 2017 - Visual Studio 2015 (Update\ 1) + - Intel® oneAPI DPC++/C++ Compiler 2022.0.0 - Intel® Compiler 2019 Update 6 - Intel® Compiler 2017 Update 8 - LLVM Clang 9.0.0 @@ -143,22 +149,28 @@ in Embree through the `EMBREE_TASKING_SYSTEM` CMake variable. Embree will either find the Intel® Threading Building Blocks (TBB) installation that comes with the Intel® Compiler, or you can install the binary distribution of TBB directly from -[www.threadingbuildingblocks.org](https://www.threadingbuildingblocks.org/download) +[https://github.com/oneapi-src/oneTBB/releases](https://github.com/oneapi-src/oneTBB/releases) into a folder named `tbb` into your Embree root directory. You also have to make sure that the libraries `tbb.dll` and `tbb_malloc.dll` can be found when executing your Embree applications, e.g. by putting the path to these libraries into your `PATH` environment variable. -Embree supports the Intel® SPMD Program Compiler (ISPC), which allows +Embree supports the Intel® Implicit SPMD Program Compiler (Intel® ISPC), which allows straightforward parallelization of an entire renderer. When installing -ISPC, make sure to download an ISPC version from +Intel® ISPC, make sure to download an Intel® ISPC version from [ispc.github.io](https://ispc.github.io/downloads.html) that is compatible with your Visual Studio version. After installation, put the path to `ispc.exe` permanently into your `PATH` environment -variable or you need to correctly set the `ISPC_EXECUTABLE` variable -during CMake configuration. We have tested ISPC version 1.9.1. If you -do not want to use ISPC then you can disable `EMBREE_ISPC_SUPPORT` in -CMake. +variable or you need to correctly set the `EMBREE_ISPC_EXECUTABLE` variable +during CMake configuration. If you do not want to use Intel® ISPC then you +can disable `EMBREE_ISPC_SUPPORT` in CMake. + +We have tested Embree with the following Intel® ISPC versions: + + - Intel® ISPC 1.14.1 + - Intel® ISPC 1.13.0 + - Intel® ISPC 1.12.0 + - Intel® ISPC 1.9.2 You additionally have to install [CMake](http://www.cmake.org/download/) (version 2.8.11 or higher). Note that you need a native Windows CMake @@ -243,15 +255,14 @@ parameters that can be configured in CMake: + `EMBREE_STACK_PROTECTOR`: Enables protection of return address from buffer overwrites. This option is OFF by default. -+ `EMBREE_ISPC_SUPPORT`: Enables ISPC support of Embree. This option ++ `EMBREE_ISPC_SUPPORT`: Enables Intel® ISPC support of Embree. This option is ON by default. + `EMBREE_STATIC_LIB`: Builds Embree as a static library (OFF by default). Further multiple static libraries are generated for the different ISAs selected (e.g. `embree3.a`, `embree3_sse42.a`, - `embree3_avx.a`, `embree3_avx2.a`, `embree3_avx512knl.a`, - `embree3_avx512skx.a`). You have to link these libraries in exactly - this order of increasing ISA. + `embree3_avx.a`, `embree3_avx2.a`, `embree3_avx512.a`). You have + to link these libraries in exactly this order of increasing ISA. + `EMBREE_API_NAMESPACE`: Specifies a namespace name to put all Embree API symbols inside. By default no namespace is used and plain C symbols @@ -280,7 +291,7 @@ parameters that can be configured in CMake: + `EMBREE_RAY_PACKETS`: Enables ray packet traversal kernels. This feature is turned ON by default. When turned on packet traversal is used internally and packets passed to rtcIntersect4/8/16 are kept - intact in callbacks (when the ISA of appropiate width is enabled). + intact in callbacks (when the ISA of appropriate width is enabled). + `EMBREE_IGNORE_INVALID_RAYS`: Makes code robust against the risk of full-tree traversals caused by invalid rays (e.g. rays containing @@ -291,24 +302,28 @@ parameters that can be configured in CMake: only), or an internal tasking system (INTERNAL). By default TBB is used. -+ `EMBREE_TBB_ROOT`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_ROOT`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, search the library in this directory tree. -+ `EMBREE_TBB_POSTFIX`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_COMPONENT`: The component/libary name of Intel® Threading + Building Blocks (TBB). Embree searches for this library name (default: tbb) + when TBB is used as tasking system. + ++ `EMBREE_TBB_POSTFIX`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, link to tbb.(so,dll,lib). Defaults to the empty string. -+ `EMBREE_TBB_DEBUG_ROOT`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_DEBUG_ROOT`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, search the library in this directory tree in Debug mode. Defaults to `EMBREE_TBB_ROOT`. -+ `EMBREE_TBB_DEBUG_POSTFIX`: If Intel® Threading TBB Building Blocks (TBB) ++ `EMBREE_TBB_DEBUG_POSTFIX`: If Intel® Threading Building Blocks (TBB) is used as a tasking system, link to tbb.(so,dll,lib) in Debug mode. Defaults to "_debug". + `EMBREE_MAX_ISA`: Select highest supported ISA (SSE2, SSE4.2, AVX, - AVX2, AVX512KNL, AVX512SKX, or NONE). When set to NONE the + AVX2, AVX512, or NONE). When set to NONE the EMBREE_ISA_* variables can be used to enable ISAs individually. By default the option is set to AVX2. @@ -324,10 +339,7 @@ parameters that can be configured in CMake: + `EMBREE_ISA_AVX2`: Enables AVX2 when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF. -+ `EMBREE_ISA_AVX512KNL`: Enables AVX-512 for Xeon Phi when - EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF. - -+ `EMBREE_ISA_AVX512SKX`: Enables AVX-512 for Skylake when ++ `EMBREE_ISA_AVX512`: Enables AVX-512 for Skylake when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF. + `EMBREE_GEOMETRY_TRIANGLE`: Enables support for trianglegeometries @@ -377,12 +389,8 @@ CMake find Embree using the `FIND_PACKAGE` function inside your FIND_PACKAGE(embree 3.0 REQUIRED) -If you installed Embree using the Linux RPM or macOS PKG installer, -this will automatically find Embree. If you used the `zip` or `tar.gz` -files to extract Embree, you need to set the `embree_DIR` variable to -the folder you extracted Embree to. If you used the Windows MSI -installer, you need to set `embree_DIR` to point to the Embree install -location (e.g. `C:\Program Files\Intel\Embree3`). +To cmake to properly find Embree you need to set the `embree_DIR` +variable to the folder you extracted Embree to. The `FIND_PACKAGE` function will create an embree target that you can add to your target link libraries: diff --git a/doc/src/downloading.md b/doc/src/downloading.md index 8d0a3e2d92..20622838db 100644 --- a/doc/src/downloading.md +++ b/doc/src/downloading.md @@ -1,25 +1,18 @@ Downloading Embree ------------------ -For Windows we provide Embree as MSI installer and ZIP files linked -against the Visual Studio 2015/2017 (VC14) runtime: +For Windows we provide Embree as ZIP files linked against the Visual Studio 2015/2017 (VC14) runtime: -[embree--x64.vc14.msi](https://github.com/embree/embree/releases/download/v/embree-.x64.vc14.msi) [embree-.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v/embree-.x64.vc14.windows.zip) For Linux we provide Embree as a `tar.gz` file: [embree-.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v/embree-.x86_64.linux.tar.gz) -For macOS we provide Embree as PKG installer and as a ZIP file: +For macOS we provide Embree a ZIP file: -[embree-.x86_64.pkg](https://github.com/embree/embree/releases/download/v/embree-.x86_64.pkg) [embree-.x86_64.macosx.zip](https://github.com/embree/embree/releases/download/v/embree-.x86_64.macosx.zip) -For the first generation Intel® Xeon Phi™ coprocessor (codenamed Knights Corner) we provide Embree v2.9.0 precompiled for Linux as a `tar.gz` file: - -[embree-knc-2.9.0.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v2.9.0/embree-knc-2.9.0.x86_64.linux.tar.gz) - The source code of the latest Embree version can be downloaded here: [embree-.zip](https://github.com/embree/embree/archive/v.zip) @@ -40,4 +33,3 @@ You can also check out the source code of Embree with subversion: If you encounter bugs please report them to the [GitHub Issue Tracker](https://github.com/embree/embree/issues) for Embree. - diff --git a/doc/src/install.md b/doc/src/install.md index b09c32be8c..8aae219ac3 100644 --- a/doc/src/install.md +++ b/doc/src/install.md @@ -1,96 +1,44 @@ Installation of Embree ====================== -Windows MSI Installer ---------------------- - -You can install the Embree library using the Windows MSI installer -[embree--x64.vc12.msi](https://github.com/embree/embree/releases/download/v/embree-.x64.vc12.msi). This -will install the 64-bit Embree version by default in `Program -Files\Intel\Embree v x64`. - -You have to set the path to the `bin` folders manually to your `PATH` -environment variable for applications to find Embree. - -To compile applications with Embree using CMake, please have a look at -the `find_embree` tutorial. To compile this tutorial, you need to set -the `embree_DIR` CMake variable of this tutorial to `Program -Files\Intel\Embree v x64`. - -To uninstall Embree, open `Programs and Features` by clicking the -`Start button`, clicking `Control Panel`, clicking `Programs`, and -then clicking `Programs and Features`. Select `Embree - x64` and uninstall it. - Windows ZIP File ----------------- -Embree linked against Visual Studio 2013 -[embree-.x64.vc12.windows.zip](https://github.com/embree/embree/releases/download/v/embree-.x64.vc12.windows.zip) -and Visual Studio 2015 -[embree-.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v/embree-.x64.vc14.windows.zip) -are provided as a ZIP file. After unpacking this ZIP file, you should -set the path to the `lib` folder manually to your `PATH` environment -variable for applications to find Embree. To compile applications with -Embree, you also have to set the `Include Directories` path in Visual -Studio to the `include` folder of the Embree installation. - -If you plan to ship Embree with your application, best use the Embree -version from this ZIP file. +Embree linked against Visual Studio 2015 are provided as a ZIP file +[embree-.x64.vc14.windows.zip](https://github.com/embree/embree/releases/download/v/embree-.x64.vc14.windows.zip). After +unpacking this ZIP file, you should set the path to the `lib` folder +manually to your `PATH` environment variable for applications to find +Embree. Linux tar.gz Files ------------------ The Linux version of Embree is also delivered as a `tar.gz` file: -[embree-.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v/embree-.x86_64.linux.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you -are using the bash shell) or `embree-vars.csh` (if you are using the -C shell) to set up the environment properly: +[embree-.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v/embree-.x86_64.linux.tar.gz). Unpack +this file using `tar` and source the provided `embree-vars.sh` (if you +are using the bash shell) or `embree-vars.csh` (if you are using the C +shell) to set up the environment properly: tar xzf embree-.x86_64.linux.tar.gz source embree-.x86_64.linux/embree-vars.sh -If you want to ship Embree with your application, best use the Embree -version provided in the `tar.gz` file. - We recommend adding a relative `RPATH` to your application that points to the location where Embree (and TBB) can be found, e.g. `$ORIGIN/../lib`. -macOS PKG Installer -------------------- - -To install the Embree library on your macOS system use the -provided package installer inside -[embree-.x86_64.pkg](https://github.com/embree/embree/releases/download/v/embree-.x86_64.pkg). This -will install Embree by default into `/opt/local/lib` and -`/opt/local/include` directories. The Embree tutorials are installed -into the `/Applications/Embree` directory. - -You also have to install the Intel® Threading Building Blocks (TBB) -using [MacPorts](http://www.macports.org/): - - sudo port install tbb - -Alternatively you can download the latest TBB version from -[https://www.threadingbuildingblocks.org/download](https://www.threadingbuildingblocks.org/download) -and set the `DYLD_LIBRARY_PATH` environment variable to point -to the TBB library. - -To uninstall Embree, execute the uninstaller script -`/Applications/Embree/uninstall.command`. - -macOS tar.gz file +macOS ZIP file ----------------- -The macOS version of Embree is also delivered as a `tar.gz` file: -[embree-.x86_64.macosx.tar.gz](https://github.com/embree/embree/releases/download/v/embree-.x86_64.macosx.tar.gz). Unpack this file using `tar` and source the provided `embree-vars.sh` (if you -are using the bash shell) or `embree-vars.csh` (if you are using the -C shell) to set up the environment properly: +The macOS version of Embree is also delivered as a ZIP file: +[embree-.x86_64.macosx.zip](https://github.com/embree/embree/releases/download/v/embree-.x86_64.macosx.zip). Unpack +this file using `tar` and source the provided `embree-vars.sh` (if you +are using the bash shell) or `embree-vars.csh` (if you are using the C +shell) to set up the environment properly: - tar xzf embree-.x64.macosx.tar.gz + unzip embree-.x64.macosx.zip source embree-.x64.macosx/embree-vars.sh If you want to ship Embree with your application, please use the Embree -library of the provided `tar.gz` file. The library name of that Embree +library of the provided ZIP file. The library name of that Embree library is of the form `@rpath/libembree..dylib` (and similar also for the included TBB library). This ensures that you can add a relative `RPATH` to your application that points to the location diff --git a/doc/src/intro.md b/doc/src/intro.md new file mode 100644 index 0000000000..7c00f2bdf2 --- /dev/null +++ b/doc/src/intro.md @@ -0,0 +1,209 @@ +The Embree API is a low-level C99 ray tracing API which can be used to +construct 3D scenes and perform ray queries of different types inside +these scenes. All API calls carry the prefix `rtc` (or `RTC` for +types) which stands for **r**ay **t**racing **c**ore. + +The API also exists in an Intel® Implicit SPMD Program Compiler +(Intel® ISPC) version, which is almost identical but +contains additional functions that operate on ray packets with a size +of the native SIMD width used by Intel® ISPC. For simplicity this document +refers to the C99 version of the API functions. For changes when +upgrading from the Embree 2 to the current Embree 3 API see Section +[Upgrading from Embree 2 to Embree 3]. + +The API supports scenes consisting of different geometry types such as +triangle meshes, quad meshes (triangle pairs), grid meshes, flat +curves, round curves, oriented curves, subdivision meshes, instances, +and user-defined geometries. See Section [Scene Object] for more +information. + +Finding the closest hit of a ray segment with the scene +(`rtcIntersect`-type functions), and determining whether any hit +between a ray segment and the scene exists (`rtcOccluded`-type +functions) are both supported. The API supports queries for single +rays, ray packets, and ray streams. See Section [Ray Queries] for +more information. + +The API is designed in an object-oriented manner, e.g. it contains +device objects (`RTCDevice` type), scene objects (`RTCScene` type), +geometry objects (`RTCGeometry` type), buffer objects (`RTCBuffer` +type), and BVH objects (`RTCBVH` type). All objects are reference +counted, and handles can be released by calling the appropriate release +function (e.g. `rtcReleaseDevice`) or retained by incrementing the +reference count (e.g. `rtcRetainDevice`). In general, API calls that +access the same object are not thread-safe, unless specified +differently. However, attaching geometries to the same scene and +performing ray queries in a scene is thread-safe. + +Device Object +------------- + +Embree supports a device concept, which allows different components of +the application to use the Embree API without interfering with each +other. An application typically first creates a device using the +[rtcNewDevice] function. This device can then be used to construct +further objects, such as scenes and geometries. Before the application +exits, it should release all devices by invoking [rtcReleaseDevice]. An +application typically creates only a single device. If required +differently, it should only use a small number of devices at any given +time. + +Each user thread has its own error flag per device. If an error occurs +when invoking an API function, this flag is set to an error code (if +it isn't already set by a previous error). See Section +[rtcGetDeviceError] for information on how to read the error code +and Section [rtcSetDeviceErrorFunction] on how to register a +callback that is invoked for each error encountered. It is recommended +to always set a error callback function, to detect all errors. + +Scene Object +------------ + +A scene is a container for a set of geometries, and contains a spatial +acceleration structure which can be used to perform different types of +ray queries. + +A scene is created using the `rtcNewScene` function call, and released +using the `rtcReleaseScene` function call. To populate a scene with +geometries use the `rtcAttachGeometry` call, and to detach them use the +`rtcDetachGeometry` call. Once all scene geometries are attached, an +`rtcCommitScene` call (or `rtcJoinCommitScene` call) will finish the +scene description and trigger building of internal data structures. +After the scene got committed, it is safe to perform ray queries (see +Section [Ray Queries]) or to query the scene bounding box (see +[rtcGetSceneBounds] and [rtcGetSceneLinearBounds]). + +If scene geometries get modified or attached or detached, the +`rtcCommitScene` call must be invoked before performing any further +ray queries for the scene; otherwise the effect of the ray query is +undefined. The modification of a geometry, committing the scene, and +tracing of rays must always happen sequentially, and never at the same +time. Any API call that sets a property of the scene or geometries +contained in the scene count as scene modification, e.g. including +setting of intersection filter functions. + +Scene flags can be used to configure a scene to use less memory +(`RTC_SCENE_FLAG_COMPACT`), use more robust traversal algorithms +(`RTC_SCENE_FLAG_ROBUST`), and to optimize for dynamic content. See +Section [rtcSetSceneFlags] for more details. + +A build quality can be specified for a scene to balance between +acceleration structure build performance and ray query performance. +See Section [rtcSetSceneBuildQuality] for more details on build +quality. + +Geometry Object +--------------- + +A new geometry is created using the `rtcNewGeometry` function. +Depending on the geometry type, different buffers must be bound (e.g. +using `rtcSetSharedGeometryBuffer`) to set up the geometry data. In +most cases, binding of a vertex and index buffer is required. The +number of primitives and vertices of that geometry is typically +inferred from the size of these bound buffers. + +Changes to the geometry always must be committed using the +`rtcCommitGeometry` call before using the geometry. After committing, +a geometry is not included in any scene. A geometry can be added to +a scene by using the `rtcAttachGeometry` function (to automatically +assign a geometry ID) or using the `rtcAttachGeometryById` function +(to specify the geometry ID manually). A geometry can get attached +to multiple scenes. + +All geometry types support multi-segment motion blur with an arbitrary +number of equidistant time steps (in the range of 2 to 129) inside a +user specified time range. Each geometry can have a different number +of time steps and a different time range. The motion blur geometry is +defined by linearly interpolating the geometries of neighboring time +steps. To construct a motion blur geometry, first the number of time +steps of the geometry must be specified using the +`rtcSetGeometryTimeStepCount` function, and then a vertex buffer for +each time step must be bound, e.g. using the +`rtcSetSharedGeometryBuffer` function. Optionally, a time range +defining the start (and end time) of the first (and last) time step +can be set using the `rtcSetGeometryTimeRange` function. This feature +will also allow geometries to appear and disappear during the camera +shutter time if the time range is a sub range of [0,1]. + +The API supports per-geometry filter callback functions (see +`rtcSetGeometryIntersectFilterFunction` and +`rtcSetGeometryOccludedFilterFunction`) that are invoked for each +intersection found during the `rtcIntersect`-type or +`rtcOccluded`-type calls. The former ones are called geometry +intersection filter functions, the latter ones geometry occlusion +filter functions. These filter functions are designed to be used to +ignore intersections outside of a user-defined silhouette of a +primitive, e.g. to model tree leaves using transparency textures. + +Ray Queries +----------- + +The API supports finding the closest hit of a ray segment with the +scene (`rtcIntersect`-type functions), and determining whether any hit +between a ray segment and the scene exists (`rtcOccluded`-type +functions). + +Supported are single ray queries (`rtcIntersect1` and `rtcOccluded1`) +as well as ray packet queries for ray packets of size 4 +(`rtcIntersect4` and `rtcOccluded4`), ray packets of size 8 +(`rtcIntersect8` and `rtcOccluded8`), and ray packets of size 16 +(`rtcIntersect16` and `rtcOccluded16`). + +Ray streams in a variety of layouts are supported as well, such as +streams of single rays (`rtcIntersect1M` and `rtcOccluded1M`), streams +of pointers to single rays (`rtcIntersect1p` and `rtcOccluded1p`), +streams of ray packets (`rtcIntersectNM` and `rtcOccludedNM`), and +large packet-like streams in structure of pointer layout +(`rtcIntersectNp` and `rtcOccludedNp`). + +See Sections [rtcIntersect1] and [rtcOccluded1] for a detailed +description of how to set up and trace a ray. + +See tutorial [Triangle Geometry] for a complete example of how to +trace single rays and ray packets. Also have a look at the tutorial +[Stream Viewer] for an example of how to trace ray streams. + +Point Queries +------------- + +The API supports traversal of the BVH using a point query object that +specifies a location and a query radius. For all primitives intersecting the +according domain, a user defined callback function is called which allows +queries such as finding the closest point on the surface geometries of the +scene (see Tutorial [Closest Point]) or nearest neighbour queries (see +Tutorial [Voronoi]). + +See Section [rtcPointQuery] for a detailed description of how to set up +point queries. + +Collision Detection +------------------- + +The Embree API also supports collision detection queries between two +scenes consisting only of user geometries. Embree only performs +broadphase collision detection, the narrow phase detection can be +performed through a callback function. + +See Section [rtcCollide] for a detailed description of how to set up collision +detection. + +Seen tutorial [Collision Detection] for a complete example of collision +detection being used on a simple cloth solver. + + +Miscellaneous +------------- + +A context filter function, which can be set per ray query is supported +(see `rtcInitIntersectContext`). This filter function is designed to +change the semantics of the ray query, e.g. to accumulate opacity for +transparent shadows, count the number of surfaces along a ray, +collect all hits along a ray, etc. + +The internal algorithms to build a BVH are exposed through the `RTCBVH` +object and `rtcBuildBVH` call. This call makes it possible to build a +BVH in a user-specified format over user-specified primitives. See the +documentation of the `rtcBuildBVH` call for more details. + +For getting the most performance out of Embree, see the Section +[Performance Recommendations]. diff --git a/doc/src/legal.md b/doc/src/legal.md index 1c02951aa0..d0f4709d4d 100644 --- a/doc/src/legal.md +++ b/doc/src/legal.md @@ -9,30 +9,12 @@ Intel, the Intel logo, Xeon, Intel Xeon Phi, and Intel Core are trademarks of Intel Corporation in the U.S. and/or other countries. *Other names and brands may be claimed as the property of others. +Performance varies by use, configuration and other factors. Learn more +at +[www.Intel.com/PerformanceIndex](https://www.intel.com/PerformanceIndex). -Optimization Notice: Intel's compilers may or may not optimize to the -same degree for non-Intel microprocessors for optimizations that are not -unique to Intel microprocessors. These optimizations include SSE2, SSE3, -and SSSE3 instruction sets and other optimizations. Intel does not -guarantee the availability, functionality, or effectiveness of any -optimization on microprocessors not manufactured by Intel. -Microprocessor-dependent optimizations in this product are intended for -use with Intel microprocessors. Certain optimizations not specific to -Intel microarchitecture are reserved for Intel microprocessors. Please -refer to the applicable product User and Reference Guides for more -information regarding the specific instruction sets covered by this -notice. -Notice Revision #20110804 - -Software and workloads used in performance tests may have been optimized -for performance only on Intel microprocessors. -Performance tests, such as SYSmark and MobileMark, are measured using -specific computer systems, components, software, operations and -functions. Any change to any of those factors may cause the results to -vary. You should consult other information and performance tests to -assist you in fully evaluating your contemplated purchases, including -the performance of that product when combined with other products. -For more complete information visit . +Intel optimizations, for Intel compilers or other products, may not +optimize to the same degree for non-Intel products. Intel Embree is using third party libraries in its implementation. Please see the third-party-programs.txt file contained diff --git a/doc/src/overview.md b/doc/src/overview.md index d3b5ab61d5..5e26190ad8 100644 --- a/doc/src/overview.md +++ b/doc/src/overview.md @@ -14,12 +14,12 @@ highest benefit from future improvements. Intel® Embree is released as Open Source under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). -Intel® Embree supports applications written with the Intel® SPMD Program -Compiler (ISPC, ) by also providing an ISPC +Intel® Embree supports applications written with the Intel® Implicit SPMD +Program Compiler (Intel® ISPC, ) by also providing an Intel® ISPC interface to the core ray tracing algorithms. This makes it possible -to write a renderer in ISPC that automatically vectorizes and -leverages SSE, AVX, AVX2, and AVX-512 instructions. ISPC also supports -runtime code selection, thus ISPC will select the best code path for +to write a renderer in Intel® ISPC that automatically vectorizes and +leverages SSE, AVX, AVX2, and AVX-512 instructions. Intel® ISPC also supports +runtime code selection, thus Intel® ISPC will select the best code path for your application. Intel® Embree contains algorithms optimized for incoherent workloads (e.g. diff --git a/doc/src/papers.html b/doc/src/papers.html index b3e42a26bf..81857357dd 100644 --- a/doc/src/papers.html +++ b/doc/src/papers.html @@ -1,5 +1,18 @@

Embree Related Papers

+Ray Tracing Lossy Compressed Grid Primitives +
+Carsten Benthin, Karthik Vaidyanathan, Sven Woop +
+To appear Eurographics 2021 +
+[
pdf], +[bib] +
+
+ +

+ Wide BVH Traversal with a Short Stack
Karthik Vaidyanathan, Sven Woop, and Carsten Benthin diff --git a/doc/src/platforms.md b/doc/src/platforms.md index c9035596fb..5993f1bc98 100644 --- a/doc/src/platforms.md +++ b/doc/src/platforms.md @@ -2,8 +2,8 @@ Supported Platforms ------------------- Embree supports Windows (32-bit and 64-bit), Linux (64-bit), and macOS -(64-bit). The code compiles with the Intel® Compiler, GCC, Clang, -and the Microsoft Compiler. +(64-bit) both x86 and Apple M1 based. The code compiles with the Intel® +Compiler, GCC, Clang, and the Microsoft Compiler. Using the Intel® Compiler improves performance by approximately 10%. Performance also varies across different operating @@ -11,6 +11,5 @@ systems, with Linux typically performing best as it supports transparently transitioning to 2MB pages. Embree is optimized for Intel CPUs supporting SSE, AVX, AVX2, and -AVX-512 instructions, and requires at least a CPU with support for -SSE2. - +AVX-512 instructions. Embree requires at least an x86 CPU with support for +SSE2 or an Apple M1 CPU. diff --git a/doc/src/projects.md b/doc/src/projects.md index bcbff9e5f4..cf20f6f62c 100644 --- a/doc/src/projects.md +++ b/doc/src/projects.md @@ -24,6 +24,8 @@ note](mailto:embree_support@intel.com). * [LibThree](http://libthree.com/): 3D Visualization Made Easy +* [Bella Renderer](https://bellarender.com) + * An Autodesk [Maya 2014 viewport plugin](https://software.intel.com/en-us/articles/an-embree-based-viewport-plugin-for-autodesk-maya) is based on the [Embree Example Renderer]. diff --git a/doc/src/readme.tex b/doc/src/readme.tex index e2c9f8421c..ec133ea554 100644 --- a/doc/src/readme.tex +++ b/doc/src/readme.tex @@ -1,14 +1,17 @@ +%% Copyright 2009-2021 Intel Corporation +%% SPDX-License-Identifier: Apache-2.0 + \IfFileExists{intelstyle/intel-spec.cls} { \documentclass[oneside]{intelstyle/intel-spec} \include{preamble} \copyrightyears{2009--2020} - \trademarkacknowledgement{% + \trademarkacknowledgment{% Intel, the Intel logo, Xeon, Intel Xeon Phi, and Intel Core are trademarks of Intel Corporation in the U.S. and/or other countries. } - \ftcdisclaimer - \ftcoptimizationnotice + \performancedisclaimer + \optimizationdisclaimer } { \documentclass[oneside]{report} diff --git a/doc/src/renderer.md b/doc/src/renderer.md index 38ed8afd0b..5c68697acc 100644 --- a/doc/src/renderer.md +++ b/doc/src/renderer.md @@ -42,8 +42,8 @@ Compiling under Windows ----------------------- For compilation under Windows you first have to install the Embree ray -tracing kernels including the Intel® SPMD Compiler (ISPC). After -installation you have to set the `EMBREE_INSTALL_DIR` environment +tracing kernels including the Intel® Implicit SPMD Program Compiler +(Intel® ISPC). After installation you have to set the `EMBREE_INSTALL_DIR` environment variable to the root folder of Embree. Use the Visual Studio 2008 or Visual Studio 2010 solution file to @@ -53,13 +53,13 @@ on the solution and then selecting the compiler. The project compiles with both compilers in 32-bit and 64-bit mode. We recommend using 64-bit mode and the Intel Compiler for best performance. -To enable AVX and AVX2 for the ISPC code select the build configurations +To enable AVX and AVX2 for the Intel® ISPC code select the build configurations `ReleaseAVX` and `ReleaseAVX2`. You have to compile the Embree kernels with the same or higher instruction set than the Embree example renderer. -By default, the solution file requires ISPC to be installed properly. -For compiling the solution without ISPC, simply delete the device_ispc +By default, the solution file requires Intel® ISPC to be installed properly. +For compiling the solution without Intel® ISPC, simply delete the device_ispc project from the solution file. Compiling under Linux and macOS @@ -85,11 +85,11 @@ configure which parts of the Embree Example Renderer to build: BUILD_SINGLE_RAY_DEVICE_XEON_PHI Single ray rendering device for the Intel® Xeon Phi™ coprocessor. - BUILD_ISPC_DEVICE ISPC CPU rendering device operating + BUILD_ISPC_DEVICE Intel® ISPC CPU rendering device operating on ray packets of size 4 (SSE) or 8 (AVX). - BUILD_ISPC_DEVICE_XEON_PHI ISPC Xeon Phi rendering device + BUILD_ISPC_DEVICE_XEON_PHI Intel® ISPC Xeon Phi rendering device operating on ray packets of size 16. BUILD_NETWORK_DEVICE Network device to render on render @@ -97,14 +97,14 @@ configure which parts of the Embree Example Renderer to build: ---------------------------------- ----------------------------------- : CMake build options for Embree Example Renderer. -When enabling any ISPC renderer, you also have to install ISPC. If you +When enabling any Intel® ISPC renderer, you also have to install Intel® ISPC. If you select `BUILD_ISPC_DEVICE`, you should select which instructions sets to -enable for ISPC (`TARGET_SSE2`, `TARGET_SSE41`, `TARGET_AVX`, and +enable for Intel® ISPC (`TARGET_SSE2`, `TARGET_SSE41`, `TARGET_AVX`, and `TARGET_AVX2`). All target ISAs you select when compiling the Embree Example Render, have also to be enabled when compiling Embree. Due to some limitation of -ISPC you have to enable more than one target ISA if you also enabled +Intel® ISPC you have to enable more than one target ISA if you also enabled more than one target ISA when compiling Embree, otherwise you will get link errors. diff --git a/doc/src/resources.html b/doc/src/resources.html index 3b9a716337..eaf723aab5 100644 --- a/doc/src/resources.html +++ b/doc/src/resources.html @@ -22,10 +22,6 @@

Presentations

Embree 1.1 Presentation at SIGGRAPH 2012

-

Blogs / Forum

+

Forum

-

Read the Embree -Blog for more details about Embree.

- -

Participate in Embree Forum Discussion.

+

Participate in Embree Forum discussions.

diff --git a/doc/src/spec.md b/doc/src/spec.md new file mode 100644 index 0000000000..560d0cf98c --- /dev/null +++ b/doc/src/spec.md @@ -0,0 +1,13 @@ +Introduction +============ + +``` {include=src/intro.md} +``` +\pagebreak + +Embree API +========== + +``` {include=src/api-ref.md} +``` +\pagebreak diff --git a/doc/src/tutorials.md b/doc/src/tutorials.md index ee9b13300d..450190a65a 100644 --- a/doc/src/tutorials.md +++ b/doc/src/tutorials.md @@ -5,12 +5,12 @@ Embree Tutorials Embree comes with a set of tutorials aimed at helping users understand how Embree can be used and extended. There is a very basic minimal that can be compiled as both C and C++, which should get new users started quickly. -All other tutorials exist in an ISPC and C++ version to demonstrate +All other tutorials exist in an Intel® ISPC and C++ version to demonstrate the two versions of the API. Look for files -named `tutorialname_device.ispc` for the ISPC implementation of the +named `tutorialname_device.ispc` for the Intel® ISPC implementation of the tutorial, and files named `tutorialname_device.cpp` for the single ray C++ version of the tutorial. To start the C++ version use the `tutorialname` -executables, to start the ISPC version use the `tutorialname_ispc` +executables, to start the Intel® ISPC version use the `tutorialname_ispc` executables. All tutorials can print available command line options using the `--help` command line parameter. @@ -95,10 +95,12 @@ It can be compiled as both C and C++. It demonstrates how to initialize a device and scene, and how to intersect rays with the scene. There is no image output to keep the tutorial as simple as possible. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/minimal/minimal.cpp) + Triangle Geometry ----------------- -![][imgTriangleGeometry] +[![][imgTriangleGeometry]](https://github.com/embree/embree/blob/master/tutorials/triangle_geometry/triangle_geometry_device.cpp) This tutorial demonstrates the creation of a static cube and ground plane using triangle meshes. It also demonstrates the use of the @@ -106,10 +108,12 @@ plane using triangle meshes. It also demonstrates the use of the and hard shadows. The cube sides are colored based on the ID of the hit primitive. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/triangle_geometry/triangle_geometry_device.cpp) + Dynamic Scene ------------- -![][imgDynamicScene] +[![][imgDynamicScene]](https://github.com/embree/embree/blob/master/tutorials/dynamic_scene/dynamic_scene_device.cpp) This tutorial demonstrates the creation of a dynamic scene, consisting of several deforming spheres. Half of the spheres use the @@ -119,10 +123,12 @@ to use a refitting strategy for these spheres, the other half uses the performance rebuild of their spatial data structure each frame. The spheres are colored based on the ID of the hit sphere geometry. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/dynamic_scene/dynamic_scene_device.cpp) + Multi Scene Geometry ------------- -![][imgDynamicScene] +[![][imgDynamicScene]](https://github.com/embree/embree/blob/master/tutorials/multiscene_geometry/multiscene_geometry_device.cpp) This tutorial demonstrates the creation of multiple scenes sharing the same geometry objects. Here, three scenes are built. One with all @@ -130,10 +136,12 @@ the dynamic spheres of the Dynamic Scene test and two others each with half. The ground plane is shared by all three scenes. The space bar is used to cycle the scene chosen for rendering. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/multiscene_geometry/multiscene_geometry_device.cpp) + User Geometry ------------- -![][imgUserGeometry] +[![][imgUserGeometry]](https://github.com/embree/embree/blob/master/tutorials/user_geometry/user_geometry_device.cpp) This tutorial shows the use of user-defined geometry, to re-implement instancing, and to add analytic spheres. A two-level scene is created, @@ -143,10 +151,12 @@ The spheres are colored using the instance ID and geometry ID of the hit sphere, to demonstrate how the same geometry instanced in different ways can be distinguished. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/user_geometry/user_geometry_device.cpp) + Viewer ------ -![][imgViewer] +[![][imgViewer]](https://github.com/embree/embree/blob/master/tutorials/viewer/viewer_device.cpp) This tutorial demonstrates a simple OBJ viewer that traces primary visibility rays only. A scene consisting of multiple meshes is created, @@ -159,10 +169,12 @@ work: ./viewer -i model.obj +[Source Code](https://github.com/embree/embree/blob/master/tutorials/viewer/viewer_device.cpp) + Stream Viewer ------------- -![][imgViewerStream] +[![][imgViewerStream]](https://github.com/embree/embree/blob/master/tutorials/viewer_stream/viewer_stream_device.cpp) This tutorial is a simple OBJ viewer that demonstrates the use of ray streams. You need to specify an OBJ file at the command line for this @@ -170,10 +182,12 @@ tutorial to work: ./viewer_stream -i model.obj +[Source Code](https://github.com/embree/embree/blob/master/tutorials/viewer_stream/viewer_stream_device.cpp) + Intersection Filter ------------------- -![][imgIntersectionFilter] +[![][imgIntersectionFilter]](https://github.com/embree/embree/blob/master/tutorials/intersection_filter/intersection_filter_device.cpp) This tutorial demonstrates the use of filter callback functions to efficiently implement transparent objects. The filter function used for @@ -183,10 +197,12 @@ properly, by potentially shooting secondary rays. The filter function used for shadow rays accumulates the transparency of all surfaces along the ray, and terminates traversal if an opaque occluder is hit. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/intersection_filter/intersection_filter_device.cpp) + Instanced Geometry ------------------ -![][imgInstancedGeometry] +[![][imgInstancedGeometry]](https://github.com/embree/embree/blob/master/tutorials/instanced_geometry/instanced_geometry_device.cpp) This tutorial demonstrates the in-build instancing feature of Embree, by instancing a number of other scenes built from triangulated spheres. The @@ -194,10 +210,12 @@ spheres are again colored using the instance ID and geometry ID of the hit sphere, to demonstrate how the same geometry instanced in different ways can be distinguished. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/instanced_geometry/instanced_geometry_device.cpp) + Multi Level Instancing ---------------------- -![][imgMultiLevelInstancing] +[![][imgMultiLevelInstancing]](https://github.com/embree/embree/blob/master/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp) This tutorial demonstrates multi-level instancing, i.e., nesting instances into instances. To enable the tutorial, set the compile-time variable @@ -215,10 +233,12 @@ During shading, the instance ID stack is used to accumulate normal transformation matrices for each hit. The tutorial visualizes transformed normals as colors. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp) + Path Tracer ----------- -![][imgPathtracer] +[![][imgPathtracer]](https://github.com/embree/embree/blob/master/tutorials/pathtracer/pathtracer_device.cpp) This tutorial is a simple path tracer, based on the viewer tutorial. @@ -240,58 +260,72 @@ To render these models execute the following: ./pathtracer -c crown/crown.ecs ./pathtracer -c asian_dragon/asian_dragon.ecs +[Source Code](https://github.com/embree/embree/blob/master/tutorials/pathtracer/pathtracer_device.cpp) + Hair ---- -![][imgHairGeometry] +[![][imgHairGeometry]](https://github.com/embree/embree/blob/master/tutorials/hair_geometry/hair_geometry_device.cpp) This tutorial demonstrates the use of the hair geometry to render a hairball. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/hair_geometry/hair_geometry_device.cpp) + Curve Geometry -------------- -![][imgCurveGeometry] +[![][imgCurveGeometry]](https://github.com/embree/embree/blob/master/tutorials/curve_geometry/curve_geometry_device.cpp) + +This tutorial demonstrates the use of the Linear Basis, B-Spline, and Catmull-Rom curve geometries. -This tutorial demonstrates the use of the B-Spline and Catmull-Rom curve geometries. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/curve_geometry/curve_geometry_device.cpp) Subdivision Geometry -------------------- -![][imgSubdivisionGeometry] +[![][imgSubdivisionGeometry]](https://github.com/embree/embree/blob/master/tutorials/subdivision_geometry/subdivision_geometry_device.cpp) This tutorial demonstrates the use of Catmull-Clark subdivision surfaces. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/subdivision_geometry/subdivision_geometry_device.cpp) + Displacement Geometry --------------------- -![][imgDisplacementGeometry] +[![][imgDisplacementGeometry]](https://github.com/embree/embree/blob/master/tutorials/displacement_geometry/displacement_geometry_device.cpp) This tutorial demonstrates the use of Catmull-Clark subdivision surfaces with procedural displacement mapping using a constant edge tessellation level. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/displacement_geometry/displacement_geometry_device.cpp) + Grid Geometry --------------------- -![][imgGridGeometry] +[![][imgGridGeometry]](https://github.com/embree/embree/tree/master/tutorials/grid_geometry) This tutorial demonstrates the use of the memory efficient grid primitive to handle highly tessellated and displaced geometry. +[Source Code](https://github.com/embree/embree/tree/master/tutorials/grid_geometry) + Point Geometry --------------------- -![][imgPointGeometry] +[![][imgPointGeometry]](https://github.com/embree/embree/blob/master/tutorials/point_geometry/point_geometry_device.cpp) This tutorial demonstrates the use of the three representations of point geometry. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/point_geometry/point_geometry_device.cpp) + Motion Blur Geometry -------------------- -![][imgMotionBlurGeometry] +[![][imgMotionBlurGeometry]](https://github.com/embree/embree/blob/master/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp) This tutorial demonstrates rendering of motion blur using the multi-segment motion blur feature. Shown is motion blur of a triangle mesh, @@ -305,10 +339,12 @@ The number of time steps used can be configured using the `--time-steps geometry can be rendered at a specific time using the the `--time ` command line parameter. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp) + Quaternion Motion Blur ---------------------- -![][imgQuaternionMotionBlur] +[![][imgQuaternionMotionBlur]](https://github.com/embree/embree/blob/master/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp) This tutorial demonstrates rendering of motion blur using quaternion interpolation. Shown is motion blur using spherical linear interpolation of @@ -316,18 +352,21 @@ the rotational component of the instance transformation on the left and simple linear interpolation of the instance transformation on the right. The number of time steps can be modified as well. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp) Interpolation ------------- -![][imgInterpolation] +[![][imgInterpolation]](https://github.com/embree/embree/blob/master/tutorials/interpolation/interpolation_device.cpp) This tutorial demonstrates interpolation of user-defined per-vertex data. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/interpolation/interpolation_device.cpp) + Closest Point ---------------------- -![][imgClosestPoint] +[![][imgClosestPoint]](https://github.com/embree/embree/blob/master/tutorials/closest_point/closest_point_device.cpp) This tutorial demonstrates a use-case of the point query API. The scene consists of a simple collection of objects that are instanced and for several @@ -337,19 +376,23 @@ implemented for Embree internal and for user-defined instancing. The tutorial also illustrates how to handle instance transformations that are not similarity transforms. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/closest_point/closest_point_device.cpp) + Voronoi ---------------------- -![][imgVoronoi] +[![][imgVoronoi]](https://github.com/embree/embree/blob/master/tutorials/voronoi/voronoi_device.cpp) This tutorial demonstrates how to implement nearest neighbour lookups using the point query API. Several colored points are located on a plane and the corresponding voroni regions are illustrated. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/voronoi/voronoi_device.cpp) + Collision Detection ---------------------- -![][imgCollision] +[![][imgCollision]](https://github.com/embree/embree/blob/master/tutorials/collide/collide_device.cpp) This tutorial demonstrates how to implement collision detection using the collide API. A simple cloth solver is setup to collide with a sphere. @@ -357,6 +400,8 @@ the collide API. A simple cloth solver is setup to collide with a sphere. The cloth can be reset with the `space` bar. The sim stepped once with `n` and continuous simulation started and paused with `p`. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/collide/collide_device.cpp) + BVH Builder ----------- @@ -365,6 +410,8 @@ of Embree to build a bounding volume hierarchy with a user-defined memory layout using a high-quality SAH builder using spatial splits, a standard SAH builder, and a very fast Morton builder. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/bvh_builder/bvh_builder_device.cpp) + BVH Access ----------- @@ -372,6 +419,8 @@ This tutorial demonstrates how to access the internal triangle acceleration structure build by Embree. Please be aware that the internal Embree data structures might change between Embree updates. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/bvh_access/bvh_access.cpp) + Find Embree ----------- @@ -381,6 +430,8 @@ the Embree installation automatically, under Windows the `embree_DIR` CMake variable must be set to the following folder of the Embree installation: `C:\Program Files\Intel\Embree3`. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/find_embree/CMakeLists.txt) + Next Hit ----------- @@ -389,5 +440,7 @@ the ray using multiple ray queries and an intersection filter function. To improve performance, the tutorial also supports collecting the next N hits in a single ray query. +[Source Code](https://github.com/embree/embree/blob/master/tutorials/next_hit/next_hit_device.cpp) + diff --git a/include/embree3/rtcore.h b/include/embree3/rtcore.h index 5830bb5880..450ab4c535 100644 --- a/include/embree3/rtcore.h +++ b/include/embree3/rtcore.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/include/embree3/rtcore.isph b/include/embree3/rtcore.isph index 95bd203cea..c256cd42be 100644 --- a/include/embree3/rtcore.isph +++ b/include/embree3/rtcore.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __RTC_ISPH__ diff --git a/include/embree3/rtcore_buffer.h b/include/embree3/rtcore_buffer.h index 400b604aa5..6b8eba9769 100644 --- a/include/embree3/rtcore_buffer.h +++ b/include/embree3/rtcore_buffer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/include/embree3/rtcore_buffer.isph b/include/embree3/rtcore_buffer.isph index 54ba415a7e..b055eb7f72 100644 --- a/include/embree3/rtcore_buffer.isph +++ b/include/embree3/rtcore_buffer.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __RTC_BUFFER_ISPH__ diff --git a/include/embree3/rtcore_builder.h b/include/embree3/rtcore_builder.h index d62a7f72cc..4bff999fed 100644 --- a/include/embree3/rtcore_builder.h +++ b/include/embree3/rtcore_builder.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/include/embree3/rtcore_common.h b/include/embree3/rtcore_common.h index a516f6bdf1..894628e47c 100644 --- a/include/embree3/rtcore_common.h +++ b/include/embree3/rtcore_common.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -19,7 +19,7 @@ typedef int ssize_t; #endif #endif -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) # define RTC_ALIGN(...) __declspec(align(__VA_ARGS__)) #else # define RTC_ALIGN(...) __attribute__((aligned(__VA_ARGS__))) diff --git a/include/embree3/rtcore_common.isph b/include/embree3/rtcore_common.isph index 4e3a4341e6..8a19cba745 100644 --- a/include/embree3/rtcore_common.isph +++ b/include/embree3/rtcore_common.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __RTC_COMMON_ISPH__ diff --git a/include/embree3/rtcore_device.h b/include/embree3/rtcore_device.h index 2fdb95b98b..2dd3047603 100644 --- a/include/embree3/rtcore_device.h +++ b/include/embree3/rtcore_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -32,6 +32,7 @@ enum RTCDeviceProperty RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED = 34, RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED = 35, + RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED = 63, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED = 64, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED = 65, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66, diff --git a/include/embree3/rtcore_device.isph b/include/embree3/rtcore_device.isph index aead1555ed..7a760d0f20 100644 --- a/include/embree3/rtcore_device.isph +++ b/include/embree3/rtcore_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __RTC_DEVICE_ISPH__ @@ -31,6 +31,7 @@ enum RTCDeviceProperty RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED = 34, RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED = 35, + RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED = 63, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED = 64, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED = 65, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66, diff --git a/include/embree3/rtcore_geometry.h b/include/embree3/rtcore_geometry.h index 85b27be63a..d1de17491c 100644 --- a/include/embree3/rtcore_geometry.h +++ b/include/embree3/rtcore_geometry.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -23,6 +23,7 @@ enum RTCGeometryType RTC_GEOMETRY_TYPE_SUBDIVISION = 8, // Catmull-Clark subdivision surface + RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE = 15, // Cone linear curves - discontinuous at edge boundaries RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE = 16, // Round (rounded cone like) linear curves RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE = 17, // flat (ribbon-like) linear curves diff --git a/include/embree3/rtcore_geometry.isph b/include/embree3/rtcore_geometry.isph index 6359e55be9..565fed7fef 100644 --- a/include/embree3/rtcore_geometry.isph +++ b/include/embree3/rtcore_geometry.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __EMBREE_GEOMETRY_ISPH__ @@ -22,6 +22,7 @@ enum RTCGeometryType RTC_GEOMETRY_TYPE_SUBDIVISION = 8, // Catmull-Clark subdivision surface + RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE = 15, // Cone linear curves - discontinuous at edge boundaries RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE = 17, // flat (ribbon-like) linear curves RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE = 16, // Round (rounded cone like) linear curves @@ -63,7 +64,7 @@ enum RTCSubdivisionMode enum RTCCurveFlags { RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0), // left segment exists - RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1) // right segement exists + RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1) // right segment exists }; /* Arguments for RTCBoundsFunction */ diff --git a/include/embree3/rtcore_quaternion.h b/include/embree3/rtcore_quaternion.h index 449cdedfdc..bd5fe1d89a 100644 --- a/include/embree3/rtcore_quaternion.h +++ b/include/embree3/rtcore_quaternion.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,7 +8,7 @@ RTC_NAMESPACE_BEGIN /* - * Structure for transformation respresentation as a matrix decomposition using + * Structure for transformation representation as a matrix decomposition using * a quaternion */ struct RTC_ALIGN(16) RTCQuaternionDecomposition diff --git a/include/embree3/rtcore_quaternion.isph b/include/embree3/rtcore_quaternion.isph index c29a243da6..43748cbdc3 100644 --- a/include/embree3/rtcore_quaternion.isph +++ b/include/embree3/rtcore_quaternion.isph @@ -1,11 +1,11 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __EMBREE_QUATERNION_ISPH__ #define __EMBREE_QUATERNION_ISPH__ /* - * Structure for transformation respresentation as a matrix decomposition using + * Structure for transformation representation as a matrix decomposition using * a quaternion */ struct RTC_ALIGN(16) RTCQuaternionDecomposition diff --git a/include/embree3/rtcore_ray.h b/include/embree3/rtcore_ray.h index 1ae3309ef1..a2ee6dabbb 100644 --- a/include/embree3/rtcore_ray.h +++ b/include/embree3/rtcore_ray.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/include/embree3/rtcore_ray.isph b/include/embree3/rtcore_ray.isph index 3f1819c64b..70df021a3b 100644 --- a/include/embree3/rtcore_ray.isph +++ b/include/embree3/rtcore_ray.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __RTC_RAY_ISPH__ diff --git a/include/embree3/rtcore_scene.h b/include/embree3/rtcore_scene.h index 0cd6401593..34d87a2ce4 100644 --- a/include/embree3/rtcore_scene.h +++ b/include/embree3/rtcore_scene.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -47,9 +47,12 @@ RTC_API void rtcAttachGeometryByID(RTCScene scene, RTCGeometry geometry, unsigne /* Detaches the geometry from the scene. */ RTC_API void rtcDetachGeometry(RTCScene scene, unsigned int geomID); -/* Gets a geometry handle from the scene. */ +/* Gets a geometry handle from the scene. This function is not thread safe and should get used during rendering. */ RTC_API RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID); +/* Gets a geometry handle from the scene. This function is thread safe and should NOT get used during rendering. */ +RTC_API RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID); + /* Commits the scene. */ RTC_API void rtcCommitScene(RTCScene scene); diff --git a/include/embree3/rtcore_scene.isph b/include/embree3/rtcore_scene.isph index ae665e40b2..1405c16de8 100644 --- a/include/embree3/rtcore_scene.isph +++ b/include/embree3/rtcore_scene.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef __RTC_SCENE_ISPH__ @@ -39,9 +39,12 @@ RTC_API void rtcAttachGeometryByID(RTCScene scene, RTCGeometry geometry, uniform /* Detaches the geometry from the scene. */ RTC_API void rtcDetachGeometry(RTCScene scene, uniform unsigned int geomID); -/* Gets a geometry handle from the scene. */ +/* Gets a geometry handle from the scene. This function is not thread safe and should get used during rendering. */ RTC_API RTCGeometry rtcGetGeometry(RTCScene scene, uniform unsigned int geomID); +/* Gets a geometry handle from the scene. This function is thread safe and should NOT get used during rendering. */ +RTC_API RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, uniform unsigned int geomID); + /* Commits the scene. */ RTC_API void rtcCommitScene(RTCScene scene); @@ -139,7 +142,7 @@ RTC_API void rtcIntersectNM(RTCScene scene, uniform RTCIntersectContext* uniform /* Intersects a stream of M ray packets of native packet size with the scene. */ RTC_FORCEINLINE void rtcIntersectVM(RTCScene scene, uniform RTCIntersectContext* uniform context, varying RTCRayHit* uniform rayhit, uniform unsigned int M, uniform uintptr_t byteStride) { - rtcIntersectNM(scene, context, (struct RTCRayHitN*)rayhit, sizeof(varying float)/4, M, byteStride); + rtcIntersectNM(scene, context, (struct RTCRayHitN* uniform)rayhit, sizeof(varying float)/4, M, byteStride); } /* Intersects a stream of M ray packets of size N in SOA format with the scene. */ @@ -184,7 +187,7 @@ RTC_API void rtcOccludedNM(RTCScene scene, uniform RTCIntersectContext* uniform /* Tests a stream of M ray packets of native size in SOA format for occlusion with the scene. */ RTC_FORCEINLINE void rtcOccludedVM(RTCScene scene, uniform RTCIntersectContext* uniform context, varying RTCRay* uniform ray, uniform unsigned int M, uniform uintptr_t byteStride) { - rtcOccludedNM(scene, context, (struct RTCRayN*)ray, sizeof(varying float)/4, M, byteStride); + rtcOccludedNM(scene, context, (struct RTCRayN* uniform)ray, sizeof(varying float)/4, M, byteStride); } /* Tests a stream of M ray packets of size N in SOA format for occlusion with the scene. */ diff --git a/kernels/CMakeLists.txt b/kernels/CMakeLists.txt index d703c63e02..91056f605d 100644 --- a/kernels/CMakeLists.txt +++ b/kernels/CMakeLists.txt @@ -1,6 +1,10 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 +IF (EMBREE_CONFIG) + ADD_DEFINITIONS(-DEMBREE_CONFIG="${EMBREE_CONFIG}") +ENDIF() + MACRO(DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS) FOREACH(src ${ARGN}) IF (src MATCHES ".*intersector.*") @@ -19,7 +23,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") SOURCE_GROUP("" FILES embree.rc) SET(EMBREE_LIBRARY_FILES - + embree.rc common/device.cpp @@ -48,8 +52,12 @@ SET(EMBREE_LIBRARY_FILES geometry/primitive4.cpp geometry/instance_intersector.cpp - geometry/curve_intersector_virtual.cpp - geometry/curve_intersector_virtual2.cpp + geometry/curve_intersector_virtual_4v.cpp + geometry/curve_intersector_virtual_4i.cpp + geometry/curve_intersector_virtual_4i_mb.cpp + geometry/curve_intersector_virtual_8v.cpp + geometry/curve_intersector_virtual_8i.cpp + geometry/curve_intersector_virtual_8i_mb.cpp builders/primrefgen.cpp bvh/bvh.cpp @@ -78,7 +86,7 @@ IF (EMBREE_GEOMETRY_SUBDIVISION) subdiv/tessellation_cache.cpp subdiv/subdivpatch1base.cpp subdiv/catmullclark_coefficients.cpp - geometry/grid_soa.cpp + geometry/grid_soa.cpp subdiv/subdivpatch1base_eval.cpp bvh/bvh_builder_subdiv.cpp) ENDIF() @@ -92,24 +100,28 @@ IF (EMBREE_RAY_PACKETS) ENDIF() MACRO(embree_files TARGET ISA) - + SET(${TARGET} geometry/instance_intersector.cpp - geometry/curve_intersector_virtual.cpp - geometry/curve_intersector_virtual2.cpp + geometry/curve_intersector_virtual_4v.cpp + geometry/curve_intersector_virtual_4i.cpp + geometry/curve_intersector_virtual_4i_mb.cpp + geometry/curve_intersector_virtual_8v.cpp + geometry/curve_intersector_virtual_8i.cpp + geometry/curve_intersector_virtual_8i_mb.cpp bvh/bvh_intersector1_bvh4.cpp) IF (${ISA} EQUAL ${ISA_LOWEST_AVX}) LIST(APPEND ${TARGET} geometry/primitive8.cpp) - ENDIF() + ENDIF() + + IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512} OR ${ISA_LOWEST} EQUAL ${ISA}) - IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512KNL} OR ${ISA} EQUAL ${AVX512SKX} OR ${ISA_LOWEST} EQUAL ${ISA}) - LIST(APPEND ${TARGET} common/scene_user_geometry.cpp common/scene_instance.cpp common/scene_triangle_mesh.cpp - common/scene_quad_mesh.cpp + common/scene_quad_mesh.cpp common/scene_curves.cpp common/scene_line_segments.cpp common/scene_grid_mesh.cpp @@ -130,13 +142,13 @@ MACRO(embree_files TARGET ISA) ENDIF() ENDIF() - IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512KNL} OR ${ISA_LOWEST} EQUAL ${ISA}) + IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA_LOWEST} EQUAL ${ISA}) LIST(APPEND ${TARGET} bvh/bvh_builder_morton.cpp bvh/bvh_rotate.cpp builders/primrefgen.cpp) ENDIF() - + IF (${ISA} GREATER ${SSE42}) LIST(APPEND ${TARGET} bvh/bvh_intersector1_bvh8.cpp) ENDIF() @@ -153,7 +165,7 @@ MACRO(embree_files TARGET ISA) geometry/grid_soa.cpp subdiv/subdivpatch1base_eval.cpp) ENDIF() - + IF (EMBREE_RAY_PACKETS) LIST(APPEND ${TARGET} bvh/bvh_intersector_hybrid4_bvh4.cpp @@ -174,36 +186,34 @@ MACRO(embree_files TARGET ISA) bvh/bvh_intersector_hybrid16_bvh4.cpp) ENDIF() ENDIF() - + ENDMACRO() #embree_files(EMBREE_LIBRARY_FILES_SSE2 ${SSE2}) embree_files(EMBREE_LIBRARY_FILES_SSE42 ${SSE42}) embree_files(EMBREE_LIBRARY_FILES_AVX ${AVX}) embree_files(EMBREE_LIBRARY_FILES_AVX2 ${AVX2}) -embree_files(EMBREE_LIBRARY_FILES_AVX512KNL ${AVX512KNL}) -embree_files(EMBREE_LIBRARY_FILES_AVX512SKX ${AVX512SKX}) +embree_files(EMBREE_LIBRARY_FILES_AVX512 ${AVX512}) #message("SSE2: ${EMBREE_LIBRARY_FILES_SSE2}") #message("SSE42: ${EMBREE_LIBRARY_FILES_SSE42}") #message("AVX: ${EMBREE_LIBRARY_FILES_AVX}") #message("AVX2: ${EMBREE_LIBRARY_FILES_AVX2}") -#message("AVX512KNL: ${EMBREE_LIBRARY_FILES_AVX512KNL}") -#message("AVX512SKX: ${EMBREE_LIBRARY_FILES_AVX512SKX}") +#message("AVX512: ${EMBREE_LIBRARY_FILES_AVX512}") # replaces all .cpp files with a dummy file that includes that .cpp file # this is to work around an ICC name mangling issue related to lambda functions under windows MACRO (CreateISADummyFiles list isa) SET(${list}) FOREACH(src ${ARGN}) - SET(src_file ${CMAKE_CURRENT_SOURCE_DIR}/${src}) - SET(dst_file ${CMAKE_BINARY_DIR}/${src}.${isa}.cpp) + SET(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${src}") + SET(dst_file "${CMAKE_CURRENT_BINARY_DIR}/${src}.${isa}.cpp") SET(${list} ${${list}} ${dst_file}) ADD_CUSTOM_COMMAND(OUTPUT ${dst_file} - COMMAND ${CMAKE_COMMAND} + COMMAND ${CMAKE_COMMAND} -D src=${src_file} -D dst=${dst_file} - -P ${PROJECT_SOURCE_DIR}/common/cmake/create_isa_dummy_file.cmake + -P "${PROJECT_SOURCE_DIR}/common/cmake/create_isa_dummy_file.cmake" DEPENDS ${src_file}) ENDFOREACH() ENDMACRO() @@ -211,22 +221,21 @@ ENDMACRO() CreateISADummyFiles(EMBREE_LIBRARY_FILES_SSE42 sse42 ${EMBREE_LIBRARY_FILES_SSE42}) CreateISADummyFiles(EMBREE_LIBRARY_FILES_AVX avx ${EMBREE_LIBRARY_FILES_AVX}) CreateISADummyFiles(EMBREE_LIBRARY_FILES_AVX2 avx2 ${EMBREE_LIBRARY_FILES_AVX2}) -CreateISADummyFiles(EMBREE_LIBRARY_FILES_AVX512KNL avx512knl ${EMBREE_LIBRARY_FILES_AVX512KNL}) -CreateISADummyFiles(EMBREE_LIBRARY_FILES_AVX512SKX avx512skx ${EMBREE_LIBRARY_FILES_AVX512SKX}) +CreateISADummyFiles(EMBREE_LIBRARY_FILES_AVX512 avx512 ${EMBREE_LIBRARY_FILES_AVX512}) MACRO (CheckGlobals library) IF (NOT WIN32 AND NOT APPLE) - ADD_CUSTOM_TARGET(${library}_check_globals ALL COMMAND ${CMAKE_COMMAND} -D file=$ -P ${PROJECT_SOURCE_DIR}/common/cmake/check_globals.cmake DEPENDS ${library}) + ADD_CUSTOM_TARGET(${library}_check_globals ALL COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_globals.cmake" DEPENDS ${library}) ENDIF() ENDMACRO() DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES}) -ADD_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES} $) +ADD_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") SET_PROPERTY(TARGET embree PROPERTY FOLDER kernels) IF (NOT WIN32 AND NOT APPLE) - ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P ${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake DEPENDS embree) + ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) ENDIF() #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) @@ -236,7 +245,7 @@ ENDIF() # SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_sse2) # CheckGlobals(embree_sse2) #IF (EMBREE_STATIC_LIB) -# INSTALL(TARGETS embree_sse2 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) +# INSTALL(TARGETS embree_sse2 ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) # ENDIF() #ENDIF () @@ -247,10 +256,10 @@ IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42) SET_TARGET_PROPERTIES(embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") SET_PROPERTY(TARGET embree_sse42 PROPERTY FOLDER kernels) SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_sse42) - CheckGlobals(embree_sse42) + # CheckGlobals(embree_sse42) IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT embree_sse42-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_sse42-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() ENDIF () @@ -261,10 +270,10 @@ IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX) SET_TARGET_PROPERTIES(embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") SET_PROPERTY(TARGET embree_avx PROPERTY FOLDER kernels) SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx) - CheckGlobals(embree_avx) + # CheckGlobals(embree_avx) IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT embree_avx-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() ENDIF() @@ -275,10 +284,24 @@ IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2) SET_TARGET_PROPERTIES(embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") SET_PROPERTY(TARGET embree_avx2 PROPERTY FOLDER kernels) SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx2) - CheckGlobals(embree_avx2) + # CheckGlobals(embree_avx2) IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT embree_avx2-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + INSTALL(TARGETS embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx2-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() +ENDIF() + +IF (EMBREE_ISA_AVX512 AND EMBREE_LIBRARY_FILES_AVX512) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512}) + ADD_LIBRARY(embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) + TARGET_LINK_LIBRARIES(embree_avx512 PRIVATE tasking) + SET_TARGET_PROPERTIES(embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") + SET_PROPERTY(TARGET embree_avx512 PROPERTY FOLDER kernels) + SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512) + CheckGlobals(embree_avx512) + IF (EMBREE_STATIC_LIB) + INSTALL(TARGETS embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx512-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() ENDIF() @@ -289,7 +312,7 @@ IF (EMBREE_ISA_AVX512KNL AND EMBREE_LIBRARY_FILES_AVX512KNL) SET_TARGET_PROPERTIES(embree_avx512knl PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512KNL}") SET_PROPERTY(TARGET embree_avx512knl PROPERTY FOLDER kernels) SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512knl) - CheckGlobals(embree_avx512knl) + # CheckGlobals(embree_avx512knl) IF (EMBREE_STATIC_LIB) INSTALL(TARGETS embree_avx512knl EXPORT embree_avx512knl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) INSTALL(EXPORT embree_avx512knl-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) @@ -303,7 +326,7 @@ IF (EMBREE_ISA_AVX512SKX AND EMBREE_LIBRARY_FILES_AVX512SKX) SET_TARGET_PROPERTIES(embree_avx512skx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512SKX}") SET_PROPERTY(TARGET embree_avx512skx PROPERTY FOLDER kernels) SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512skx) - CheckGlobals(embree_avx512skx) + # CheckGlobals(embree_avx512skx) IF (EMBREE_STATIC_LIB) INSTALL(TARGETS embree_avx512skx EXPORT embree_avx512skx-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) INSTALL(EXPORT embree_avx512skx-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) @@ -316,7 +339,6 @@ target_include_directories(embree PUBLIC $ $) - # libtbb is located in same install folder as libembree IF(WIN32) ELSEIF(APPLE) @@ -327,34 +349,37 @@ ENDIF() IF (WIN32) ELSEIF (APPLE) - SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,${PROJECT_SOURCE_DIR}/kernels/export.macosx.map) - SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/kernels/export.macosx.map) + SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") + SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") ELSE() - SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,--version-script=${PROJECT_SOURCE_DIR}/kernels/export.linux.map) - SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/kernels/export.linux.map) + SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") + SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.linux.map") ENDIF() -IF (EMBREE_ZIP_MODE) - SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) -ELSE() - SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) -ENDIF() +# Wenzel, Sep 4, 2020 -- skip all of the installation instructions for Mitsuba +return() + +#IF (EMBREE_ZIP_MODE) +# SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) +#ELSE() +# SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) +#ENDIF() INSTALL(TARGETS embree EXPORT embree-targets - LIBRARY NAMELINK_SKIP DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib + LIBRARY NAMELINK_SKIP DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib # on Windows put the dlls into bin - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples # ... and the import lib into the devel package - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel ) # export Embree targets -INSTALL(EXPORT embree-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) +INSTALL(EXPORT embree-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) # installs libembree3.so link IF (NOT EMBREE_STATIC_LIB) INSTALL(TARGETS embree - LIBRARY NAMELINK_ONLY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + LIBRARY NAMELINK_ONLY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel ) ENDIF() diff --git a/kernels/builders/bvh_builder_hair.h b/kernels/builders/bvh_builder_hair.h index 755ce255fb..d83e8918a1 100644 --- a/kernels/builders/bvh_builder_hair.h +++ b/kernels/builders/bvh_builder_hair.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/builders/bvh_builder_morton.h b/kernels/builders/bvh_builder_morton.h index 92be2f7e65..cba32ca73c 100644 --- a/kernels/builders/bvh_builder_morton.h +++ b/kernels/builders/bvh_builder_morton.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -411,7 +411,7 @@ namespace embree ReductionTy bounds[MAX_BRANCHING_FACTOR]; if (current.size() > singleThreadThreshold) { - /*! parallel_for is faster than spawing sub-tasks */ + /*! parallel_for is faster than spawning sub-tasks */ parallel_for(size_t(0), numChildren, [&] (const range& r) { for (size_t i=r.begin(); i 1.01f/float(set.max_num_time_segments)) { const Split temporal_split = heuristicTemporalSplit.find(set,cfg.logBlockSize); @@ -374,7 +374,7 @@ namespace embree const size_t begin = set.begin(); const size_t end = set.end(); - const size_t center = (begin + end)/2; + const size_t center = (begin + end + 1) / 2; PrimInfoMB linfo = empty; for (size_t i=begin; i cfg.singleThreadThreshold)) { - /*! parallel_for is faster than spawing sub-tasks */ + /*! parallel_for is faster than spawning sub-tasks */ parallel_for(size_t(0), children.size(), [&] (const range& r) { for (size_t i=r.begin(); i cfg.singleThreadThreshold) { - /*! parallel_for is faster than spawing sub-tasks */ + /*! parallel_for is faster than spawning sub-tasks */ parallel_for(size_t(0), numChildren, [&] (const range& r) { // FIXME: no range here for (size_t i=r.begin(); i= 0 && (size_t)i[0] < num); assert(i[1] >= 0 && (size_t)i[1] < num); assert(i[2] >= 0 && (size_t)i[2] < num); - return Vec3ia(i); -#else + + // we clamp to handle corner cases that could calculate out of bounds bin return Vec3ia(clamp(i,vint4(0),vint4(num-1))); -#endif } /*! faster but unsafe binning */ @@ -444,482 +442,6 @@ namespace embree BBox _bounds[BINS][3]; //!< geometry bounds for each bin in each dimension vuint4 _counts[BINS]; //!< counts number of primitives that map into the bins }; - -#if defined(__AVX512ER__) // KNL - - /*! mapping into bins */ - template<> - struct BinMapping<16> - { - public: - __forceinline BinMapping() {} - - /*! calculates the mapping */ - template - __forceinline BinMapping(const PrimInfo& pinfo) - { - num = 16; - const vfloat4 eps = 1E-34f; - const vfloat4 diag = max(eps,(vfloat4) pinfo.centBounds.size()); - scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f)); - ofs = (vfloat4) pinfo.centBounds.lower; - scale16 = scale; - ofs16 = ofs; - } - - /*! returns number of bins */ - __forceinline size_t size() const { return num; } - - __forceinline vint16 bin16(const Vec3fa& p) const { - return vint16(vint4(floori((vfloat4(p)-ofs)*scale))); - } - - __forceinline vint16 bin16(const vfloat16& p) const { - return floori((p-ofs16)*scale16); - } - - __forceinline int bin_unsafe(const PrimRef& ref, - const vint16& vSplitPos, - const vbool16& splitDimMask) const // FIXME: rename to isLeft - { - const vfloat16 lower(*(vfloat4*)&ref.lower); - const vfloat16 upper(*(vfloat4*)&ref.upper); - const vfloat16 p = lower + upper; - const vint16 i = floori((p-ofs16)*scale16); - return lt(splitDimMask,i,vSplitPos); - } - - /*! returns true if the mapping is invalid in some dimension */ - __forceinline bool invalid(const size_t dim) const { - return scale[dim] == 0.0f; - } - - public: - size_t num; - vfloat4 ofs,scale; //!< linear function that maps to bin ID - vfloat16 ofs16,scale16; //!< linear function that maps to bin ID - }; - - /* 16 bins in-register binner */ - template - struct __aligned(64) BinInfoT<16,PrimRef,BBox3fa> - { - typedef BinSplit<16> Split; - typedef vbool16 vbool; - typedef vint16 vint; - typedef vfloat16 vfloat; - - __forceinline BinInfoT() { - } - - __forceinline BinInfoT(EmptyTy) { - clear(); - } - - /*! clears the bin info */ - __forceinline void clear() - { - lower[0] = lower[1] = lower[2] = pos_inf; - upper[0] = upper[1] = upper[2] = neg_inf; - count[0] = count[1] = count[2] = 0; - } - - - static __forceinline vfloat16 prefix_area_rl(const vfloat16 min_x, - const vfloat16 min_y, - const vfloat16 min_z, - const vfloat16 max_x, - const vfloat16 max_y, - const vfloat16 max_z) - { - const vfloat16 r_min_x = reverse_prefix_min(min_x); - const vfloat16 r_min_y = reverse_prefix_min(min_y); - const vfloat16 r_min_z = reverse_prefix_min(min_z); - const vfloat16 r_max_x = reverse_prefix_max(max_x); - const vfloat16 r_max_y = reverse_prefix_max(max_y); - const vfloat16 r_max_z = reverse_prefix_max(max_z); - const vfloat16 dx = r_max_x - r_min_x; - const vfloat16 dy = r_max_y - r_min_y; - const vfloat16 dz = r_max_z - r_min_z; - const vfloat16 area_rl = madd(dx,dy,madd(dx,dz,dy*dz)); - return area_rl; - } - - static __forceinline vfloat16 prefix_area_lr(const vfloat16 min_x, - const vfloat16 min_y, - const vfloat16 min_z, - const vfloat16 max_x, - const vfloat16 max_y, - const vfloat16 max_z) - { - const vfloat16 r_min_x = prefix_min(min_x); - const vfloat16 r_min_y = prefix_min(min_y); - const vfloat16 r_min_z = prefix_min(min_z); - const vfloat16 r_max_x = prefix_max(max_x); - const vfloat16 r_max_y = prefix_max(max_y); - const vfloat16 r_max_z = prefix_max(max_z); - const vfloat16 dx = r_max_x - r_min_x; - const vfloat16 dy = r_max_y - r_min_y; - const vfloat16 dz = r_max_z - r_min_z; - const vfloat16 area_lr = madd(dx,dy,madd(dx,dz,dy*dz)); - return area_lr; - } - - - /*! bins an array of primitives */ - __forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<16>& mapping) - { - if (unlikely(N == 0)) return; - - const vfloat16 init_min(pos_inf); - const vfloat16 init_max(neg_inf); - - vfloat16 min_x0,min_x1,min_x2; - vfloat16 min_y0,min_y1,min_y2; - vfloat16 min_z0,min_z1,min_z2; - vfloat16 max_x0,max_x1,max_x2; - vfloat16 max_y0,max_y1,max_y2; - vfloat16 max_z0,max_z1,max_z2; - vuint16 count0,count1,count2; - - min_x0 = init_min; - min_x1 = init_min; - min_x2 = init_min; - min_y0 = init_min; - min_y1 = init_min; - min_y2 = init_min; - min_z0 = init_min; - min_z1 = init_min; - min_z2 = init_min; - - max_x0 = init_max; - max_x1 = init_max; - max_x2 = init_max; - max_y0 = init_max; - max_y1 = init_max; - max_y2 = init_max; - max_z0 = init_max; - max_z1 = init_max; - max_z2 = init_max; - - count0 = zero; - count1 = zero; - count2 = zero; - - const vint16 step16(step); - size_t i; - for (i=0; i(binA); - const vint16 bin1 = shuffle<1>(binA); - const vint16 bin2 = shuffle<2>(binA); - - const vbool16 m_update_x = step16 == bin0; - const vbool16 m_update_y = step16 == bin1; - const vbool16 m_update_z = step16 == bin2; - - assert(popcnt((size_t)m_update_x) == 1); - assert(popcnt((size_t)m_update_y) == 1); - assert(popcnt((size_t)m_update_z) == 1); - - min_x0 = mask_min(m_update_x,min_x0,min_x0,b_min_x); - min_y0 = mask_min(m_update_x,min_y0,min_y0,b_min_y); - min_z0 = mask_min(m_update_x,min_z0,min_z0,b_min_z); - // ------------------------------------------------------------------------ - max_x0 = mask_max(m_update_x,max_x0,max_x0,b_max_x); - max_y0 = mask_max(m_update_x,max_y0,max_y0,b_max_y); - max_z0 = mask_max(m_update_x,max_z0,max_z0,b_max_z); - // ------------------------------------------------------------------------ - min_x1 = mask_min(m_update_y,min_x1,min_x1,b_min_x); - min_y1 = mask_min(m_update_y,min_y1,min_y1,b_min_y); - min_z1 = mask_min(m_update_y,min_z1,min_z1,b_min_z); - // ------------------------------------------------------------------------ - max_x1 = mask_max(m_update_y,max_x1,max_x1,b_max_x); - max_y1 = mask_max(m_update_y,max_y1,max_y1,b_max_y); - max_z1 = mask_max(m_update_y,max_z1,max_z1,b_max_z); - // ------------------------------------------------------------------------ - min_x2 = mask_min(m_update_z,min_x2,min_x2,b_min_x); - min_y2 = mask_min(m_update_z,min_y2,min_y2,b_min_y); - min_z2 = mask_min(m_update_z,min_z2,min_z2,b_min_z); - // ------------------------------------------------------------------------ - max_x2 = mask_max(m_update_z,max_x2,max_x2,b_max_x); - max_y2 = mask_max(m_update_z,max_y2,max_y2,b_max_y); - max_z2 = mask_max(m_update_z,max_z2,max_z2,b_max_z); - // ------------------------------------------------------------------------ - count0 = mask_add(m_update_x,count0,count0,vuint16(1)); - count1 = mask_add(m_update_y,count1,count1,vuint16(1)); - count2 = mask_add(m_update_z,count2,count2,vuint16(1)); - } - - - /* B */ - { - const vfloat16 b_min_x = prims[i+1].lower.x; - const vfloat16 b_min_y = prims[i+1].lower.y; - const vfloat16 b_min_z = prims[i+1].lower.z; - const vfloat16 b_max_x = prims[i+1].upper.x; - const vfloat16 b_max_y = prims[i+1].upper.y; - const vfloat16 b_max_z = prims[i+1].upper.z; - - const vint16 bin0 = shuffle<0>(binB); - const vint16 bin1 = shuffle<1>(binB); - const vint16 bin2 = shuffle<2>(binB); - - const vbool16 m_update_x = step16 == bin0; - const vbool16 m_update_y = step16 == bin1; - const vbool16 m_update_z = step16 == bin2; - - assert(popcnt((size_t)m_update_x) == 1); - assert(popcnt((size_t)m_update_y) == 1); - assert(popcnt((size_t)m_update_z) == 1); - - min_x0 = mask_min(m_update_x,min_x0,min_x0,b_min_x); - min_y0 = mask_min(m_update_x,min_y0,min_y0,b_min_y); - min_z0 = mask_min(m_update_x,min_z0,min_z0,b_min_z); - // ------------------------------------------------------------------------ - max_x0 = mask_max(m_update_x,max_x0,max_x0,b_max_x); - max_y0 = mask_max(m_update_x,max_y0,max_y0,b_max_y); - max_z0 = mask_max(m_update_x,max_z0,max_z0,b_max_z); - // ------------------------------------------------------------------------ - min_x1 = mask_min(m_update_y,min_x1,min_x1,b_min_x); - min_y1 = mask_min(m_update_y,min_y1,min_y1,b_min_y); - min_z1 = mask_min(m_update_y,min_z1,min_z1,b_min_z); - // ------------------------------------------------------------------------ - max_x1 = mask_max(m_update_y,max_x1,max_x1,b_max_x); - max_y1 = mask_max(m_update_y,max_y1,max_y1,b_max_y); - max_z1 = mask_max(m_update_y,max_z1,max_z1,b_max_z); - // ------------------------------------------------------------------------ - min_x2 = mask_min(m_update_z,min_x2,min_x2,b_min_x); - min_y2 = mask_min(m_update_z,min_y2,min_y2,b_min_y); - min_z2 = mask_min(m_update_z,min_z2,min_z2,b_min_z); - // ------------------------------------------------------------------------ - max_x2 = mask_max(m_update_z,max_x2,max_x2,b_max_x); - max_y2 = mask_max(m_update_z,max_y2,max_y2,b_max_y); - max_z2 = mask_max(m_update_z,max_z2,max_z2,b_max_z); - // ------------------------------------------------------------------------ - count0 = mask_add(m_update_x,count0,count0,vuint16(1)); - count1 = mask_add(m_update_y,count1,count1,vuint16(1)); - count2 = mask_add(m_update_z,count2,count2,vuint16(1)); - } - - } - - if (i < N) - { - const BBox3fa prim0 = prims[i].bounds(); - const vfloat16 center0 = vfloat16((vfloat4)prim0.lower) + vfloat16((vfloat4)prim0.upper); - const vint16 bin = mapping.bin16(center0); - - const vfloat16 b_min_x = prims[i].lower.x; - const vfloat16 b_min_y = prims[i].lower.y; - const vfloat16 b_min_z = prims[i].lower.z; - const vfloat16 b_max_x = prims[i].upper.x; - const vfloat16 b_max_y = prims[i].upper.y; - const vfloat16 b_max_z = prims[i].upper.z; - - const vint16 bin0 = shuffle<0>(bin); - const vint16 bin1 = shuffle<1>(bin); - const vint16 bin2 = shuffle<2>(bin); - - const vbool16 m_update_x = step16 == bin0; - const vbool16 m_update_y = step16 == bin1; - const vbool16 m_update_z = step16 == bin2; - - assert(popcnt((size_t)m_update_x) == 1); - assert(popcnt((size_t)m_update_y) == 1); - assert(popcnt((size_t)m_update_z) == 1); - - min_x0 = mask_min(m_update_x,min_x0,min_x0,b_min_x); - min_y0 = mask_min(m_update_x,min_y0,min_y0,b_min_y); - min_z0 = mask_min(m_update_x,min_z0,min_z0,b_min_z); - // ------------------------------------------------------------------------ - max_x0 = mask_max(m_update_x,max_x0,max_x0,b_max_x); - max_y0 = mask_max(m_update_x,max_y0,max_y0,b_max_y); - max_z0 = mask_max(m_update_x,max_z0,max_z0,b_max_z); - // ------------------------------------------------------------------------ - min_x1 = mask_min(m_update_y,min_x1,min_x1,b_min_x); - min_y1 = mask_min(m_update_y,min_y1,min_y1,b_min_y); - min_z1 = mask_min(m_update_y,min_z1,min_z1,b_min_z); - // ------------------------------------------------------------------------ - max_x1 = mask_max(m_update_y,max_x1,max_x1,b_max_x); - max_y1 = mask_max(m_update_y,max_y1,max_y1,b_max_y); - max_z1 = mask_max(m_update_y,max_z1,max_z1,b_max_z); - // ------------------------------------------------------------------------ - min_x2 = mask_min(m_update_z,min_x2,min_x2,b_min_x); - min_y2 = mask_min(m_update_z,min_y2,min_y2,b_min_y); - min_z2 = mask_min(m_update_z,min_z2,min_z2,b_min_z); - // ------------------------------------------------------------------------ - max_x2 = mask_max(m_update_z,max_x2,max_x2,b_max_x); - max_y2 = mask_max(m_update_z,max_y2,max_y2,b_max_y); - max_z2 = mask_max(m_update_z,max_z2,max_z2,b_max_z); - // ------------------------------------------------------------------------ - count0 = mask_add(m_update_x,count0,count0,vuint16(1)); - count1 = mask_add(m_update_y,count1,count1,vuint16(1)); - count2 = mask_add(m_update_z,count2,count2,vuint16(1)); - } - - lower[0] = Vec3vf16( min_x0, min_y0, min_z0 ); - lower[1] = Vec3vf16( min_x1, min_y1, min_z1 ); - lower[2] = Vec3vf16( min_x2, min_y2, min_z2 ); - - upper[0] = Vec3vf16( max_x0, max_y0, max_z0 ); - upper[1] = Vec3vf16( max_x1, max_y1, max_z1 ); - upper[2] = Vec3vf16( max_x2, max_y2, max_z2 ); - - count[0] = count0; - count[1] = count1; - count[2] = count2; - } - - __forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<16>& mapping) { - bin(prims+begin,end-begin,mapping); - } - - /*! merges in other binning information */ - __forceinline void merge (const BinInfoT& other, size_t numBins) - { - for (size_t i=0; i<3; i++) - { - lower[i] = min(lower[i],other.lower[i]); - upper[i] = max(upper[i],other.upper[i]); - count[i] += other.count[i]; - } - } - - /*! reducesr binning information */ - static __forceinline const BinInfoT reduce (const BinInfoT& a, const BinInfoT& b) - { - BinInfoT c; - for (size_t i=0; i<3; i++) - { - c.counts[i] = a.counts[i] + b.counts[i]; - c.lower[i] = min(a.lower[i],b.lower[i]); - c.upper[i] = max(a.upper[i],b.upper[i]); - } - return c; - } - - /*! finds the best split by scanning binning information */ - __forceinline Split best(const BinMapping<16>& mapping, const size_t blocks_shift) const - { - /* find best dimension */ - float bestSAH = inf; - int bestDim = -1; - int bestPos = 0; - const vuint16 blocks_add = (1 << blocks_shift)-1; - const vfloat16 inf(pos_inf); - for (size_t dim=0; dim<3; dim++) - { - /* ignore zero sized dimensions */ - if (unlikely(mapping.invalid(dim))) - continue; - - const vfloat16 rArea16 = prefix_area_rl(lower[dim].x,lower[dim].y,lower[dim].z, upper[dim].x,upper[dim].y,upper[dim].z); - const vfloat16 lArea16 = prefix_area_lr(lower[dim].x,lower[dim].y,lower[dim].z, upper[dim].x,upper[dim].y,upper[dim].z); - const vuint16 lCount16 = prefix_sum(count[dim]); - const vuint16 rCount16 = reverse_prefix_sum(count[dim]); - - /* compute best split in this dimension */ - const vfloat16 leftArea = lArea16; - const vfloat16 rightArea = align_shift_right<1>(zero,rArea16); - const vuint16 lC = lCount16; - const vuint16 rC = align_shift_right<1>(zero,rCount16); - const vuint16 leftCount = ( lC + blocks_add) >> blocks_shift; - const vuint16 rightCount = ( rC + blocks_add) >> blocks_shift; - const vbool16 valid = (leftArea < inf) & (rightArea < inf) & vbool16(0x7fff); // handles inf entries - const vfloat16 sah = select(valid,madd(leftArea,vfloat16(leftCount),rightArea*vfloat16(rightCount)),vfloat16(pos_inf)); - /* test if this is a better dimension */ - if (any(sah < vfloat16(bestSAH))) - { - const size_t index = select_min(sah); - assert(index < 15); - assert(sah[index] < bestSAH); - bestDim = dim; - bestPos = index+1; - bestSAH = sah[index]; - } - } - - return Split(bestSAH,bestDim,bestPos,mapping); - - } - - /*! calculates extended split information */ - __forceinline void getSplitInfo(const BinMapping<16>& mapping, const Split& split, SplitInfo& info) const - { - if (split.dim == -1) { - new (&info) SplitInfo(0,empty,0,empty); - return; - } - // FIXME: horizontal reduction! - - size_t leftCount = 0; - BBox3fa leftBounds = empty; - for (size_t i=0; i<(size_t)split.pos; i++) { - leftCount += count[split.dim][i]; - Vec3fa bounds_lower(lower[split.dim].x[i],lower[split.dim].y[i],lower[split.dim].z[i]); - Vec3fa bounds_upper(upper[split.dim].x[i],upper[split.dim].y[i],upper[split.dim].z[i]); - leftBounds.extend(BBox3fa(bounds_lower,bounds_upper)); - } - size_t rightCount = 0; - BBox3fa rightBounds = empty; - for (size_t i=split.pos; i& mapping, const Split& split) const - { - if (unlikely(split.dim == -1)) return -1; - - size_t leftCount = 0; - for (size_t i = 0; i < (size_t)split.pos; i++) { - leftCount += count[split.dim][i]; - } - return leftCount; - } - - /*! gets the number of primitives right of the split */ - __forceinline size_t getRightCount(const BinMapping<16>& mapping, const Split& split) const - { - if (unlikely(split.dim == -1)) return -1; - - size_t rightCount = 0; - for (size_t i = (size_t)split.pos; i diff --git a/kernels/builders/heuristic_binning_array_aligned.h b/kernels/builders/heuristic_binning_array_aligned.h index a4c272f015..ab3b97efb9 100644 --- a/kernels/builders/heuristic_binning_array_aligned.h +++ b/kernels/builders/heuristic_binning_array_aligned.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -40,15 +40,10 @@ namespace embree typedef BinInfoT Binner; typedef range Set; -#if defined(__AVX512ER__) // KNL - static const size_t PARALLEL_THRESHOLD = 4*768; - static const size_t PARALLEL_FIND_BLOCK_SIZE = 768; - static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 768; -#else static const size_t PARALLEL_THRESHOLD = 3 * 1024; static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024; static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128; -#endif + __forceinline HeuristicArrayBinningSAH () : prims(nullptr) {} diff --git a/kernels/builders/heuristic_binning_array_unaligned.h b/kernels/builders/heuristic_binning_array_unaligned.h index 1370244586..34a7f121bb 100644 --- a/kernels/builders/heuristic_binning_array_unaligned.h +++ b/kernels/builders/heuristic_binning_array_unaligned.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/builders/heuristic_openmerge_array.h b/kernels/builders/heuristic_openmerge_array.h index 21f18c0208..354e283557 100644 --- a/kernels/builders/heuristic_openmerge_array.h +++ b/kernels/builders/heuristic_openmerge_array.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // TODO: @@ -275,7 +275,7 @@ namespace embree openNodesBasedOnExtend(set); #endif - /* disable opening when unsufficient space for opening a node available */ + /* disable opening when insufficient space for opening a node available */ if (set.ext_range_size() < max_open_size-1) set.set_ext_range(set.end()); /* disable opening */ } diff --git a/kernels/builders/heuristic_spatial.h b/kernels/builders/heuristic_spatial.h index d8ca6cb92c..8b3499ac8d 100644 --- a/kernels/builders/heuristic_spatial.h +++ b/kernels/builders/heuristic_spatial.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -159,27 +159,25 @@ namespace embree assert(binID < BINS); bounds [binID][dim].extend(b); } - - /*! bins an array of triangles */ - template - __forceinline void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t N, const SpatialBinMapping& mapping) + + /*! bins an array of primitives */ + template + __forceinline void bin2(const PrimitiveSplitterFactory& splitterFactory, const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping& mapping) { - for (size_t i=0; i> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS); - - if (unlikely(splits == 1)) + + if (unlikely(splits <= 1)) { const vint4 bin = mapping.bin(center(prim.bounds())); for (size_t dim=0; dim<3; dim++) { assert(bin[dim] >= (int)0 && bin[dim] < (int)BINS); - numBegin[bin[dim]][dim]++; - numEnd [bin[dim]][dim]++; - bounds [bin[dim]][dim].extend(prim.bounds()); + add(dim,bin[dim],bin[dim],bin[dim],prim.bounds()); } - } + } else { const vint4 bin0 = mapping.bin(prim.bounds().lower); @@ -187,89 +185,44 @@ namespace embree for (size_t dim=0; dim<3; dim++) { + if (unlikely(mapping.invalid(dim))) + continue; + size_t bin; - PrimRef rest = prim; size_t l = bin0[dim]; size_t r = bin1[dim]; - + // same bin optimization if (likely(l == r)) { - numBegin[l][dim]++; - numEnd [l][dim]++; - bounds [l][dim].extend(prim.bounds()); + add(dim,l,l,l,prim.bounds()); continue; } - - for (bin=(size_t)bin0[dim]; bin<(size_t)bin1[dim]; bin++) + size_t bin_start = bin0[dim]; + size_t bin_end = bin1[dim]; + BBox3fa rest = prim.bounds(); + + /* assure that split position always overlaps the primitive bounds */ + while (bin_start < bin_end && mapping.pos(bin_start+1,dim) <= rest.lower[dim]) bin_start++; + while (bin_start < bin_end && mapping.pos(bin_end ,dim) >= rest.upper[dim]) bin_end--; + + const auto splitter = splitterFactory(prim); + for (bin=bin_start; bin - void bin(const SplitPrimitive& splitPrimitive, const PrimRef* prims, size_t begin, size_t end, const SpatialBinMapping& mapping) { - bin(splitPrimitive,prims+begin,end-begin,mapping); - } - - /*! bins an array of primitives */ - template - __forceinline void bin2(const PrimitiveSplitterFactory& splitterFactory, const PrimRef* source, size_t begin, size_t end, const SpatialBinMapping& mapping) - { - for (size_t i=begin; i Set; typedef Split2 Split; -#if defined(__AVX512ER__) // KNL - static const size_t PARALLEL_THRESHOLD = 3*1024; - static const size_t PARALLEL_FIND_BLOCK_SIZE = 768; - static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128; -#else static const size_t PARALLEL_THRESHOLD = 3*1024; static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024; static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128; -#endif static const size_t MOVE_STEP_SIZE = 64; static const size_t CREATE_SPLITS_STEP_SIZE = 64; @@ -247,7 +241,7 @@ namespace embree SpatialBinner binner(empty); const SpatialBinMapping mapping(set); binner.bin2(splitterFactory,prims0,set.begin(),set.end(),mapping); - /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/ + /* todo: best spatial split not exceeding the extended range does not provide any benefit ?*/ return binner.best(mapping,logBlockSize); //,set.ext_size()); } @@ -262,7 +256,7 @@ namespace embree binner.bin2(splitterFactory,prims0,r.begin(),r.end(),_mapping); return binner; }, [&] (const SpatialBinner& b0, const SpatialBinner& b1) -> SpatialBinner { return SpatialBinner::reduce(b0,b1); }); - /* todo: best spatial split not exeeding the extended range does not provide any benefit ?*/ + /* todo: best spatial split not exceeding the extended range does not provide any benefit ?*/ return binner.best(mapping,logBlockSize); //,set.ext_size()); } @@ -292,6 +286,7 @@ namespace embree //int bin0 = split.mapping.bin(prims0[i].lower)[split.dim]; //int bin1 = split.mapping.bin(prims0[i].upper)[split.dim]; //if (unlikely(bin0 < split.pos && bin1 >= split.pos)) + if (unlikely(prims0[i].lower[split.dim] < fpos && prims0[i].upper[split.dim] > fpos)) { assert(splits > 1); @@ -390,8 +385,8 @@ namespace embree new (&lset) PrimInfoExtRange(begin,center,center,local_left); new (&rset) PrimInfoExtRange(center,end,end,local_right); - assert(area(lset.geomBounds) >= 0.0f); - assert(area(rset.geomBounds) >= 0.0f); + assert(!lset.geomBounds.empty() && area(lset.geomBounds) >= 0.0f); + assert(!rset.geomBounds.empty() && area(rset.geomBounds) >= 0.0f); return std::pair(left_weight,right_weight); } @@ -416,7 +411,7 @@ namespace embree begin,end,local_left,local_right, [&] (const PrimRef& ref) { const Vec3fa c = ref.bounds().center(); - return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask); + return any(((vint4)mapping.bin(c) < vSplitPos) & vSplitMask); }, [] (PrimInfo& pinfo,const PrimRef& ref) { pinfo.add_center2(ref,ref.lower.u >> (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)); }); @@ -425,8 +420,8 @@ namespace embree new (&lset) PrimInfoExtRange(begin,center,center,local_left); new (&rset) PrimInfoExtRange(center,end,end,local_right); - assert(area(lset.geomBounds) >= 0.0f); - assert(area(rset.geomBounds) >= 0.0f); + assert(!lset.geomBounds.empty() && area(lset.geomBounds) >= 0.0f); + assert(!rset.geomBounds.empty() && area(rset.geomBounds) >= 0.0f); return std::pair(left_weight,right_weight); } diff --git a/kernels/builders/heuristic_strand_array.h b/kernels/builders/heuristic_strand_array.h index ede0d04c78..19c7fcdaa8 100644 --- a/kernels/builders/heuristic_strand_array.h +++ b/kernels/builders/heuristic_strand_array.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/builders/heuristic_timesplit_array.h b/kernels/builders/heuristic_timesplit_array.h index c999941a11..b968e01c90 100644 --- a/kernels/builders/heuristic_timesplit_array.h +++ b/kernels/builders/heuristic_timesplit_array.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/builders/priminfo.h b/kernels/builders/priminfo.h index 06c1388742..fee515247a 100644 --- a/kernels/builders/priminfo.h +++ b/kernels/builders/priminfo.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/builders/primrefgen.cpp b/kernels/builders/primrefgen.cpp index 11d5ecd92e..e2d7c27bd8 100644 --- a/kernels/builders/primrefgen.cpp +++ b/kernels/builders/primrefgen.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "primrefgen.h" @@ -11,7 +11,7 @@ namespace embree { namespace isa { - PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, mvector& prims, BuildProgressMonitor& progressMonitor) + PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, const size_t numPrimRefs, mvector& prims, BuildProgressMonitor& progressMonitor) { ParallelPrefixSumState pstate; @@ -22,7 +22,7 @@ namespace embree }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); /* if we need to filter out geometry, run again */ - if (pinfo.size() != prims.size()) + if (pinfo.size() != numPrimRefs) { progressMonitor(0); pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range& r, const PrimInfo& base) -> PrimInfo { @@ -32,7 +32,7 @@ namespace embree return pinfo; } - PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, mvector& prims, BuildProgressMonitor& progressMonitor) + PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector& prims, BuildProgressMonitor& progressMonitor) { ParallelForForPrefixSumState pstate; Scene::Iterator2 iter(scene,types,mblur); @@ -45,7 +45,7 @@ namespace embree }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); /* if we need to filter out geometry, run again */ - if (pinfo.size() != prims.size()) + if (pinfo.size() != numPrimRefs) { progressMonitor(0); pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo { @@ -55,7 +55,7 @@ namespace embree return pinfo; } - PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, mvector& prims, BuildProgressMonitor& progressMonitor, size_t itime) + PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector& prims, BuildProgressMonitor& progressMonitor, size_t itime) { ParallelForForPrefixSumState pstate; Scene::Iterator2 iter(scene,types,true); @@ -68,7 +68,7 @@ namespace embree }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); /* if we need to filter out geometry, run again */ - if (pinfo.size() != prims.size()) + if (pinfo.size() != numPrimRefs) { progressMonitor(0); pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo { @@ -78,7 +78,7 @@ namespace embree return pinfo; } - PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, mvector& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1) + PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1) { ParallelForForPrefixSumState pstate; Scene::Iterator2 iter(scene,types,true); @@ -91,7 +91,7 @@ namespace embree }, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); }); /* if we need to filter out geometry, run again */ - if (pinfo.size() != prims.size()) + if (pinfo.size() != numPrimRefs) { progressMonitor(0); pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB { @@ -182,56 +182,120 @@ namespace embree // ==================================================================================================== // ==================================================================================================== - // template for grid meshes + // special variants for grid meshes -#if 0 - template<> - PrimInfo createPrimRefArray(Scene* scene, mvector& prims, BuildProgressMonitor& progressMonitor) +#if defined(EMBREE_GEOMETRY_GRID) + PrimInfo createPrimRefArrayGrids(Scene* scene, mvector& prims, mvector& sgrids) { - PING; + PrimInfo pinfo(empty); + size_t numPrimitives = 0; + + /* first run to get #primitives */ + ParallelForForPrefixSumState pstate; Scene::Iterator iter(scene); - - /* first try */ - progressMonitor(0); + pstate.init(iter,size_t(1024)); - PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k) -> PrimInfo - { - PrimInfo pinfo(empty); - for (size_t j=r.begin(); jbuildBounds(j,&bounds)) continue; - const PrimRef prim(bounds,mesh->geomID,unsigned(j)); - pinfo.add_center2(prim); - prims[k++] = prim; - } - return pinfo; - }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); - - /* if we need to filter out geometry, run again */ - if (pinfo.size() != prims.size()) - { - progressMonitor(0); - pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, const PrimInfo& base) -> PrimInfo - { - k = base.size(); + + /* iterate over all meshes in the scene */ + pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID) -> PrimInfo { PrimInfo pinfo(empty); for (size_t j=r.begin(); jvalid(j)) continue; BBox3fa bounds = empty; - if (!mesh->buildBounds(j,&bounds)) continue; - const PrimRef prim(bounds,mesh->geomID,unsigned(j)); - pinfo.add_center2(prim); - prims[k++] = prim; + const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j); + if (!mesh->valid(j)) continue; + pinfo.add_center2(prim,mesh->getNumSubGrids(j)); } return pinfo; }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); - } + numPrimitives = pinfo.size(); + + /* resize arrays */ + sgrids.resize(numPrimitives); + prims.resize(numPrimitives); + + /* second run to fill primrefs and SubGridBuildData arrays */ + pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo { + k = base.size(); + size_t p_index = k; + PrimInfo pinfo(empty); + for (size_t j=r.begin(); jvalid(j)) continue; + const GridMesh::Grid &g = mesh->grid(j); + for (unsigned int y=0; ybuildBounds(g,x,y,bounds)) continue; // get bounds of subgrid + const PrimRef prim(bounds,(unsigned)geomID,(unsigned)p_index); + pinfo.add_center2(prim); + sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j)); + prims[p_index++] = prim; + } + } + return pinfo; + }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); + assert(pinfo.size() == numPrimitives); return pinfo; } -#endif + PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector& prims, mvector& sgrids) + { + unsigned int geomID_ = std::numeric_limits::max (); + + PrimInfo pinfo(empty); + size_t numPrimitives = 0; + + ParallelPrefixSumState pstate; + /* iterate over all grids in a single mesh */ + pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range& r, const PrimInfo& base) -> PrimInfo + { + PrimInfo pinfo(empty); + for (size_t j=r.begin(); jvalid(j)) continue; + BBox3fa bounds = empty; + const PrimRef prim(bounds,geomID_,unsigned(j)); + pinfo.add_center2(prim,mesh->getNumSubGrids(j)); + } + return pinfo; + }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); + numPrimitives = pinfo.size(); + /* resize arrays */ + sgrids.resize(numPrimitives); + prims.resize(numPrimitives); + + /* second run to fill primrefs and SubGridBuildData arrays */ + pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range& r, const PrimInfo& base) -> PrimInfo + { + + size_t p_index = base.size(); + PrimInfo pinfo(empty); + for (size_t j=r.begin(); jvalid(j)) continue; + const GridMesh::Grid &g = mesh->grid(j); + for (unsigned int y=0; ybuildBounds(g,x,y,bounds)) continue; // get bounds of subgrid + const PrimRef prim(bounds,geomID_,unsigned(p_index)); + pinfo.add_center2(prim); + sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j)); + prims[p_index++] = prim; + } + } + return pinfo; + }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); + + return pinfo; + } +#endif + // ==================================================================================================== // ==================================================================================================== // ==================================================================================================== @@ -239,5 +303,6 @@ namespace embree IF_ENABLED_TRIS (template size_t createMortonCodeArray(TriangleMesh* mesh COMMA mvector& morton COMMA BuildProgressMonitor& progressMonitor)); IF_ENABLED_QUADS(template size_t createMortonCodeArray(QuadMesh* mesh COMMA mvector& morton COMMA BuildProgressMonitor& progressMonitor)); IF_ENABLED_USER (template size_t createMortonCodeArray(UserGeometry* mesh COMMA mvector& morton COMMA BuildProgressMonitor& progressMonitor)); + IF_ENABLED_INSTANCE (template size_t createMortonCodeArray(Instance* mesh COMMA mvector& morton COMMA BuildProgressMonitor& progressMonitor)); } } diff --git a/kernels/builders/primrefgen.h b/kernels/builders/primrefgen.h index 9919c945c3..c09a848ba3 100644 --- a/kernels/builders/primrefgen.h +++ b/kernels/builders/primrefgen.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -10,19 +10,25 @@ #include "bvh_builder_morton.h" namespace embree -{ +{ namespace isa { - PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, mvector& prims, BuildProgressMonitor& progressMonitor); + PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, size_t numPrimitives, mvector& prims, BuildProgressMonitor& progressMonitor); - PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, mvector& prims, BuildProgressMonitor& progressMonitor); + PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, size_t numPrimitives, mvector& prims, BuildProgressMonitor& progressMonitor); - PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, mvector& prims, BuildProgressMonitor& progressMonitor, size_t itime = 0); + PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, size_t numPrimitives, mvector& prims, BuildProgressMonitor& progressMonitor, size_t itime = 0); - PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, mvector& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f)); + PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, size_t numPrimitives, mvector& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f)); template size_t createMortonCodeArray(Mesh* mesh, mvector& morton, BuildProgressMonitor& progressMonitor); + + /* special variants for grids */ + PrimInfo createPrimRefArrayGrids(Scene* scene, mvector& prims, mvector& sgrids); + + PrimInfo createPrimRefArrayGrids(GridMesh* mesh, mvector& prims, mvector& sgrids); + } } diff --git a/kernels/builders/primrefgen_presplit.h b/kernels/builders/primrefgen_presplit.h index 8bdb38b955..aa2026a85e 100644 --- a/kernels/builders/primrefgen_presplit.h +++ b/kernels/builders/primrefgen_presplit.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -266,7 +266,7 @@ namespace embree /* anything to split ? */ if (center < numPrimitives) { - const size_t numPrimitivesToSplit = numPrimitives - center; + size_t numPrimitivesToSplit = numPrimitives - center; assert(presplitItem[center].priority >= 1.0f); /* sort presplit items in ascending order */ @@ -279,8 +279,8 @@ namespace embree }); ); - unsigned int *const primOffset0 = (unsigned int*)tmp_presplitItem; - unsigned int *const primOffset1 = (unsigned int*)tmp_presplitItem + numPrimitivesToSplit; + unsigned int* primOffset0 = (unsigned int*)tmp_presplitItem; + unsigned int* primOffset1 = (unsigned int*)tmp_presplitItem + numPrimitivesToSplit; /* compute actual number of sub-primitives generated within the [center;numPrimitives-1] range */ const size_t totalNumSubPrims = parallel_reduce( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), size_t(0), [&](const range& t) -> size_t { @@ -317,11 +317,16 @@ namespace embree sum += numSubPrims; } new_center++; + + primOffset0 += new_center - center; + numPrimitivesToSplit -= new_center - center; center = new_center; + assert(numPrimitivesToSplit == (numPrimitives - center)); } /* parallel prefix sum to compute offsets for storing sub-primitives */ const unsigned int offset = parallel_prefix_sum(primOffset0,primOffset1,numPrimitivesToSplit,(unsigned int)0,std::plus()); + assert(numPrimitives+offset <= alloc_numPrimitives); /* iterate over range, and split primitives into sub primitives and append them to prims array */ parallel_for( size_t(center), numPrimitives, size_t(MIN_STEP_SIZE), [&](const range& rn) -> void { @@ -338,7 +343,7 @@ namespace embree unsigned int numSubPrims = 0; splitPrimitive(Splitter,prims[primrefID],geomID,primID,split_levels,grid_base,grid_scale,grid_extend,subPrims,numSubPrims); const size_t newID = numPrimitives + primOffset1[j-center]; - assert(newID+numSubPrims <= alloc_numPrimitives); + assert(newID+numSubPrims-1 <= alloc_numPrimitives); prims[primrefID] = subPrims[0]; for (size_t i=1;i void BVHN::layoutLargeNodes(size_t num) { -#if defined(__X86_64__) // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues +#if defined(__64BIT__) // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues struct NodeArea { __forceinline NodeArea() {} @@ -183,7 +183,7 @@ namespace embree template class BVHN<8>; #endif -#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42) +#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42) || defined(__aarch64__) template class BVHN<4>; #endif } diff --git a/kernels/bvh/bvh.h b/kernels/bvh/bvh.h index 7c1a45b632..565eec5a58 100644 --- a/kernels/bvh/bvh.h +++ b/kernels/bvh/bvh.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh4_factory.cpp b/kernels/bvh/bvh4_factory.cpp index 1bacb4583c..890d5e7b7c 100644 --- a/kernels/bvh/bvh4_factory.cpp +++ b/kernels/bvh/bvh4_factory.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh4_factory.h" @@ -206,6 +206,7 @@ namespace embree DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool); DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool); DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool); + DECLARE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool); DECLARE_ISA_FUNCTION(Builder*,BVH4Curve4vBuilder_OBB_New,void* COMMA Scene* COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH4Curve4iBuilder_OBB_New,void* COMMA Scene* COMMA size_t); @@ -259,11 +260,12 @@ namespace embree void BVH4Factory::selectBuilders(int features) { - IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelTriangle4MeshSAH)); - IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelTriangle4iMeshSAH)); - IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelTriangle4vMeshSAH)); - IF_ENABLED_QUADS (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelQuadMeshSAH)); - IF_ENABLED_USER (SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4BuilderTwoLevelVirtualSAH)); + IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelTriangle4MeshSAH)); + IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelTriangle4iMeshSAH)); + IF_ENABLED_TRIS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelTriangle4vMeshSAH)); + IF_ENABLED_QUADS (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelQuadMeshSAH)); + IF_ENABLED_USER (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelVirtualSAH)); + IF_ENABLED_INSTANCE (SELECT_SYMBOL_DEFAULT_AVX(features,BVH4BuilderTwoLevelInstanceSAH)); IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Curve4vBuilder_OBB_New)); IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Curve4iBuilder_OBB_New)); @@ -271,15 +273,15 @@ namespace embree IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH4Curve8iBuilder_OBB_New)); IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH4OBBCurve8iMBBuilder_OBB)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Triangle4SceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Triangle4vSceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Triangle4iSceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4SceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vSceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iSceneBuilderSAH)); IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4iMBSceneBuilderSAH)); IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Triangle4vMBSceneBuilderSAH)); IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4QuantizedTriangle4iSceneBuilderSAH)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Quad4vSceneBuilderSAH)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4Quad4iSceneBuilderSAH)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4vSceneBuilderSAH)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4iSceneBuilderSAH)); IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4iMBSceneBuilderSAH)); IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4QuantizedQuad4iSceneBuilderSAH)); @@ -289,207 +291,207 @@ namespace embree IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4Quad4vSceneBuilderFastSpatialSAH)); - IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4VirtualSceneBuilderSAH)); + IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4VirtualSceneBuilderSAH)); IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4VirtualMBSceneBuilderSAH)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4InstanceSceneBuilderSAH)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4InstanceSceneBuilderSAH)); IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4InstanceMBSceneBuilderSAH)); IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4GridSceneBuilderSAH)); IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4GridMBSceneBuilderSAH)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4SubdivPatch1BuilderSAH)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,BVH4SubdivPatch1MBBuilderSAH)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4SubdivPatch1BuilderSAH)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_AVX(features,BVH4SubdivPatch1MBBuilderSAH)); } void BVH4Factory::selectIntersectors(int features) { - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector4i)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8i)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector4v)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8v)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector4iMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8iMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,VirtualCurveIntersector4i)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8i)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,VirtualCurveIntersector4v)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8v)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,VirtualCurveIntersector4iMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8iMB)); /* select intersectors1 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector1)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector1MB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust1)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust1MB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector1)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector1MB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust1)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust1MB)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4Intersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,BVH4Triangle4iIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,BVH4Triangle4vIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,BVH4Triangle4iIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,BVH4Triangle4iIntersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,BVH4Triangle4vIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,BVH4Triangle4iIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector1Moeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector1Moeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,QBVH4Triangle4iIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,QBVH4Quad4iIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,QBVH4Triangle4iIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,QBVH4Quad4iIntersector1Pluecker)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1Intersector1)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1MBIntersector1)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1Intersector1)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1MBIntersector1)); - IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualIntersector1)); - IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualMBIntersector1)); + IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualIntersector1)); + IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualMBIntersector1)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceIntersector1)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceMBIntersector1)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceIntersector1)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceMBIntersector1)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector1Moeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridMBIntersector1Moeller)) - IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector1Pluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector1Moeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridMBIntersector1Moeller)) + IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector1Pluecker)); #if defined (EMBREE_RAY_PACKETS) /* select intersectors4 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector4Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector4HybridMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust4Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust4HybridMB)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector4HybridMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vIntersector4HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector4HybridPluecker)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector4HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector4HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector4HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector4HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector4HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector4HybridPluecker)); - - IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1Intersector4)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1MBIntersector4)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector4Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector4HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust4Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust4HybridMB)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector4HybridMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vIntersector4HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector4HybridPluecker)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector4HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector4HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector4HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector4HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector4HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector4HybridPluecker)); + + IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1Intersector4)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4SubdivPatch1MBIntersector4)); - IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualIntersector4Chunk)); - IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4VirtualMBIntersector4Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualIntersector4Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualMBIntersector4Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceIntersector4Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4InstanceMBIntersector4Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceIntersector4Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceMBIntersector4Chunk)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector4HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector4HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector4HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridMBIntersector4HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector4HybridPluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector4HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridMBIntersector4HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4GridIntersector4HybridPluecker)); /* select intersectors8 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector8Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersector8HybridMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust8Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust8HybridMB)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4Intersector8HybridMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vIntersector8HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iIntersector8HybridPluecker)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4vMBIntersector8HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Triangle4iMBIntersector8HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector8HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector8HybridMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector8HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4vIntersector8HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iIntersector8HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector8HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4Quad4iMBIntersector8HybridPluecker)); - - IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1Intersector8)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4SubdivPatch1MBIntersector8)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector8Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersector8HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust8Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust8HybridMB)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4Intersector8HybridMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4vIntersector8HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersector8HybridPluecker)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4vMBIntersector8HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Triangle4iMBIntersector8HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector8HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector8HybridMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector8HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4vIntersector8HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iIntersector8HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector8HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4Quad4iMBIntersector8HybridPluecker)); + + IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4SubdivPatch1Intersector8)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4SubdivPatch1MBIntersector8)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4VirtualIntersector8Chunk)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4VirtualMBIntersector8Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4VirtualIntersector8Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4VirtualMBIntersector8Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4InstanceIntersector8Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4InstanceMBIntersector8Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4InstanceIntersector8Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4InstanceMBIntersector8Chunk)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector8HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4GridMBIntersector8HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH4GridIntersector8HybridPluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4GridIntersector8HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4GridMBIntersector8HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH4GridIntersector8HybridPluecker)); /* select intersectors16 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersector16Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersector16HybridMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust16Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4OBBVirtualCurveIntersectorRobust16HybridMB)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4Intersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4Intersector16HybridMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4vIntersector16HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersector16HybridPluecker)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4vMBIntersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iMBIntersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4vMBIntersector16HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Triangle4iMBIntersector16HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersector16HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersector16HybridMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersector16HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersector16HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersector16HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iMBIntersector16HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4Quad4iMBIntersector16HybridPluecker)); - - IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4SubdivPatch1Intersector16)); - IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4SubdivPatch1MBIntersector16)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersector16Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersector16HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust16Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH4OBBVirtualCurveIntersectorRobust16HybridMB)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4Intersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4Intersector16HybridMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iIntersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4vIntersector16HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iIntersector16HybridPluecker)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4vMBIntersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iMBIntersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4vMBIntersector16HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Triangle4iMBIntersector16HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4vIntersector16HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4vIntersector16HybridMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iIntersector16HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4vIntersector16HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iIntersector16HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iMBIntersector16HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH4Quad4iMBIntersector16HybridPluecker)); + + IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512(features,BVH4SubdivPatch1Intersector16)); + IF_ENABLED_SUBDIV(SELECT_SYMBOL_INIT_AVX512(features,BVH4SubdivPatch1MBIntersector16)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4VirtualIntersector16Chunk)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4VirtualMBIntersector16Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH4VirtualIntersector16Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH4VirtualMBIntersector16Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4InstanceIntersector16Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4InstanceMBIntersector16Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH4InstanceIntersector16Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH4InstanceMBIntersector16Chunk)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4GridIntersector16HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4GridMBIntersector16HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH4GridIntersector16HybridPluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH4GridIntersector16HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH4GridMBIntersector16HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH4GridIntersector16HybridPluecker)); /* select stream intersectors */ - SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4IntersectorStreamPacketFallback); + SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4IntersectorStreamPacketFallback); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4IntersectorStreamMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4IntersectorStreamMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersectorStreamMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4vIntersectorStreamPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Triangle4iIntersectorStreamPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4IntersectorStreamMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4IntersectorStreamMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersectorStreamMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4vIntersectorStreamPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Triangle4iIntersectorStreamPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersectorStreamMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersectorStreamMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersectorStreamMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4vIntersectorStreamPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4Quad4iIntersectorStreamPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersectorStreamMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersectorStreamMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersectorStreamMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4vIntersectorStreamPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4Quad4iIntersectorStreamPluecker)); - IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4VirtualIntersectorStream)); + IF_ENABLED_USER(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4VirtualIntersectorStream)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH4InstanceIntersectorStream)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,BVH4InstanceIntersectorStream)); #endif } @@ -1227,7 +1229,20 @@ namespace embree BVH4* accel = new BVH4(InstancePrimitive::type,scene); Accel::Intersectors intersectors = BVH4InstanceIntersectors(accel); auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE_CHEAP; - Builder* builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype); + // Builder* builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype); + + Builder* builder = nullptr; + if (scene->device->object_builder == "default") { + switch (bvariant) { + case BuildVariant::STATIC : builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype); break; + case BuildVariant::DYNAMIC : builder = BVH4BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); break; + case BuildVariant::HIGH_QUALITY: assert(false); break; + } + } + else if (scene->device->object_builder == "sah") builder = BVH4InstanceSceneBuilderSAH(accel,scene,gtype); + else if (scene->device->object_builder == "dynamic") builder = BVH4BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); + else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH4"); + return new AccelInstance(accel,builder,intersectors); } diff --git a/kernels/bvh/bvh4_factory.h b/kernels/bvh/bvh4_factory.h index a429b41a49..30973971a4 100644 --- a/kernels/bvh/bvh4_factory.h +++ b/kernels/bvh/bvh4_factory.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -311,5 +311,6 @@ namespace embree DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool); DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool); DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool); + DEFINE_ISA_FUNCTION(Builder*,BVH4BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool); }; } diff --git a/kernels/bvh/bvh8_factory.cpp b/kernels/bvh/bvh8_factory.cpp index 2aaefe5267..d4521af241 100644 --- a/kernels/bvh/bvh8_factory.cpp +++ b/kernels/bvh/bvh8_factory.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/isa.h" // to define EMBREE_TARGET_SIMD8 @@ -223,6 +223,7 @@ namespace embree DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool); DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool); DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool); + DECLARE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool); BVH8Factory::BVH8Factory(int bfeatures, int ifeatures) { @@ -237,17 +238,17 @@ namespace embree IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH8Curve8vBuilder_OBB_New)); IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX(features,BVH8OBBCurve8iMBBuilder_OBB)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4SceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4vSceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4iSceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4iMBSceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4vMBSceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4SceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4vSceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4iSceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4iMBSceneBuilderSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4vMBSceneBuilderSAH)); IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedTriangle4iSceneBuilderSAH)); IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedTriangle4SceneBuilderSAH)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4vSceneBuilderSAH)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4iSceneBuilderSAH)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4iMBSceneBuilderSAH)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4vSceneBuilderSAH)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4iSceneBuilderSAH)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4iMBSceneBuilderSAH)); IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8QuantizedQuad4iSceneBuilderSAH)); IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX(features,BVH8VirtualSceneBuilderSAH)); @@ -259,188 +260,189 @@ namespace embree IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX(features,BVH8GridSceneBuilderSAH)); IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX(features,BVH8GridMBSceneBuilderSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4SceneBuilderFastSpatialSAH)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Triangle4vSceneBuilderFastSpatialSAH)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8Quad4vSceneBuilderFastSpatialSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4SceneBuilderFastSpatialSAH)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX(features,BVH8Triangle4vSceneBuilderFastSpatialSAH)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX(features,BVH8Quad4vSceneBuilderFastSpatialSAH)); - IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelTriangle4MeshSAH)); - IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelTriangle4vMeshSAH)); - IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelTriangle4iMeshSAH)); - IF_ENABLED_QUADS (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelQuadMeshSAH)); - IF_ENABLED_USER (SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,BVH8BuilderTwoLevelVirtualSAH)); + IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelTriangle4MeshSAH)); + IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelTriangle4vMeshSAH)); + IF_ENABLED_TRIS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelTriangle4iMeshSAH)); + IF_ENABLED_QUADS (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelQuadMeshSAH)); + IF_ENABLED_USER (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelVirtualSAH)); + IF_ENABLED_INSTANCE (SELECT_SYMBOL_INIT_AVX(features,BVH8BuilderTwoLevelInstanceSAH)); } void BVH8Factory::selectIntersectors(int features) { - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8v)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,VirtualCurveIntersector8iMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8v)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,VirtualCurveIntersector8iMB)); /* select intersectors1 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector1)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector1MB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust1)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust1MB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector1)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector1MB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust1)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust1MB)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4Intersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersector1Woop)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector1Woop)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector1Moeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector1Moeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector1Moeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector1Moeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector1Pluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector1Moeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector1Pluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iMBIntersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iMBIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,QBVH8Triangle4iIntersector1Pluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,QBVH8Triangle4Intersector1Moeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,QBVH8Quad4iIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,QBVH8Triangle4iIntersector1Pluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,QBVH8Triangle4Intersector1Moeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,QBVH8Quad4iIntersector1Pluecker)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8VirtualIntersector1)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8VirtualMBIntersector1)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersector1)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualMBIntersector1)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8InstanceIntersector1)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8InstanceMBIntersector1)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersector1)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceMBIntersector1)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector1Moeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridMBIntersector1Moeller)) - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector1Pluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector1Moeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridMBIntersector1Moeller)) + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector1Pluecker)); #if defined (EMBREE_RAY_PACKETS) /* select intersectors4 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector4Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector4HybridMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust4Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust4HybridMB)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector4HybridMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vIntersector4HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector4HybridPluecker)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector4HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector4HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector4HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector4HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector4HybridMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector4HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector4HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector4HybridPluecker)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector4Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector4HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust4Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust4HybridMB)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector4HybridMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector4HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector4HybridPluecker)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector4HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector4HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector4HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector4HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector4HybridMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector4HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector4HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector4HybridPluecker)); IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector4HybridMoeller)); IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector4HybridPluecker)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualIntersector4Chunk)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualMBIntersector4Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersector4Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualMBIntersector4Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceIntersector4Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceMBIntersector4Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersector4Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceMBIntersector4Chunk)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector4HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector4HybridPluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector4HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector4HybridPluecker)); /* select intersectors8 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector8Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersector8HybridMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust8Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust8HybridMB)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4Intersector8HybridMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vIntersector8HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iIntersector8HybridPluecker)); - - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector8HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4vMBIntersector8HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Triangle4iMBIntersector8HybridPluecker)); - - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector8HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector8HybridMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector8HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4vIntersector8HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8Quad4iIntersector8HybridPluecker)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector8Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersector8HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust8Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust8HybridMB)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4Intersector8HybridMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersector8HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersector8HybridPluecker)); + + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector8HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vMBIntersector8HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iMBIntersector8HybridPluecker)); + + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector8HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector8HybridMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector8HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersector8HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersector8HybridPluecker)); IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector8HybridMoeller)); IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2(features,BVH8Quad4iMBIntersector8HybridPluecker)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualIntersector8Chunk)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8VirtualMBIntersector8Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersector8Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualMBIntersector8Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceIntersector8Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8InstanceMBIntersector8Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersector8Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceMBIntersector8Chunk)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector8HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,BVH8GridIntersector8HybridPluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector8HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8GridIntersector8HybridPluecker)); /* select intersectors16 */ - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector16Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersector16HybridMB)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust16Hybrid)); - IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8OBBVirtualCurveIntersectorRobust16HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersector16Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersector16HybridMB)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust16Hybrid)); + IF_ENABLED_CURVES_OR_POINTS(SELECT_SYMBOL_INIT_AVX512(features,BVH8OBBVirtualCurveIntersectorRobust16HybridMB)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4Intersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4Intersector16HybridMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersector16HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersector16HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4Intersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4Intersector16HybridMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iIntersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4vIntersector16HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iIntersector16HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector16HybridMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4vMBIntersector16HybridPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Triangle4iMBIntersector16HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4vMBIntersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iMBIntersector16HybridMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4vMBIntersector16HybridPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Triangle4iMBIntersector16HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector16HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector16HybridMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector16HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersector16HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersector16HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4vIntersector16HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4vIntersector16HybridMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iIntersector16HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4vIntersector16HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iIntersector16HybridPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector16HybridMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8Quad4iMBIntersector16HybridPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iMBIntersector16HybridMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX512(features,BVH8Quad4iMBIntersector16HybridPluecker)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8VirtualIntersector16Chunk)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8VirtualMBIntersector16Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH8VirtualIntersector16Chunk)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512(features,BVH8VirtualMBIntersector16Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8InstanceIntersector16Chunk)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8InstanceMBIntersector16Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH8InstanceIntersector16Chunk)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX512(features,BVH8InstanceMBIntersector16Chunk)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8GridIntersector16HybridMoeller)); - IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8GridIntersector16HybridPluecker)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH8GridIntersector16HybridMoeller)); + IF_ENABLED_GRIDS(SELECT_SYMBOL_INIT_AVX512(features,BVH8GridIntersector16HybridPluecker)); /* select stream intersectors */ - SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8IntersectorStreamPacketFallback); + SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8IntersectorStreamPacketFallback); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4IntersectorStreamMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4IntersectorStreamMoellerNoFilter)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersectorStreamMoeller)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4vIntersectorStreamPluecker)); - IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Triangle4iIntersectorStreamPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4IntersectorStreamMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4IntersectorStreamMoellerNoFilter)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersectorStreamMoeller)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4vIntersectorStreamPluecker)); + IF_ENABLED_TRIS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Triangle4iIntersectorStreamPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersectorStreamMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersectorStreamMoellerNoFilter)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersectorStreamMoeller)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4vIntersectorStreamPluecker)); - IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8Quad4iIntersectorStreamPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersectorStreamMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersectorStreamMoellerNoFilter)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersectorStreamMoeller)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4vIntersectorStreamPluecker)); + IF_ENABLED_QUADS(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8Quad4iIntersectorStreamPluecker)); - IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8VirtualIntersectorStream)); + IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8VirtualIntersectorStream)); - IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVH8InstanceIntersectorStream)); + IF_ENABLED_INSTANCE(SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,BVH8InstanceIntersectorStream)); #endif } @@ -1067,7 +1069,20 @@ namespace embree BVH8* accel = new BVH8(InstancePrimitive::type,scene); Accel::Intersectors intersectors = BVH8InstanceIntersectors(accel); auto gtype = isExpensive ? Geometry::MTY_INSTANCE_EXPENSIVE : Geometry::MTY_INSTANCE; - Builder* builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype); + // Builder* builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype); + + Builder* builder = nullptr; + if (scene->device->object_builder == "default") { + switch (bvariant) { + case BuildVariant::STATIC : builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype);; break; + case BuildVariant::DYNAMIC : builder = BVH8BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); break; + case BuildVariant::HIGH_QUALITY: assert(false); break; + } + } + else if (scene->device->object_builder == "sah") builder = BVH8InstanceSceneBuilderSAH(accel,scene,gtype); + else if (scene->device->object_builder == "dynamic") builder = BVH8BuilderTwoLevelInstanceSAH(accel,scene,gtype,false); + else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown builder "+scene->device->object_builder+" for BVH8"); + return new AccelInstance(accel,builder,intersectors); } diff --git a/kernels/bvh/bvh8_factory.h b/kernels/bvh/bvh8_factory.h index 41d9c3731b..198d6f1df0 100644 --- a/kernels/bvh/bvh8_factory.h +++ b/kernels/bvh/bvh8_factory.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -275,5 +275,6 @@ namespace embree DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelTriangle4iMeshSAH,void* COMMA Scene* COMMA bool); DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelQuadMeshSAH,void* COMMA Scene* COMMA bool); DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelVirtualSAH,void* COMMA Scene* COMMA bool); + DEFINE_ISA_FUNCTION(Builder*,BVH8BuilderTwoLevelInstanceSAH,void* COMMA Scene* COMMA Geometry::GTypeMask COMMA bool); }; } diff --git a/kernels/bvh/bvh_builder.cpp b/kernels/bvh/bvh_builder.cpp index e832537ec5..161d01bb5c 100644 --- a/kernels/bvh/bvh_builder.cpp +++ b/kernels/bvh/bvh_builder.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_builder.h" diff --git a/kernels/bvh/bvh_builder.h b/kernels/bvh/bvh_builder.h index 1b86bb45ad..e35d052a62 100644 --- a/kernels/bvh/bvh_builder.h +++ b/kernels/bvh/bvh_builder.h @@ -1,8 +1,9 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" #include "../builders/bvh_builder_sah.h" +#include "../builders/bvh_builder_msmblur.h" namespace embree { diff --git a/kernels/bvh/bvh_builder_hair.cpp b/kernels/bvh/bvh_builder_hair.cpp index 1a51ae3339..5cb0e2a8a4 100644 --- a/kernels/bvh/bvh_builder_hair.cpp +++ b/kernels/bvh/bvh_builder_hair.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../builders/bvh_builder_hair.h" @@ -47,7 +47,7 @@ namespace embree /* create primref array */ prims.resize(numPrimitives); - const PrimInfo pinfo = createPrimRefArray(scene,Geometry::MTY_CURVES,false,prims,scene->progressInterface); + const PrimInfo pinfo = createPrimRefArray(scene,Geometry::MTY_CURVES,false,numPrimitives,prims,scene->progressInterface); /* estimate acceleration structure size */ const size_t node_bytes = pinfo.size()*sizeof(typename BVH::OBBNode)/(4*N); diff --git a/kernels/bvh/bvh_builder_hair_mb.cpp b/kernels/bvh/bvh_builder_hair_mb.cpp index 9e54645c04..56fcb5328f 100644 --- a/kernels/bvh/bvh_builder_hair_mb.cpp +++ b/kernels/bvh/bvh_builder_hair_mb.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../builders/bvh_builder_msmblur_hair.h" @@ -43,7 +43,7 @@ namespace embree /* create primref array */ mvector prims0(scene->device,numPrimitives); - const PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,Geometry::MTY_CURVES,prims0,bvh->scene->progressInterface); + const PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,Geometry::MTY_CURVES,numPrimitives,prims0,bvh->scene->progressInterface); /* estimate acceleration structure size */ const size_t node_bytes = pinfo.num_time_segments*sizeof(typename BVH::AABBNodeMB)/(4*N); diff --git a/kernels/bvh/bvh_builder_morton.cpp b/kernels/bvh/bvh_builder_morton.cpp index 65b3de14ed..4a4d8d71df 100644 --- a/kernels/bvh/bvh_builder_morton.cpp +++ b/kernels/bvh/bvh_builder_morton.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" @@ -16,8 +16,9 @@ #include "../geometry/quadv.h" #include "../geometry/quadi.h" #include "../geometry/object.h" +#include "../geometry/instance.h" -#if defined(__X86_64__) +#if defined(__64BIT__) # define ROTATE_TREE 1 // specifies number of tree rotation rounds to perform #else # define ROTATE_TREE 0 // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues @@ -354,6 +355,50 @@ namespace embree unsigned int geomID_ = std::numeric_limits::max(); }; + template + struct CreateMortonLeaf + { + typedef BVHN BVH; + typedef typename BVH::NodeRef NodeRef; + typedef typename BVH::NodeRecord NodeRecord; + + __forceinline CreateMortonLeaf (Instance* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton) + : mesh(mesh), morton(morton), geomID_(geomID) {} + + __noinline NodeRecord operator() (const range& current, const FastAllocator::CachedAllocator& alloc) + { + vfloat4 lower(pos_inf); + vfloat4 upper(neg_inf); + size_t items = current.size(); + size_t start = current.begin(); + assert(items <= 1); + + /* allocate leaf node */ + InstancePrimitive* accel = (InstancePrimitive*) alloc.malloc1(items*sizeof(InstancePrimitive),BVH::byteAlignment); + NodeRef ref = BVH::encodeLeaf((char*)accel,items); + const Instance* instance = this->mesh; + + BBox3fa bounds = empty; + for (size_t i=0; ibounds(primID)); + new (&accel[i]) InstancePrimitive(instance, geomID_); + } + + BBox3fx box_o = (BBox3fx&)bounds; +#if ROTATE_TREE + if (N == 4) + box_o.lower.a = current.size(); +#endif + return NodeRecord(ref,box_o); + } + private: + Instance* mesh; + BVHBuilderMorton::BuildPrim* morton; + unsigned int geomID_ = std::numeric_limits::max(); + }; + template struct CalculateMeshBounds { @@ -473,6 +518,13 @@ namespace embree #if defined(__AVX__) Builder* BVH8VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,UserGeometry,Object>((BVH8*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); } #endif +#endif + +#if defined(EMBREE_GEOMETRY_INSTANCE) + Builder* BVH4InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,Instance,InstancePrimitive>((BVH4*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); } +#if defined(__AVX__) + Builder* BVH8InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,Instance,InstancePrimitive>((BVH8*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); } +#endif #endif } diff --git a/kernels/bvh/bvh_builder_sah.cpp b/kernels/bvh/bvh_builder_sah.cpp index 5efece4ca3..fad02fcc04 100644 --- a/kernels/bvh/bvh_builder_sah.cpp +++ b/kernels/bvh/bvh_builder_sah.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" @@ -153,8 +153,8 @@ namespace embree prims.resize(numPrimitives); PrimInfo pinfo = mesh ? - createPrimRefArray(mesh,geomID_,prims,bvh->scene->progressInterface) : - createPrimRefArray(scene,gtype_,false,prims,bvh->scene->progressInterface); + createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) : + createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface); /* pinfo might has zero size due to invalid geometry */ if (unlikely(pinfo.size() == 0)) @@ -242,8 +242,8 @@ namespace embree /* create primref array */ prims.resize(numPrimitives); PrimInfo pinfo = mesh ? - createPrimRefArray(mesh,geomID_,prims,bvh->scene->progressInterface) : - createPrimRefArray(scene,gtype_,false,prims,bvh->scene->progressInterface); + createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) : + createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface); /* enable os_malloc for two level build */ if (mesh) @@ -356,7 +356,7 @@ namespace embree mvector prims; mvector sgrids; GeneralBVHBuilder::Settings settings; - unsigned int geomID_ = std::numeric_limits::max(); + const unsigned int geomID_ = std::numeric_limits::max(); unsigned int numPreviousPrimitives = 0; BVHNBuilderSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode) @@ -378,109 +378,10 @@ namespace embree const size_t numGridPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(GridMesh::geom_type,false); numPreviousPrimitives = numGridPrimitives; - - PrimInfo pinfo(empty); - size_t numPrimitives = 0; - - if (!mesh) - { - /* first run to get #primitives */ - - ParallelForForPrefixSumState pstate; - Scene::Iterator iter(scene); - - pstate.init(iter,size_t(1024)); - - /* iterate over all meshes in the scene */ - pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID) -> PrimInfo { - PrimInfo pinfo(empty); - for (size_t j=r.begin(); jvalid(j)) continue; - BBox3fa bounds = empty; - const PrimRef prim(bounds,(unsigned)geomID,(unsigned)j); - if (!mesh->valid(j)) continue; - pinfo.add_center2(prim,mesh->getNumSubGrids(j)); - } - return pinfo; - }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); - numPrimitives = pinfo.size(); - - /* resize arrays */ - sgrids.resize(numPrimitives); - prims.resize(numPrimitives); - - /* second run to fill primrefs and SubGridBuildData arrays */ - pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo { - k = base.size(); - size_t p_index = k; - PrimInfo pinfo(empty); - for (size_t j=r.begin(); jvalid(j)) continue; - const GridMesh::Grid &g = mesh->grid(j); - for (unsigned int y=0; ybuildBounds(g,x,y,bounds)) continue; // get bounds of subgrid - const PrimRef prim(bounds,(unsigned)geomID,(unsigned)p_index); - pinfo.add_center2(prim); - sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j)); - prims[p_index++] = prim; - } - } - return pinfo; - }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); - assert(pinfo.size() == numPrimitives); - } - else - { - ParallelPrefixSumState pstate; - /* iterate over all grids in a single mesh */ - pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range& r, const PrimInfo& base) -> PrimInfo - { - PrimInfo pinfo(empty); - for (size_t j=r.begin(); jvalid(j)) continue; - BBox3fa bounds = empty; - const PrimRef prim(bounds,geomID_,unsigned(j)); - pinfo.add_center2(prim,mesh->getNumSubGrids(j)); - } - return pinfo; - }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); - numPrimitives = pinfo.size(); - /* resize arrays */ - sgrids.resize(numPrimitives); - prims.resize(numPrimitives); - - /* second run to fill primrefs and SubGridBuildData arrays */ - pinfo = parallel_prefix_sum( pstate, size_t(0), mesh->size(), size_t(1024), PrimInfo(empty), [&](const range& r, const PrimInfo& base) -> PrimInfo - { - - size_t p_index = base.size(); - PrimInfo pinfo(empty); - for (size_t j=r.begin(); jvalid(j)) continue; - const GridMesh::Grid &g = mesh->grid(j); - for (unsigned int y=0; ybuildBounds(g,x,y,bounds)) continue; // get bounds of subgrid - const PrimRef prim(bounds,geomID_,unsigned(p_index)); - pinfo.add_center2(prim); - sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j)); - prims[p_index++] = prim; - } - } - return pinfo; - }, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); }); - } + PrimInfo pinfo = mesh ? createPrimRefArrayGrids(mesh,prims,sgrids) : createPrimRefArrayGrids(scene,prims,sgrids); + const size_t numPrimitives = pinfo.size(); /* no primitives */ if (numPrimitives == 0) { bvh->clear(); @@ -546,6 +447,7 @@ namespace embree /************************************************************************************/ /************************************************************************************/ + #if defined(EMBREE_GEOMETRY_TRIANGLE) Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); } Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); } @@ -555,7 +457,6 @@ namespace embree Builder* BVH4Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); } Builder* BVH4Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); } - Builder* BVH4QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); } #if defined(__AVX__) Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); } @@ -568,6 +469,8 @@ namespace embree Builder* BVH8QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); } Builder* BVH8QuantizedTriangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); } + + #endif #endif @@ -616,8 +519,14 @@ namespace embree #if defined(EMBREE_GEOMETRY_INSTANCE) Builder* BVH4InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); } + Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { + return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,gtype); + } #if defined(__AVX__) Builder* BVH8InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); } + Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { + return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,gtype); + } #endif #endif diff --git a/kernels/bvh/bvh_builder_sah_mb.cpp b/kernels/bvh/bvh_builder_sah_mb.cpp index 9c01553ec6..d163a80ab1 100644 --- a/kernels/bvh/bvh_builder_sah_mb.cpp +++ b/kernels/bvh/bvh_builder_sah_mb.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" @@ -142,7 +142,7 @@ namespace embree { /* create primref array */ mvector prims(scene->device,numPrimitives); - const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,prims,bvh->scene->progressInterface,0); + const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0); /* early out if no valid primitives */ if (pinfo.size() == 0) { bvh->clear(); return; } /* estimate acceleration structure size */ @@ -175,7 +175,7 @@ namespace embree { /* create primref array */ mvector prims(scene->device,numPrimitives); - PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,prims,bvh->scene->progressInterface); + PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface); /* early out if no valid primitives */ if (pinfo.size() == 0) { bvh->clear(); return; } diff --git a/kernels/bvh/bvh_builder_sah_spatial.cpp b/kernels/bvh/bvh_builder_sah_spatial.cpp index 285b38c39d..a4e55d7484 100644 --- a/kernels/bvh/bvh_builder_sah_spatial.cpp +++ b/kernels/bvh/bvh_builder_sah_spatial.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" @@ -127,8 +127,8 @@ namespace embree { /* standard spatial split SAH BVH builder */ pinfo = mesh ? - createPrimRefArray(mesh,geomID_,/*numSplitPrimitives,*/prims0,bvh->scene->progressInterface) : - createPrimRefArray(scene,Mesh::geom_type,false,/*numSplitPrimitives,*/prims0,bvh->scene->progressInterface); + createPrimRefArray(mesh,geomID_,numSplitPrimitives,prims0,bvh->scene->progressInterface) : + createPrimRefArray(scene,Mesh::geom_type,false,numSplitPrimitives,prims0,bvh->scene->progressInterface); Splitter splitter(scene); diff --git a/kernels/bvh/bvh_builder_subdiv.cpp b/kernels/bvh/bvh_builder_subdiv.cpp index 47a2a386fa..fd7a208276 100644 --- a/kernels/bvh/bvh_builder_subdiv.cpp +++ b/kernels/bvh/bvh_builder_subdiv.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh.h" diff --git a/kernels/bvh/bvh_builder_twolevel.cpp b/kernels/bvh/bvh_builder_twolevel.cpp index 0262649fa5..5d45ed3748 100644 --- a/kernels/bvh/bvh_builder_twolevel.cpp +++ b/kernels/bvh/bvh_builder_twolevel.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_builder_twolevel.h" @@ -15,8 +15,8 @@ namespace embree namespace isa { template - BVHNBuilderTwoLevel::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, bool useMortonBuilder, const size_t singleThreadThreshold) - : bvh(bvh), scene(scene), refs(scene->device,0), prims(scene->device,0), singleThreadThreshold(singleThreadThreshold), useMortonBuilder_(useMortonBuilder) {} + BVHNBuilderTwoLevel::BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder, const size_t singleThreadThreshold) + : bvh(bvh), scene(scene), refs(scene->device,0), prims(scene->device,0), singleThreadThreshold(singleThreadThreshold), gtype(gtype), useMortonBuilder_(useMortonBuilder) {} template BVHNBuilderTwoLevel::~BVHNBuilderTwoLevel () { @@ -48,7 +48,7 @@ namespace embree bvh->alloc.reset(); /* skip build for empty scene */ - const size_t numPrimitives = scene->getNumPrimitives(Mesh::geom_type,false); + const size_t numPrimitives = scene->getNumPrimitives(gtype,false); if (numPrimitives == 0) { prims.resize(0); @@ -129,10 +129,6 @@ namespace embree prims.resize(refs.size()); #endif -#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL - tbb::task_arena limited(min(32,(int)TaskScheduler::threadCount())); - limited.execute([&] -#endif { #if ENABLE_DIRECT_SAH_MERGE_BUILDER @@ -211,10 +207,6 @@ namespace embree bvh->set(root,LBBox3fa(pinfo.geomBounds),numPrimitives); } } -#if defined(TASKING_TBB) && defined(__AVX512ER__) && USE_TASK_ARENA // KNL - ); -#endif - } bvh->alloc.cleanup(); @@ -313,53 +305,65 @@ namespace embree #if defined(EMBREE_GEOMETRY_TRIANGLE) Builder* BVH4BuilderTwoLevelTriangle4MeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4>((BVH4*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder); } Builder* BVH4BuilderTwoLevelTriangle4vMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4v>((BVH4*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4v>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder); } Builder* BVH4BuilderTwoLevelTriangle4iMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder); } #endif #if defined(EMBREE_GEOMETRY_QUAD) Builder* BVH4BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<4,QuadMesh,Quad4v>((BVH4*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<4,QuadMesh,Quad4v>((BVH4*)bvh,scene,QuadMesh::geom_type,useMortonBuilder); } #endif #if defined(EMBREE_GEOMETRY_USER) Builder* BVH4BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<4,UserGeometry,Object>((BVH4*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<4,UserGeometry,Object>((BVH4*)bvh,scene,UserGeometry::geom_type,useMortonBuilder); } #endif +#if defined(EMBREE_GEOMETRY_INSTANCE) + Builder* BVH4BuilderTwoLevelInstanceSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder) { + return new BVHNBuilderTwoLevel<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,gtype,useMortonBuilder); + } +#endif #if defined(__AVX__) #if defined(EMBREE_GEOMETRY_TRIANGLE) Builder* BVH8BuilderTwoLevelTriangle4MeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4>((BVH8*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder); } Builder* BVH8BuilderTwoLevelTriangle4vMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4v>((BVH8*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4v>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder); } Builder* BVH8BuilderTwoLevelTriangle4iMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,TriangleMesh::geom_type,useMortonBuilder); } #endif #if defined(EMBREE_GEOMETRY_QUAD) Builder* BVH8BuilderTwoLevelQuadMeshSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<8,QuadMesh,Quad4v>((BVH8*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<8,QuadMesh,Quad4v>((BVH8*)bvh,scene,QuadMesh::geom_type,useMortonBuilder); } #endif #if defined(EMBREE_GEOMETRY_USER) Builder* BVH8BuilderTwoLevelVirtualSAH (void* bvh, Scene* scene, bool useMortonBuilder) { - return new BVHNBuilderTwoLevel<8,UserGeometry,Object>((BVH8*)bvh,scene,useMortonBuilder); + return new BVHNBuilderTwoLevel<8,UserGeometry,Object>((BVH8*)bvh,scene,UserGeometry::geom_type,useMortonBuilder); } #endif + +#if defined(EMBREE_GEOMETRY_INSTANCE) + Builder* BVH8BuilderTwoLevelInstanceSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype, bool useMortonBuilder) { + return new BVHNBuilderTwoLevel<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,gtype,useMortonBuilder); + } +#endif + #endif } } diff --git a/kernels/bvh/bvh_builder_twolevel.h b/kernels/bvh/bvh_builder_twolevel.h index 80883e9c5e..dc7ec7d278 100644 --- a/kernels/bvh/bvh_builder_twolevel.h +++ b/kernels/bvh/bvh_builder_twolevel.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -103,7 +103,7 @@ namespace embree } /*! Constructor. */ - BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, bool useMortonBuilder = false, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD); + BVHNBuilderTwoLevel (BVH* bvh, Scene* scene, Geometry::GTypeMask gtype = Mesh::geom_type, bool useMortonBuilder = false, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD); /*! Destructor */ ~BVHNBuilderTwoLevel (); @@ -137,7 +137,7 @@ namespace embree assert(isSmallGeometry(mesh)); mvector prefs(topBuilder->scene->device, meshSize); - auto pinfo = createPrimRefArray(mesh,objectID_,prefs,topBuilder->bvh->scene->progressInterface); + auto pinfo = createPrimRefArray(mesh,objectID_,meshSize,prefs,topBuilder->bvh->scene->progressInterface); size_t begin=0; while (begin < pinfo.size()) @@ -244,19 +244,20 @@ namespace embree return; } - __internal_two_level_builder__::MeshBuilder()(accel, mesh, geomID, this->useMortonBuilder_, builder); + __internal_two_level_builder__::MeshBuilder()(accel, mesh, geomID, this->gtype, this->useMortonBuilder_, builder); } using BuilderList = std::vector>; - BuilderList builders; - BVH* bvh; - Scene* scene; - mvector refs; - mvector prims; - std::atomic nextRef; - const size_t singleThreadThreshold; - bool useMortonBuilder_ = false; + BuilderList builders; + BVH* bvh; + Scene* scene; + mvector refs; + mvector prims; + std::atomic nextRef; + const size_t singleThreadThreshold; + Geometry::GTypeMask gtype; + bool useMortonBuilder_ = false; }; } } diff --git a/kernels/bvh/bvh_builder_twolevel_internal.h b/kernels/bvh/bvh_builder_twolevel_internal.h index c80f767023..023b52b780 100644 --- a/kernels/bvh/bvh_builder_twolevel_internal.h +++ b/kernels/bvh/bvh_builder_twolevel_internal.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -10,6 +10,7 @@ #include "../geometry/quadv.h" #include "../geometry/quadi.h" #include "../geometry/object.h" +#include "../geometry/instance.h" namespace embree { @@ -28,6 +29,9 @@ namespace embree DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshBuilderMortonGeneral,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshBuilderSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH4InstanceMeshRefitSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t) DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshBuilderMortonGeneral,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshBuilderSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH8Triangle4MeshRefitSAH,void* COMMA TriangleMesh* COMMA unsigned int COMMA size_t); @@ -42,7 +46,10 @@ namespace embree DECLARE_ISA_FUNCTION(Builder*,BVH8Quad4vMeshRefitSAH,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshBuilderSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); - DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH8VirtualMeshRefitSAH,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshBuilderMortonGeneral,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshBuilderSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t); + DECLARE_ISA_FUNCTION(Builder*,BVH8InstanceMeshRefitSAH,void* COMMA Instance* COMMA Geometry::GTypeMask COMMA unsigned int COMMA size_t) namespace isa { @@ -54,52 +61,62 @@ namespace embree template<> struct MortonBuilder<4,TriangleMesh,Triangle4> { MortonBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<4,TriangleMesh,Triangle4v> { MortonBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<4,TriangleMesh,Triangle4i> { MortonBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<4,QuadMesh,Quad4v> { MortonBuilder () {} - Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID) { return BVH4Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<4,UserGeometry,Object> { MortonBuilder () {} - Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID) { return BVH4VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + }; + template<> + struct MortonBuilder<4,Instance,InstancePrimitive> { + MortonBuilder () {} + Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshBuilderMortonGeneral(bvh,mesh,gtype,geomID,0);} }; template<> struct MortonBuilder<8,TriangleMesh,Triangle4> { MortonBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<8,TriangleMesh,Triangle4v> { MortonBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<8,TriangleMesh,Triangle4i> { MortonBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<8,QuadMesh,Quad4v> { MortonBuilder () {} - Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID) { return BVH8Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} }; template<> struct MortonBuilder<8,UserGeometry,Object> { MortonBuilder () {} - Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID) { return BVH8VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshBuilderMortonGeneral(bvh,mesh,geomID,0);} + }; + template<> + struct MortonBuilder<8,Instance,InstancePrimitive> { + MortonBuilder () {} + Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshBuilderMortonGeneral(bvh,mesh,gtype,geomID,0);} }; template @@ -107,52 +124,62 @@ namespace embree template<> struct SAHBuilder<4,TriangleMesh,Triangle4> { SAHBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<4,TriangleMesh,Triangle4v> { SAHBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<4,TriangleMesh,Triangle4i> { SAHBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<4,QuadMesh,Quad4v> { SAHBuilder () {} - Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID) { return BVH4Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<4,UserGeometry,Object> { SAHBuilder () {} - Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID) { return BVH4VirtualMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshBuilderSAH(bvh,mesh,geomID,0);} + }; + template<> + struct SAHBuilder<4,Instance,InstancePrimitive> { + SAHBuilder () {} + Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshBuilderSAH(bvh,mesh,gtype,geomID,0);} }; template<> struct SAHBuilder<8,TriangleMesh,Triangle4> { SAHBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<8,TriangleMesh,Triangle4v> { SAHBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<8,TriangleMesh,Triangle4i> { SAHBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<8,QuadMesh,Quad4v> { SAHBuilder () {} - Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID) { return BVH8Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshBuilderSAH(bvh,mesh,geomID,0);} }; template<> struct SAHBuilder<8,UserGeometry,Object> { SAHBuilder () {} - Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID) { return BVH8VirtualMeshBuilderSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshBuilderSAH(bvh,mesh,geomID,0);} + }; + template<> + struct SAHBuilder<8,Instance,InstancePrimitive> { + SAHBuilder () {} + Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshBuilderSAH(bvh,mesh,gtype,geomID,0);} }; template @@ -160,67 +187,77 @@ namespace embree template<> struct RefitBuilder<4,TriangleMesh,Triangle4> { RefitBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4MeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4MeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<4,TriangleMesh,Triangle4v> { RefitBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<4,TriangleMesh,Triangle4i> { RefitBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH4Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<4,QuadMesh,Quad4v> { RefitBuilder () {} - Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID) { return BVH4Quad4vMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4Quad4vMeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<4,UserGeometry,Object> { RefitBuilder () {} - Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID) { return BVH4VirtualMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH4VirtualMeshRefitSAH(bvh,mesh,geomID,0);} + }; + template<> + struct RefitBuilder<4,Instance,InstancePrimitive> { + RefitBuilder () {} + Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH4InstanceMeshRefitSAH(bvh,mesh,gtype,geomID,0);} }; template<> struct RefitBuilder<8,TriangleMesh,Triangle4> { RefitBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4MeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4MeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<8,TriangleMesh,Triangle4v> { RefitBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4vMeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<8,TriangleMesh,Triangle4i> { RefitBuilder () {} - Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID) { return BVH8Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, TriangleMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Triangle4iMeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<8,QuadMesh,Quad4v> { RefitBuilder () {} - Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID) { return BVH8Quad4vMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, QuadMesh* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8Quad4vMeshRefitSAH(bvh,mesh,geomID,0);} }; template<> struct RefitBuilder<8,UserGeometry,Object> { RefitBuilder () {} - Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID) { return BVH8VirtualMeshRefitSAH(bvh,mesh,geomID,0);} + Builder* operator () (void* bvh, UserGeometry* mesh, size_t geomID, Geometry::GTypeMask /*gtype*/) { return BVH8VirtualMeshRefitSAH(bvh,mesh,geomID,0);} + }; + template<> + struct RefitBuilder<8,Instance,InstancePrimitive> { + RefitBuilder () {} + Builder* operator () (void* bvh, Instance* mesh, size_t geomID, Geometry::GTypeMask gtype) { return BVH8InstanceMeshRefitSAH(bvh,mesh,gtype,geomID,0);} }; template struct MeshBuilder { MeshBuilder () {} - void operator () (void* bvh, Mesh* mesh, size_t geomID, bool useMortonBuilder, Builder*& builder) { + void operator () (void* bvh, Mesh* mesh, size_t geomID, Geometry::GTypeMask gtype, bool useMortonBuilder, Builder*& builder) { if(useMortonBuilder) { - builder = MortonBuilder()(bvh,mesh,geomID); + builder = MortonBuilder()(bvh,mesh,geomID,gtype); return; } switch (mesh->quality) { - case RTC_BUILD_QUALITY_LOW: builder = MortonBuilder()(bvh,mesh,geomID); break; + case RTC_BUILD_QUALITY_LOW: builder = MortonBuilder()(bvh,mesh,geomID,gtype); break; case RTC_BUILD_QUALITY_MEDIUM: - case RTC_BUILD_QUALITY_HIGH: builder = SAHBuilder()(bvh,mesh,geomID); break; - case RTC_BUILD_QUALITY_REFIT: builder = RefitBuilder()(bvh,mesh,geomID); break; + case RTC_BUILD_QUALITY_HIGH: builder = SAHBuilder()(bvh,mesh,geomID,gtype); break; + case RTC_BUILD_QUALITY_REFIT: builder = RefitBuilder()(bvh,mesh,geomID,gtype); break; default: throw_RTCError(RTC_ERROR_UNKNOWN,"invalid build quality"); } } diff --git a/kernels/bvh/bvh_collider.cpp b/kernels/bvh/bvh_collider.cpp index a27be8bae8..9428c0b88e 100644 --- a/kernels/bvh/bvh_collider.cpp +++ b/kernels/bvh/bvh_collider.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_collider.h" diff --git a/kernels/bvh/bvh_collider.h b/kernels/bvh/bvh_collider.h index ac4f99c96a..3c42f211c1 100644 --- a/kernels/bvh/bvh_collider.h +++ b/kernels/bvh/bvh_collider.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_factory.h b/kernels/bvh/bvh_factory.h index 54021ca6eb..453d455bd9 100644 --- a/kernels/bvh/bvh_factory.h +++ b/kernels/bvh/bvh_factory.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_intersector1.cpp b/kernels/bvh/bvh_intersector1.cpp index ea6adc2717..9594f402c3 100644 --- a/kernels/bvh/bvh_intersector1.cpp +++ b/kernels/bvh/bvh_intersector1.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector1.h" @@ -61,10 +61,10 @@ namespace embree assert(!(types & BVH_MB) || (ray.time() >= 0.0f && ray.time() <= 1.0f)); /* load the ray into SIMD registers */ - TravRay tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f)); + TravRay tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f)); /* initialize the node traverser */ - BVHNNodeTraverser1Hit nodeTraverser; + BVHNNodeTraverser1Hit nodeTraverser; /* pop loop */ while (true) pop: @@ -75,22 +75,16 @@ namespace embree NodeRef cur = NodeRef(stackPtr->ptr); /* if popped node is too far, pop next one */ -#if defined(__AVX512ER__) - /* much faster on KNL */ - if (unlikely(any(vfloat(*(float*)&stackPtr->dist) > tray.tfar))) - continue; -#else if (unlikely(*(float*)&stackPtr->dist > ray.tfar)) continue; -#endif /* downtraversal loop */ while (true) { /* intersect node */ - size_t mask; vfloat tNear; + size_t mask; vfloat tNear; STAT3(normal.trav_nodes,1,1,1); - bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray, ray.time(), tNear, mask); + bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray, ray.time(), tNear, mask); if (unlikely(!nodeIntersected)) { STAT3(normal.trav_nodes,-1,-1,-1); break; } /* if no child is hit, pop next node */ @@ -153,10 +147,10 @@ namespace embree assert(!(types & BVH_MB) || (ray.time() >= 0.0f && ray.time() <= 1.0f)); /* load the ray into SIMD registers */ - TravRay tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f)); + TravRay tray(ray.org, ray.dir, max(ray.tnear(), 0.0f), max(ray.tfar, 0.0f)); /* initialize the node traverser */ - BVHNNodeTraverser1Hit nodeTraverser; + BVHNNodeTraverser1Hit nodeTraverser; /* pop loop */ while (true) pop: @@ -170,9 +164,9 @@ namespace embree while (true) { /* intersect node */ - size_t mask; vfloat tNear; + size_t mask; vfloat tNear; STAT3(shadow.trav_nodes,1,1,1); - bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray, ray.time(), tNear, mask); + bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray, ray.time(), tNear, mask); if (unlikely(!nodeIntersected)) { STAT3(shadow.trav_nodes,-1,-1,-1); break; } /* if no child is hit, pop next node */ @@ -213,9 +207,6 @@ namespace embree static const size_t stackSize = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store - /* right now AVX512KNL SIMD extension only for standard node types */ - static const size_t Nx = (types == BVH_AN1 || types == BVH_QN1) ? vextend::size : N; - static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { const BVH* __restrict__ bvh = (const BVH*)This->ptr; @@ -238,7 +229,7 @@ namespace embree TravPointQuery tquery(query->p, context->query_radius); /* initialize the node traverser */ - BVHNNodeTraverser1Hit nodeTraverser; + BVHNNodeTraverser1Hit nodeTraverser; bool changed = false; float cull_radius = context->query_type == POINT_QUERY_TYPE_SPHERE diff --git a/kernels/bvh/bvh_intersector1.h b/kernels/bvh/bvh_intersector1.h index 1a269c319a..2df3d6eddb 100644 --- a/kernels/bvh/bvh_intersector1.h +++ b/kernels/bvh/bvh_intersector1.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -25,9 +25,6 @@ namespace embree static const size_t stackSize = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store - /* right now AVX512KNL SIMD extension only for standard node types */ - static const size_t Nx = (types == BVH_AN1 || types == BVH_QN1) ? vextend::size : N; - public: static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context); static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context); diff --git a/kernels/bvh/bvh_intersector1_bvh4.cpp b/kernels/bvh/bvh_intersector1_bvh4.cpp index 989f7354fd..831d613367 100644 --- a/kernels/bvh/bvh_intersector1_bvh4.cpp +++ b/kernels/bvh/bvh_intersector1_bvh4.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector1.cpp" @@ -21,15 +21,15 @@ namespace embree IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersectorRobust1,BVHNIntersector1<4 COMMA BVH_AN1_UN1 COMMA true COMMA VirtualCurveIntersector1 >)); IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH4OBBVirtualCurveIntersectorRobust1MB,BVHNIntersector1<4 COMMA BVH_AN2_AN4D_UN2 COMMA true COMMA VirtualCurveIntersector1 >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4Intersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4Intersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4vMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH4Triangle4iMBIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4vIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH4Quad4iIntersector1Moeller, BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); @@ -48,7 +48,7 @@ namespace embree IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR1(BVH4InstanceIntersector1,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 >)); IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR1(BVH4InstanceMBIntersector1,BVHNIntersector1<4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH4Triangle4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(QBVH4Quad4iIntersector1Pluecker,BVHNIntersector1<4 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); IF_ENABLED_GRIDS(DEFINE_INTERSECTOR1(BVH4GridIntersector1Moeller,BVHNIntersector1<4 COMMA BVH_AN1 COMMA false COMMA SubGridIntersector1Moeller<4 COMMA true> >)); diff --git a/kernels/bvh/bvh_intersector1_bvh8.cpp b/kernels/bvh/bvh_intersector1_bvh8.cpp index 00c1f6f7ea..430464e873 100644 --- a/kernels/bvh/bvh_intersector1_bvh8.cpp +++ b/kernels/bvh/bvh_intersector1_bvh8.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector1.cpp" @@ -17,17 +17,17 @@ namespace embree IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH8OBBVirtualCurveIntersectorRobust1,BVHNIntersector1<8 COMMA BVH_AN1_UN1 COMMA true COMMA VirtualCurveIntersector1 >)); IF_ENABLED_CURVES_OR_POINTS(DEFINE_INTERSECTOR1(BVH8OBBVirtualCurveIntersectorRobust1MB,BVHNIntersector1<8 COMMA BVH_AN2_AN4D_UN2 COMMA true COMMA VirtualCurveIntersector1 >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4Intersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4Intersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vIntersector1Woop, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vIntersector1Woop, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vMBIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iMBIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vMBIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iMBIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vMBIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iMBIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4vMBIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(BVH8Triangle4iMBIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH8Quad4vIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH8Quad4iIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersector1 > >)); @@ -37,8 +37,8 @@ namespace embree IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH8Quad4iMBIntersector1Moeller, BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(BVH8Quad4iMBIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH8Triangle4iIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH8Triangle4Intersector1Moeller,BVHNIntersector1<8 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH8Triangle4iIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR1(QBVH8Triangle4Intersector1Moeller,BVHNIntersector1<8 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR1(QBVH8Quad4iIntersector1Pluecker,BVHNIntersector1<8 COMMA BVH_QN1 COMMA false COMMA ArrayIntersector1 > >)); diff --git a/kernels/bvh/bvh_intersector_hybrid.cpp b/kernels/bvh/bvh_intersector_hybrid.cpp index d4adca24e7..8630a2bacb 100644 --- a/kernels/bvh/bvh_intersector_hybrid.cpp +++ b/kernels/bvh/bvh_intersector_hybrid.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.h" @@ -51,7 +51,8 @@ namespace embree stack[0].dist = neg_inf; /* load the ray into SIMD registers */ - TravRay tray1(k, tray.org, tray.dir, tray.rdir, tray.nearXYZ, tray.tnear[k], tray.tfar[k]); + TravRay tray1; + tray1.template init(k, tray.org, tray.dir, tray.rdir, tray.nearXYZ, tray.tnear[k], tray.tfar[k]); /* pop loop */ while (true) pop: @@ -62,22 +63,16 @@ namespace embree NodeRef cur = NodeRef(stackPtr->ptr); /* if popped node is too far, pop next one */ -#if defined(__AVX512ER__) - /* much faster on KNL */ - if (unlikely(any(vfloat(*(float*)&stackPtr->dist) > tray1.tfar))) - continue; -#else if (unlikely(*(float*)&stackPtr->dist > ray.tfar[k])) continue; -#endif /* downtraversal loop */ while (true) { /* intersect node */ - size_t mask; vfloat tNear; + size_t mask; vfloat tNear; STAT3(normal.trav_nodes, 1, 1, 1); - bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray1, ray.time()[k], tNear, mask); + bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray1, ray.time()[k], tNear, mask); if (unlikely(!nodeIntersected)) { STAT3(normal.trav_nodes,-1,-1,-1); break; } /* if no child is hit, pop next node */ @@ -85,7 +80,7 @@ namespace embree goto pop; /* select next child and push other children */ - BVHNNodeTraverser1Hit::traverseClosestHit(cur, mask, tNear, stackPtr, stackEnd); + BVHNNodeTraverser1Hit::traverseClosestHit(cur, mask, tNear, stackPtr, stackEnd); } /* this is a leaf node */ @@ -235,7 +230,7 @@ namespace embree continue; /* switch to single ray traversal */ -#if (!defined(__WIN32__) || defined(__X86_64__)) && defined(__SSE4_2__) +#if (!defined(__WIN32__) || defined(__X86_64__)) && ((defined(__aarch64__)) || defined(__SSE4_2__)) #if FORCE_SINGLE_MODE == 0 if (single) #endif @@ -415,7 +410,8 @@ namespace embree tray.tnear = select(octant_valid, org_ray_tnear, vfloat(pos_inf)); tray.tfar = select(octant_valid, org_ray_tfar , vfloat(neg_inf)); - Frustum frustum(octant_valid, tray.org, tray.rdir, tray.tnear, tray.tfar, N); + Frustum frustum; + frustum.template init(octant_valid, tray.org, tray.rdir, tray.tnear, tray.tfar, N); StackItemT stack[stackSizeSingle]; // stack of nodes StackItemT* stackPtr = stack + 1; // current stack pointer @@ -442,8 +438,8 @@ namespace embree const NodeRef nodeRef = cur; const AABBNode* __restrict__ const node = nodeRef.getAABBNode(); - vfloat fmin; - size_t m_frustum_node = intersectNodeFrustum(node, frustum, fmin); + vfloat fmin; + size_t m_frustum_node = intersectNodeFrustum(node, frustum, fmin); if (unlikely(!m_frustum_node)) goto pop; cur = BVH::emptyNode; @@ -518,7 +514,7 @@ namespace embree if (likely(any((ray.tfar < tray.tfar) & valid_leaf))) { tray.tfar = select(valid_leaf, ray.tfar, tray.tfar); - frustum.updateMaxDist(tray.tfar); + frustum.template updateMaxDist(tray.tfar); } if (unlikely(lazy_node)) { @@ -552,7 +548,8 @@ namespace embree stack[0] = root; /* load the ray into SIMD registers */ - TravRay tray1(k, tray.org, tray.dir, tray.rdir, tray.nearXYZ, tray.tnear[k], tray.tfar[k]); + TravRay tray1; + tray1.template init(k, tray.org, tray.dir, tray.rdir, tray.nearXYZ, tray.tnear[k], tray.tfar[k]); /* pop loop */ while (true) pop: @@ -566,9 +563,9 @@ namespace embree while (true) { /* intersect node */ - size_t mask; vfloat tNear; + size_t mask; vfloat tNear; STAT3(shadow.trav_nodes, 1, 1, 1); - bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray1, ray.time()[k], tNear, mask); + bool nodeIntersected = BVHNNodeIntersector1::intersect(cur, tray1, ray.time()[k], tNear, mask); if (unlikely(!nodeIntersected)) { STAT3(shadow.trav_nodes,-1,-1,-1); break; } /* if no child is hit, pop next node */ @@ -576,7 +573,7 @@ namespace embree goto pop; /* select next child and push other children */ - BVHNNodeTraverser1Hit::traverseAnyHit(cur, mask, tNear, stackPtr, stackEnd); + BVHNNodeTraverser1Hit::traverseAnyHit(cur, mask, tNear, stackPtr, stackEnd); } /* this is a leaf node */ @@ -679,7 +676,7 @@ namespace embree continue; /* switch to single ray traversal */ -#if (!defined(__WIN32__) || defined(__X86_64__)) && defined(__SSE4_2__) +#if (!defined(__WIN32__) || defined(__X86_64__)) && ((defined(__aarch64__)) || defined(__SSE4_2__)) #if FORCE_SINGLE_MODE == 0 if (single) #endif @@ -826,7 +823,8 @@ namespace embree tray.tnear = select(octant_valid, org_ray_tnear, vfloat(pos_inf)); tray.tfar = select(octant_valid, org_ray_tfar, vfloat(neg_inf)); - const Frustum frustum(octant_valid, tray.org, tray.rdir, tray.tnear, tray.tfar, N); + Frustum frustum; + frustum.template init(octant_valid, tray.org, tray.rdir, tray.tnear, tray.tfar, N); StackItemMaskT stack[stackSizeSingle]; // stack of nodes StackItemMaskT* stackPtr = stack + 1; // current stack pointer @@ -853,8 +851,8 @@ namespace embree const NodeRef nodeRef = cur; const AABBNode* __restrict__ const node = nodeRef.getAABBNode(); - vfloat fmin; - size_t m_frustum_node = intersectNodeFrustum(node, frustum, fmin); + vfloat fmin; + size_t m_frustum_node = intersectNodeFrustum(node, frustum, fmin); if (unlikely(!m_frustum_node)) goto pop; cur = BVH::emptyNode; @@ -864,6 +862,7 @@ namespace embree //STAT3(normal.trav_hit_boxes[popcnt(m_frustum_node)], 1, 1, 1); #endif size_t num_child_hits = 0; + (void) num_child_hits; do { const size_t i = bscf(m_frustum_node); vfloat lnearP; diff --git a/kernels/bvh/bvh_intersector_hybrid.h b/kernels/bvh/bvh_intersector_hybrid.h index d764cc928d..50ebf375c4 100644 --- a/kernels/bvh/bvh_intersector_hybrid.h +++ b/kernels/bvh/bvh_intersector_hybrid.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -19,9 +19,6 @@ namespace embree template class BVHNIntersectorKHybrid { - /* right now AVX512KNL SIMD extension only for standard node types */ - static const size_t Nx = types == BVH_AN1 ? vextend::size : N; - /* shortcuts for frequently used types */ typedef typename PrimitiveIntersectorK::Precalculations Precalculations; typedef typename PrimitiveIntersectorK::Primitive Primitive; diff --git a/kernels/bvh/bvh_intersector_hybrid16_bvh4.cpp b/kernels/bvh/bvh_intersector_hybrid16_bvh4.cpp index 57e2fbd8f3..8909bbac53 100644 --- a/kernels/bvh/bvh_intersector_hybrid16_bvh4.cpp +++ b/kernels/bvh/bvh_intersector_hybrid16_bvh4.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.cpp" @@ -11,16 +11,16 @@ namespace embree /// BVH4Intersector16 Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4Intersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4Intersector16HybridMoellerNoFilter, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4vIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4Intersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4Intersector16HybridMoellerNoFilter, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller <4 COMMA 16 COMMA false> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4vIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4vMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4vMBIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iMBIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4vMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4vMBIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH4Triangle4iMBIntersector16HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR16(BVH4Quad4vIntersector16HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA QuadMvIntersectorKMoeller <4 COMMA 16 COMMA true > > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR16(BVH4Quad4vIntersector16HybridMoellerNoFilter,BVHNIntersectorKHybrid<4 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA QuadMvIntersectorKMoeller <4 COMMA 16 COMMA false> > >)); diff --git a/kernels/bvh/bvh_intersector_hybrid16_bvh8.cpp b/kernels/bvh/bvh_intersector_hybrid16_bvh8.cpp index 1b8f85a241..152ad28000 100644 --- a/kernels/bvh/bvh_intersector_hybrid16_bvh8.cpp +++ b/kernels/bvh/bvh_intersector_hybrid16_bvh8.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.cpp" @@ -11,16 +11,16 @@ namespace embree /// BVH8Intersector16 Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4Intersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4Intersector16HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4vIntersector16HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iIntersector16HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4Intersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4Intersector16HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMIntersectorKMoeller <4 COMMA 16 COMMA false> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKMoeller <4 COMMA 16 COMMA true > > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4vIntersector16HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iIntersector16HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiIntersectorKPluecker<4 COMMA 16 COMMA true > > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4vMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4vMBIntersector16HybridPluecker,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iMBIntersector16HybridPluecker,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4vMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iMBIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKMoeller <4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4vMBIntersector16HybridPluecker,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMvMBIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR16(BVH8Triangle4iMBIntersector16HybridPluecker,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<16 COMMA TriangleMiMBIntersectorKPluecker<4 COMMA 16 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR16(BVH8Quad4vIntersector16HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA QuadMvIntersectorKMoeller <4 COMMA 16 COMMA true > > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR16(BVH8Quad4vIntersector16HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 16 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<16 COMMA QuadMvIntersectorKMoeller <4 COMMA 16 COMMA false> > >)); diff --git a/kernels/bvh/bvh_intersector_hybrid4_bvh4.cpp b/kernels/bvh/bvh_intersector_hybrid4_bvh4.cpp index 34bafc31c5..2137da6a25 100644 --- a/kernels/bvh/bvh_intersector_hybrid4_bvh4.cpp +++ b/kernels/bvh/bvh_intersector_hybrid4_bvh4.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.cpp" @@ -11,16 +11,16 @@ namespace embree /// BVH4Intersector4 Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4Intersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4Intersector4HybridMoellerNoFilter, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4vIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4Intersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4Intersector4HybridMoellerNoFilter, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller <4 COMMA 4 COMMA false> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4vIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4vMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4vMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4vMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4vMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH4Triangle4iMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR4(BVH4Quad4vIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA QuadMvIntersectorKMoeller <4 COMMA 4 COMMA true > > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR4(BVH4Quad4vIntersector4HybridMoellerNoFilter,BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA QuadMvIntersectorKMoeller <4 COMMA 4 COMMA false> > >)); @@ -49,6 +49,8 @@ namespace embree IF_ENABLED_INSTANCE(DEFINE_INTERSECTOR4(BVH4InstanceMBIntersector4Chunk, BVHNIntersectorKChunk<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA InstanceIntersectorKMB<4>> >)); IF_ENABLED_GRIDS(DEFINE_INTERSECTOR4(BVH4GridIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA SubGridIntersectorKMoeller <4 COMMA 4 COMMA true> >)); + //IF_ENABLED_GRIDS(DEFINE_INTERSECTOR4(BVH4GridIntersector4HybridMoeller, BVHNIntersectorKChunk<4 COMMA 4 COMMA BVH_AN1 COMMA false COMMA SubGridIntersectorKMoeller <4 COMMA 4 COMMA true> >)); + IF_ENABLED_GRIDS(DEFINE_INTERSECTOR4(BVH4GridMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA SubGridMBIntersectorKPluecker <4 COMMA 4 COMMA true> >)); IF_ENABLED_GRIDS(DEFINE_INTERSECTOR4(BVH4GridIntersector4HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 4 COMMA BVH_AN1 COMMA true COMMA SubGridIntersectorKPluecker <4 COMMA 4 COMMA true> >)); diff --git a/kernels/bvh/bvh_intersector_hybrid4_bvh8.cpp b/kernels/bvh/bvh_intersector_hybrid4_bvh8.cpp index 551e7d7fe7..10f717556a 100644 --- a/kernels/bvh/bvh_intersector_hybrid4_bvh8.cpp +++ b/kernels/bvh/bvh_intersector_hybrid4_bvh8.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.cpp" @@ -11,16 +11,16 @@ namespace embree /// BVH8Intersector4 Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4Intersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4Intersector4HybridMoellerNoFilter, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4vIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4Intersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4Intersector4HybridMoellerNoFilter, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMIntersectorKMoeller <4 COMMA 4 COMMA false> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4vIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4vMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4vMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4vMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iMBIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4vMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMvMBIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR4(BVH8Triangle4iMBIntersector4HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<4 COMMA TriangleMiMBIntersectorKPluecker<4 COMMA 4 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR4(BVH8Quad4vIntersector4HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA QuadMvIntersectorKMoeller <4 COMMA 4 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR4(BVH8Quad4vIntersector4HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 4 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<4 COMMA QuadMvIntersectorKMoeller <4 COMMA 4 COMMA false> > >)); diff --git a/kernels/bvh/bvh_intersector_hybrid8_bvh4.cpp b/kernels/bvh/bvh_intersector_hybrid8_bvh4.cpp index 50a78193a0..327c7dcd43 100644 --- a/kernels/bvh/bvh_intersector_hybrid8_bvh4.cpp +++ b/kernels/bvh/bvh_intersector_hybrid8_bvh4.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.cpp" @@ -11,16 +11,16 @@ namespace embree /// BVH4Intersector8 Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4Intersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4Intersector8HybridMoellerNoFilter, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4vIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4Intersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4Intersector8HybridMoellerNoFilter, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller <4 COMMA 8 COMMA false> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4vIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4vMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4vMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4vMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4vMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH4Triangle4iMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR8(BVH4Quad4vIntersector8HybridMoeller, BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA QuadMvIntersectorKMoeller<4 COMMA 8 COMMA true > > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR8(BVH4Quad4vIntersector8HybridMoellerNoFilter,BVHNIntersectorKHybrid<4 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA QuadMvIntersectorKMoeller<4 COMMA 8 COMMA false> > >)); diff --git a/kernels/bvh/bvh_intersector_hybrid8_bvh8.cpp b/kernels/bvh/bvh_intersector_hybrid8_bvh8.cpp index a74078d1c4..d12dd0b861 100644 --- a/kernels/bvh/bvh_intersector_hybrid8_bvh8.cpp +++ b/kernels/bvh/bvh_intersector_hybrid8_bvh8.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_hybrid.cpp" @@ -11,16 +11,16 @@ namespace embree /// BVH8Intersector8 Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4Intersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4Intersector8HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4vIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4Intersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4Intersector8HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMIntersectorKMoeller <4 COMMA 8 COMMA false> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4vIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4vMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKMoeller > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4vMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKPluecker > >)); - IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKPluecker > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4vMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iMBIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA false COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4vMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMvMBIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); + IF_ENABLED_TRIS(DEFINE_INTERSECTOR8(BVH8Triangle4iMBIntersector8HybridPluecker, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN2_AN4D COMMA true COMMA ArrayIntersectorK_1<8 COMMA TriangleMiMBIntersectorKPluecker<4 COMMA 8 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR8(BVH8Quad4vIntersector8HybridMoeller, BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA QuadMvIntersectorKMoeller <4 COMMA 8 COMMA true> > >)); IF_ENABLED_QUADS(DEFINE_INTERSECTOR8(BVH8Quad4vIntersector8HybridMoellerNoFilter,BVHNIntersectorKHybrid<8 COMMA 8 COMMA BVH_AN1 COMMA false COMMA ArrayIntersectorK_1<8 COMMA QuadMvIntersectorKMoeller <4 COMMA 8 COMMA false> > >)); diff --git a/kernels/bvh/bvh_intersector_stream.cpp b/kernels/bvh/bvh_intersector_stream.cpp index 9ff20878c6..4a74d8468d 100644 --- a/kernels/bvh/bvh_intersector_stream.cpp +++ b/kernels/bvh/bvh_intersector_stream.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_stream.h" @@ -29,8 +29,8 @@ namespace embree (int)1 << 24, (int)1 << 25, (int)1 << 26, (int)1 << 27, (int)1 << 28, (int)1 << 29, (int)1 << 30, (int)1 << 31 }; - template - __forceinline void BVHNIntersectorStream::intersect(Accel::Intersectors* __restrict__ This, + template + __forceinline void BVHNIntersectorStream::intersect(Accel::Intersectors* __restrict__ This, RayHitN** inputPackets, size_t numOctantRays, IntersectContext* context) @@ -45,9 +45,9 @@ namespace embree intersectCoherent(This, (RayHitK**)inputPackets, numOctantRays, context); } - template + template template - __forceinline void BVHNIntersectorStream::intersectCoherent(Accel::Intersectors* __restrict__ This, + __forceinline void BVHNIntersectorStream::intersectCoherent(Accel::Intersectors* __restrict__ This, RayHitK** inputPackets, size_t numOctantRays, IntersectContext* context) @@ -105,11 +105,11 @@ namespace embree __aligned(64) size_t maskK[N]; for (size_t i = 0; i < N; i++) maskK[i] = m_trav_active; - vfloat dist; + vfloat dist; const size_t m_node_hit = traverseCoherentStream(m_trav_active, packets, node, frustum, maskK, dist); if (unlikely(m_node_hit == 0)) goto pop; - BVHNNodeTraverserStreamHitCoherent::traverseClosestHit(cur, m_trav_active, vbool((int)m_node_hit), dist, (size_t*)maskK, stackPtr); + BVHNNodeTraverserStreamHitCoherent::traverseClosestHit(cur, m_trav_active, vbool((int)m_node_hit), dist, (size_t*)maskK, stackPtr); assert(m_trav_active); } @@ -153,8 +153,8 @@ namespace embree } // traversal + intersection } - template - __forceinline void BVHNIntersectorStream::occluded(Accel::Intersectors* __restrict__ This, + template + __forceinline void BVHNIntersectorStream::occluded(Accel::Intersectors* __restrict__ This, RayN** inputPackets, size_t numOctantRays, IntersectContext* context) @@ -170,9 +170,9 @@ namespace embree occludedIncoherent(This, (RayK**)inputPackets, numOctantRays, context); } - template + template template - __noinline void BVHNIntersectorStream::occludedCoherent(Accel::Intersectors* __restrict__ This, + __noinline void BVHNIntersectorStream::occludedCoherent(Accel::Intersectors* __restrict__ This, RayK** inputPackets, size_t numOctantRays, IntersectContext* context) @@ -235,11 +235,11 @@ namespace embree for (size_t i = 0; i < N; i++) maskK[i] = m_trav_active; - vfloat dist; + vfloat dist; const size_t m_node_hit = traverseCoherentStream(m_trav_active, packets, node, frustum, maskK, dist); if (unlikely(m_node_hit == 0)) goto pop; - BVHNNodeTraverserStreamHitCoherent::traverseAnyHit(cur, m_trav_active, vbool((int)m_node_hit), (size_t*)maskK, stackPtr); + BVHNNodeTraverserStreamHitCoherent::traverseAnyHit(cur, m_trav_active, vbool((int)m_node_hit), (size_t*)maskK, stackPtr); assert(m_trav_active); } @@ -283,9 +283,9 @@ namespace embree } - template + template template - __forceinline void BVHNIntersectorStream::occludedIncoherent(Accel::Intersectors* __restrict__ This, + __forceinline void BVHNIntersectorStream::occludedIncoherent(Accel::Intersectors* __restrict__ This, RayK** inputPackets, size_t numOctantRays, IntersectContext* context) @@ -338,13 +338,13 @@ namespace embree if (unlikely(cur.isLeaf())) break; const AABBNode* __restrict__ const node = cur.getAABBNode(); - const vint vmask = traverseIncoherentStream(cur_mask, packet, node, nf, shiftTable); + const vint vmask = traverseIncoherentStream(cur_mask, packet, node, nf, shiftTable); - size_t mask = movemask(vmask != vint(zero)); + size_t mask = movemask(vmask != vint(zero)); if (unlikely(mask == 0)) goto pop; - __aligned(64) unsigned int child_mask[Nx]; - vint::storeu(child_mask, vmask); // this explicit store here causes much better code generation + __aligned(64) unsigned int child_mask[N]; + vint::storeu(child_mask, vmask); // this explicit store here causes much better code generation /*! one child is hit, continue with that child */ size_t r = bscf(mask); @@ -415,22 +415,22 @@ namespace embree template struct Triangle4IntersectorStreamMoeller { - template using Type = ArrayIntersectorKStream>; + template using Type = ArrayIntersectorKStream>; }; template struct Triangle4vIntersectorStreamPluecker { - template using Type = ArrayIntersectorKStream>; + template using Type = ArrayIntersectorKStream>; }; template struct Triangle4iIntersectorStreamMoeller { - template using Type = ArrayIntersectorKStream>; + template using Type = ArrayIntersectorKStream>; }; template struct Triangle4iIntersectorStreamPluecker { - template using Type = ArrayIntersectorKStream>; + template using Type = ArrayIntersectorKStream>; }; template @@ -465,8 +465,8 @@ namespace embree // ===================================================================================================== // ===================================================================================================== - template - void BVHNIntersectorStreamPacketFallback::intersect(Accel::Intersectors* __restrict__ This, + template + void BVHNIntersectorStreamPacketFallback::intersect(Accel::Intersectors* __restrict__ This, RayHitN** inputRays, size_t numTotalRays, IntersectContext* context) @@ -477,8 +477,8 @@ namespace embree intersectK(This, (RayHitK**)inputRays, numTotalRays, context); } - template - void BVHNIntersectorStreamPacketFallback::occluded(Accel::Intersectors* __restrict__ This, + template + void BVHNIntersectorStreamPacketFallback::occluded(Accel::Intersectors* __restrict__ This, RayN** inputRays, size_t numTotalRays, IntersectContext* context) @@ -489,9 +489,9 @@ namespace embree occludedK(This, (RayK**)inputRays, numTotalRays, context); } - template + template template - __noinline void BVHNIntersectorStreamPacketFallback::intersectK(Accel::Intersectors* __restrict__ This, + __noinline void BVHNIntersectorStreamPacketFallback::intersectK(Accel::Intersectors* __restrict__ This, RayHitK** inputRays, size_t numTotalRays, IntersectContext* context) @@ -507,9 +507,9 @@ namespace embree } } - template + template template - __noinline void BVHNIntersectorStreamPacketFallback::occludedK(Accel::Intersectors* __restrict__ This, + __noinline void BVHNIntersectorStreamPacketFallback::occludedK(Accel::Intersectors* __restrict__ This, RayK** inputRays, size_t numTotalRays, IntersectContext* context) diff --git a/kernels/bvh/bvh_intersector_stream.h b/kernels/bvh/bvh_intersector_stream.h index f5beb6ca91..c7e040fadb 100644 --- a/kernels/bvh/bvh_intersector_stream.h +++ b/kernels/bvh/bvh_intersector_stream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -12,11 +12,9 @@ namespace embree namespace isa { /*! BVH ray stream intersector. */ - template + template class BVHNIntersectorStream { - static const int Nxd = (Nx == N) ? N : Nx/2; - /* shortcuts for frequently used types */ template using PrimitiveIntersectorK = typename PrimitiveIntersector::template Type; template using PrimitiveK = typename PrimitiveIntersectorK::PrimitiveK; @@ -128,13 +126,13 @@ namespace embree const AABBNode* __restrict__ node, const Frustum& frustum, size_t* maskK, - vfloat& dist) + vfloat& dist) { - size_t m_node_hit = intersectNodeFrustum(node, frustum, dist); + size_t m_node_hit = intersectNodeFrustum(node, frustum, dist); const size_t first_index = bsf(m_active); const size_t first_packetID = first_index / K; const size_t first_rayID = first_index % K; - size_t m_first_hit = intersectNode1(node, packets[first_packetID], first_rayID, frustum.nf); + size_t m_first_hit = intersectNode1(node, packets[first_packetID], first_rayID, frustum.nf); /* this make traversal independent of the ordering of rays */ size_t m_node = m_node_hit ^ m_first_hit; @@ -150,20 +148,20 @@ namespace embree // TODO: explicit 16-wide path for KNL template - __forceinline static vint traverseIncoherentStream(size_t m_active, + __forceinline static vint traverseIncoherentStream(size_t m_active, TravRayKStreamFast* __restrict__ packets, const AABBNode* __restrict__ node, const NearFarPrecalculations& nf, const int shiftTable[32]) { - const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); - const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); - const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); - const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); - const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); - const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); + const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); + const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); + const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); + const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); + const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); + const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); assert(m_active); - vint vmask(zero); + vint vmask(zero); do { STAT3(shadow.trav_nodes,1,1,1); @@ -171,47 +169,52 @@ namespace embree assert(rayID < MAX_INTERNAL_STREAM_SIZE); TravRayKStream &p = packets[rayID / K]; const size_t i = rayID % K; - const vint bitmask(shiftTable[rayID]); - const vfloat tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]); - const vfloat tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]); - const vfloat tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]); - const vfloat tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]); - const vfloat tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]); - const vfloat tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]); - const vfloat tNear = maxi(tNearX, tNearY, tNearZ, vfloat(p.tnear[i])); - const vfloat tFar = mini(tFarX , tFarY , tFarZ, vfloat(p.tfar[i])); - -#if defined(__AVX512ER__) - const vboolx m_node((1 << N)-1); - const vbool hit_mask = le(m_node, tNear, tFar); - vmask = mask_or(hit_mask, vmask, vmask, bitmask); + const vint bitmask(shiftTable[rayID]); + +#if defined (__aarch64__) + const vfloat tNearX = madd(bminX, p.rdir.x[i], p.neg_org_rdir.x[i]); + const vfloat tNearY = madd(bminY, p.rdir.y[i], p.neg_org_rdir.y[i]); + const vfloat tNearZ = madd(bminZ, p.rdir.z[i], p.neg_org_rdir.z[i]); + const vfloat tFarX = madd(bmaxX, p.rdir.x[i], p.neg_org_rdir.x[i]); + const vfloat tFarY = madd(bmaxY, p.rdir.y[i], p.neg_org_rdir.y[i]); + const vfloat tFarZ = madd(bmaxZ, p.rdir.z[i], p.neg_org_rdir.z[i]); #else - const vbool hit_mask = tNear <= tFar; + const vfloat tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]); + const vfloat tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]); + const vfloat tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]); + const vfloat tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]); + const vfloat tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]); + const vfloat tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]); +#endif + + const vfloat tNear = maxi(tNearX, tNearY, tNearZ, vfloat(p.tnear[i])); + const vfloat tFar = mini(tFarX , tFarY , tFarZ, vfloat(p.tfar[i])); + + const vbool hit_mask = tNear <= tFar; #if defined(__AVX2__) - vmask = vmask | (bitmask & vint(hit_mask)); + vmask = vmask | (bitmask & vint(hit_mask)); #else vmask = select(hit_mask, vmask | bitmask, vmask); -#endif #endif } while(m_active); return vmask; } template - __forceinline static vint traverseIncoherentStream(size_t m_active, + __forceinline static vint traverseIncoherentStream(size_t m_active, TravRayKStreamRobust* __restrict__ packets, const AABBNode* __restrict__ node, const NearFarPrecalculations& nf, const int shiftTable[32]) { - const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); - const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); - const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); - const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); - const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); - const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); + const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); + const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); + const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); + const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); + const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); + const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); assert(m_active); - vint vmask(zero); + vint vmask(zero); do { STAT3(shadow.trav_nodes,1,1,1); @@ -219,28 +222,22 @@ namespace embree assert(rayID < MAX_INTERNAL_STREAM_SIZE); TravRayKStream &p = packets[rayID / K]; const size_t i = rayID % K; - const vint bitmask(shiftTable[rayID]); - const vfloat tNearX = (bminX - p.org.x[i]) * p.rdir.x[i]; - const vfloat tNearY = (bminY - p.org.y[i]) * p.rdir.y[i]; - const vfloat tNearZ = (bminZ - p.org.z[i]) * p.rdir.z[i]; - const vfloat tFarX = (bmaxX - p.org.x[i]) * p.rdir.x[i]; - const vfloat tFarY = (bmaxY - p.org.y[i]) * p.rdir.y[i]; - const vfloat tFarZ = (bmaxZ - p.org.z[i]) * p.rdir.z[i]; - const vfloat tNear = maxi(tNearX, tNearY, tNearZ, vfloat(p.tnear[i])); - const vfloat tFar = mini(tFarX , tFarY , tFarZ, vfloat(p.tfar[i])); + const vint bitmask(shiftTable[rayID]); + const vfloat tNearX = (bminX - p.org.x[i]) * p.rdir.x[i]; + const vfloat tNearY = (bminY - p.org.y[i]) * p.rdir.y[i]; + const vfloat tNearZ = (bminZ - p.org.z[i]) * p.rdir.z[i]; + const vfloat tFarX = (bmaxX - p.org.x[i]) * p.rdir.x[i]; + const vfloat tFarY = (bmaxY - p.org.y[i]) * p.rdir.y[i]; + const vfloat tFarZ = (bmaxZ - p.org.z[i]) * p.rdir.z[i]; + const vfloat tNear = maxi(tNearX, tNearY, tNearZ, vfloat(p.tnear[i])); + const vfloat tFar = mini(tFarX , tFarY , tFarZ, vfloat(p.tfar[i])); const float round_down = 1.0f-2.0f*float(ulp); const float round_up = 1.0f+2.0f*float(ulp); -#if defined(__AVX512ER__) - const vboolx m_node((1 << N)-1); - const vbool hit_mask = le(m_node, round_down*tNear, round_up*tFar); - vmask = mask_or(hit_mask, vmask, vmask, bitmask); -#else - const vbool hit_mask = round_down*tNear <= round_up*tFar; + const vbool hit_mask = round_down*tNear <= round_up*tFar; #if defined(__AVX2__) - vmask = vmask | (bitmask & vint(hit_mask)); + vmask = vmask | (bitmask & vint(hit_mask)); #else vmask = select(hit_mask, vmask | bitmask, vmask); -#endif #endif } while(m_active); return vmask; @@ -266,7 +263,7 @@ namespace embree /*! BVH ray stream intersector with direct fallback to packets. */ - template + template class BVHNIntersectorStreamPacketFallback { public: diff --git a/kernels/bvh/bvh_intersector_stream_bvh4.cpp b/kernels/bvh/bvh_intersector_stream_bvh4.cpp index 22956c2e81..c3e5f137b8 100644 --- a/kernels/bvh/bvh_intersector_stream_bvh4.cpp +++ b/kernels/bvh/bvh_intersector_stream_bvh4.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_stream.cpp" @@ -12,25 +12,25 @@ namespace embree /// General BVHIntersectorStreamPacketFallback Intersector //////////////////////////////////////////////////////////////////////////////// - DEFINE_INTERSECTORN(BVH4IntersectorStreamPacketFallback,BVHNIntersectorStreamPacketFallback); + DEFINE_INTERSECTORN(BVH4IntersectorStreamPacketFallback,BVHNIntersectorStreamPacketFallback<4>); //////////////////////////////////////////////////////////////////////////////// /// BVH4IntersectorStream Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4iIntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4vIntersectorStreamPluecker, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4iIntersectorStreamPluecker, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4IntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4IntersectorStreamMoellerNoFilter, BVHNIntersectorStream>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4iIntersectorStreamMoeller, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA Triangle4iIntersectorStreamMoeller>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4vIntersectorStreamPluecker, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA true COMMA Triangle4vIntersectorStreamPluecker>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4iIntersectorStreamPluecker, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA true COMMA Triangle4iIntersectorStreamPluecker>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4IntersectorStreamMoeller, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA Triangle4IntersectorStreamMoeller>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH4Triangle4IntersectorStreamMoellerNoFilter, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA Triangle4IntersectorStreamMoeller>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4vIntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4vIntersectorStreamMoellerNoFilter,BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4iIntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4vIntersectorStreamPluecker, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4iIntersectorStreamPluecker, BVHNIntersectorStream>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4vIntersectorStreamMoeller, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA Quad4vIntersectorStreamMoeller>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4vIntersectorStreamMoellerNoFilter,BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA Quad4vIntersectorStreamMoeller>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4iIntersectorStreamMoeller, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA Quad4iIntersectorStreamMoeller>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4vIntersectorStreamPluecker, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA true COMMA Quad4vIntersectorStreamPluecker>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH4Quad4iIntersectorStreamPluecker, BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA true COMMA Quad4iIntersectorStreamPluecker>)); - IF_ENABLED_USER(DEFINE_INTERSECTORN(BVH4VirtualIntersectorStream,BVHNIntersectorStream)); - IF_ENABLED_INSTANCE(DEFINE_INTERSECTORN(BVH4InstanceIntersectorStream,BVHNIntersectorStream)); + IF_ENABLED_USER(DEFINE_INTERSECTORN(BVH4VirtualIntersectorStream,BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA ObjectIntersectorStream>)); + IF_ENABLED_INSTANCE(DEFINE_INTERSECTORN(BVH4InstanceIntersectorStream,BVHNIntersectorStream<4 COMMA BVH_AN1 COMMA false COMMA InstanceIntersectorStream>)); } } diff --git a/kernels/bvh/bvh_intersector_stream_bvh8.cpp b/kernels/bvh/bvh_intersector_stream_bvh8.cpp index 9ea4352389..15aae92088 100644 --- a/kernels/bvh/bvh_intersector_stream_bvh8.cpp +++ b/kernels/bvh/bvh_intersector_stream_bvh8.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_stream.cpp" @@ -11,25 +11,25 @@ namespace embree /// General BVHIntersectorStreamPacketFallback Intersector //////////////////////////////////////////////////////////////////////////////// - DEFINE_INTERSECTORN(BVH8IntersectorStreamPacketFallback,BVHNIntersectorStreamPacketFallback); + DEFINE_INTERSECTORN(BVH8IntersectorStreamPacketFallback,BVHNIntersectorStreamPacketFallback<8>); //////////////////////////////////////////////////////////////////////////////// /// BVH8IntersectorStream Definitions //////////////////////////////////////////////////////////////////////////////// - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4IntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4IntersectorStreamMoellerNoFilter, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4iIntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4vIntersectorStreamPluecker, BVHNIntersectorStream>)); - IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4iIntersectorStreamPluecker, BVHNIntersectorStream>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4IntersectorStreamMoeller, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA Triangle4IntersectorStreamMoeller>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4IntersectorStreamMoellerNoFilter, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA Triangle4IntersectorStreamMoeller>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4iIntersectorStreamMoeller, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA Triangle4iIntersectorStreamMoeller>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4vIntersectorStreamPluecker, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA true COMMA Triangle4vIntersectorStreamPluecker>)); + IF_ENABLED_TRIS(DEFINE_INTERSECTORN(BVH8Triangle4iIntersectorStreamPluecker, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA true COMMA Triangle4iIntersectorStreamPluecker>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4vIntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4vIntersectorStreamMoellerNoFilter, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4iIntersectorStreamMoeller, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4vIntersectorStreamPluecker, BVHNIntersectorStream>)); - IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4iIntersectorStreamPluecker, BVHNIntersectorStream>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4vIntersectorStreamMoeller, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA Quad4vIntersectorStreamMoeller>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4vIntersectorStreamMoellerNoFilter, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA Quad4vIntersectorStreamMoeller>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4iIntersectorStreamMoeller, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA Quad4iIntersectorStreamMoeller>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4vIntersectorStreamPluecker, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA true COMMA Quad4vIntersectorStreamPluecker>)); + IF_ENABLED_QUADS(DEFINE_INTERSECTORN(BVH8Quad4iIntersectorStreamPluecker, BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA true COMMA Quad4iIntersectorStreamPluecker>)); - IF_ENABLED_USER(DEFINE_INTERSECTORN(BVH8VirtualIntersectorStream,BVHNIntersectorStream)); - IF_ENABLED_INSTANCE(DEFINE_INTERSECTORN(BVH8InstanceIntersectorStream,BVHNIntersectorStream)); + IF_ENABLED_USER(DEFINE_INTERSECTORN(BVH8VirtualIntersectorStream,BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA ObjectIntersectorStream>)); + IF_ENABLED_INSTANCE(DEFINE_INTERSECTORN(BVH8InstanceIntersectorStream,BVHNIntersectorStream<8 COMMA BVH_AN1 COMMA false COMMA InstanceIntersectorStream>)); } } diff --git a/kernels/bvh/bvh_intersector_stream_filters.cpp b/kernels/bvh/bvh_intersector_stream_filters.cpp index ddf8bd1a21..b858eb163f 100644 --- a/kernels/bvh/bvh_intersector_stream_filters.cpp +++ b/kernels/bvh/bvh_intersector_stream_filters.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_intersector_stream_filters.h" @@ -31,7 +31,7 @@ namespace embree const vint offset = vij * int(stride); const size_t packetIndex = j / K; - RayTypeK ray = rayN.getRayByOffset(valid, offset); + RayTypeK ray = rayN.getRayByOffset(valid, offset); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); @@ -114,7 +114,7 @@ namespace embree const vint offset = *(vint*)&rayIDs[j] * int(stride); RayK& ray = rays[j/K]; rayPtrs[j/K] = &ray; - ray = rayN.getRayByOffset(valid, offset); + ray = rayN.getRayByOffset(valid, offset); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); } @@ -126,7 +126,7 @@ namespace embree const vint vi = vint(int(j)) + vint(step); const vbool valid = vi < vint(int(numOctantRays)); const vint offset = *(vint*)&rayIDs[j] * int(stride); - rayN.setHitByOffset(valid, offset, rays[j/K]); + rayN.setHitByOffset(valid, offset, rays[j/K]); } raysInOctant[curOctant] = 0; @@ -141,12 +141,12 @@ namespace embree vbool valid = vi < vint(int(N)); const vint offset = vi * int(stride); - RayTypeK ray = rayN.getRayByOffset(valid, offset); + RayTypeK ray = rayN.getRayByOffset(valid, offset); valid &= ray.tnear() <= ray.tfar; scene->intersectors.intersect(valid, ray, context); - rayN.setHitByOffset(valid, offset, ray); + rayN.setHitByOffset(valid, offset, ray); } } } @@ -173,7 +173,7 @@ namespace embree const vbool valid = vij < vint(int(N)); const size_t packetIndex = j / K; - RayTypeK ray = rayN.getRayByIndex(valid, vij); + RayTypeK ray = rayN.getRayByIndex(valid, vij); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); @@ -191,7 +191,7 @@ namespace embree const vbool valid = vij < vint(int(N)); const size_t packetIndex = j / K; - rayN.setHitByIndex(valid, vij, rays[packetIndex]); + rayN.setHitByIndex(valid, vij, rays[packetIndex]); } } } @@ -256,7 +256,7 @@ namespace embree const vint index = *(vint*)&rayIDs[j]; RayK& ray = rays[j/K]; rayPtrs[j/K] = &ray; - ray = rayN.getRayByIndex(valid, index); + ray = rayN.getRayByIndex(valid, index); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); } @@ -268,7 +268,7 @@ namespace embree const vint vi = vint(int(j)) + vint(step); const vbool valid = vi < vint(int(numOctantRays)); const vint index = *(vint*)&rayIDs[j]; - rayN.setHitByIndex(valid, index, rays[j/K]); + rayN.setHitByIndex(valid, index, rays[j/K]); } raysInOctant[curOctant] = 0; @@ -282,12 +282,12 @@ namespace embree const vint vi = vint(int(i)) + vint(step); vbool valid = vi < vint(int(N)); - RayTypeK ray = rayN.getRayByIndex(valid, vi); + RayTypeK ray = rayN.getRayByIndex(valid, vi); valid &= ray.tnear() <= ray.tfar; scene->intersectors.intersect(valid, ray, context); - rayN.setHitByIndex(valid, vi, ray); + rayN.setHitByIndex(valid, vi, ray); } } } @@ -394,7 +394,7 @@ namespace embree const vint offset = *(vint*)&rayOffsets[j]; RayK& ray = rays[j/K]; rayPtrs[j/K] = &ray; - ray = rayN.getRayByOffset(valid, offset); + ray = rayN.getRayByOffset(valid, offset); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); } @@ -436,7 +436,7 @@ namespace embree { const size_t offset = j * sizeof(float); vbool valid = (vint(int(j)) + vint(step)) < vint(int(N)); - RayTypeK ray = rayN.getRayByOffset(valid, offset); + RayTypeK ray = rayN.getRayByOffset(valid, offset); valid &= ray.tnear() <= ray.tfar; scene->intersectors.intersect(valid, ray, context); @@ -470,7 +470,7 @@ namespace embree const size_t offset = (i+j) * sizeof(float); const size_t packetIndex = j / K; - RayTypeK ray = rayN.getRayByOffset(valid, offset); + RayTypeK ray = rayN.getRayByOffset(valid, offset); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); @@ -554,7 +554,7 @@ namespace embree const vint offset = *(vint*)&rayOffsets[j]; RayK& ray = rays[j/K]; rayPtrs[j/K] = &ray; - ray = rayN.getRayByOffset(valid, offset); + ray = rayN.getRayByOffset(valid, offset); ray.tnear() = select(valid, ray.tnear(), zero); ray.tfar = select(valid, ray.tfar, neg_inf); } @@ -581,7 +581,7 @@ namespace embree vbool valid = vi < vint(int(N)); const size_t offset = i * sizeof(float); - RayTypeK ray = rayN.getRayByOffset(valid, offset); + RayTypeK ray = rayN.getRayByOffset(valid, offset); valid &= ray.tnear() <= ray.tfar; scene->intersectors.intersect(valid, ray, context); diff --git a/kernels/bvh/bvh_intersector_stream_filters.h b/kernels/bvh/bvh_intersector_stream_filters.h index cdeb923637..e7df7c2ae2 100644 --- a/kernels/bvh/bvh_intersector_stream_filters.h +++ b/kernels/bvh/bvh_intersector_stream_filters.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_node_aabb.h b/kernels/bvh/bvh_node_aabb.h index baa4a8d805..3fd9fc7d18 100644 --- a/kernels/bvh/bvh_node_aabb.h +++ b/kernels/bvh/bvh_node_aabb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -46,6 +46,14 @@ namespace embree template __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const { +#if defined(DEBUG) + // check that empty children are only at the end of the child list + bool emptyChild = false; + for (size_t i=0; isetRef(i,children[i]); return ref; @@ -60,6 +68,14 @@ namespace embree template __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const { +#if defined(DEBUG) + // check that empty children are only at the end of the child list + bool emptyChild = false; + for (size_t i=0; isetRef(i,children[i]); diff --git a/kernels/bvh/bvh_node_aabb_mb.h b/kernels/bvh/bvh_node_aabb_mb.h index 90f4bf163a..001f526c25 100644 --- a/kernels/bvh/bvh_node_aabb_mb.h +++ b/kernels/bvh/bvh_node_aabb_mb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -31,6 +31,14 @@ namespace embree template __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const { +#if defined(DEBUG) + // check that empty children are only at the end of the child list + bool emptyChild = false; + for (size_t i=0; i(nan); - upper_x = upper_y = upper_z = vfloat(nan); - lower_dx = lower_dy = lower_dz = vfloat(nan); // initialize with NAN and update during refit - upper_dx = upper_dy = upper_dz = vfloat(nan); + lower_x = lower_y = lower_z = vfloat(pos_inf); + upper_x = upper_y = upper_z = vfloat(neg_inf); + lower_dx = lower_dy = lower_dz = vfloat(0.0f); + upper_dx = upper_dy = upper_dz = vfloat(0.0f); BaseNode_t::clear(); } @@ -120,11 +128,6 @@ namespace embree setBounds(i, child.lbounds, child.dt); } - /*! tests if the node has valid bounds */ - __forceinline bool hasBounds() const { - return lower_dx.i[0] != cast_f2i(float(nan)); - } - /*! Return bounding box for time 0 */ __forceinline BBox3fa bounds0(size_t i) const { return BBox3fa(Vec3fa(lower_x[i],lower_y[i],lower_z[i]), diff --git a/kernels/bvh/bvh_node_aabb_mb4d.h b/kernels/bvh/bvh_node_aabb_mb4d.h index e968bbbc39..3b966fd054 100644 --- a/kernels/bvh/bvh_node_aabb_mb4d.h +++ b/kernels/bvh/bvh_node_aabb_mb4d.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -41,6 +41,14 @@ namespace embree template __forceinline void operator() (const BuildRecord&, const BuildRecord*, NodeRef ref, NodeRecordMB4D* children, const size_t num) const { +#if defined(DEBUG) + // check that empty children are only at the end of the child list + bool emptyChild = false; + for (size_t i=0; iset(i, children[i]); diff --git a/kernels/bvh/bvh_node_base.h b/kernels/bvh/bvh_node_base.h index 8268f3b932..a5570a7b9e 100644 --- a/kernels/bvh/bvh_node_base.h +++ b/kernels/bvh/bvh_node_base.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_node_obb.h b/kernels/bvh/bvh_node_obb.h index fa7cc08211..e6b500691e 100644 --- a/kernels/bvh/bvh_node_obb.h +++ b/kernels/bvh/bvh_node_obb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_node_obb_mb.h b/kernels/bvh/bvh_node_obb_mb.h index 834cf5ec28..c06b1aea5e 100644 --- a/kernels/bvh/bvh_node_obb_mb.h +++ b/kernels/bvh/bvh_node_obb_mb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_node_qaabb.h b/kernels/bvh/bvh_node_qaabb.h index 5212821f3f..99671ddc5a 100644 --- a/kernels/bvh/bvh_node_qaabb.h +++ b/kernels/bvh/bvh_node_qaabb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -190,6 +190,14 @@ namespace embree template __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const { +#if defined(DEBUG) + // check that empty children are only at the end of the child list + bool emptyChild = false; + for (size_t i=0; isetRef(i,children[i]); return ref; diff --git a/kernels/bvh/bvh_node_ref.h b/kernels/bvh/bvh_node_ref.h index 5efc9c72c7..6f6da758de 100644 --- a/kernels/bvh/bvh_node_ref.h +++ b/kernels/bvh/bvh_node_ref.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -102,7 +102,7 @@ namespace embree /*! Sets the barrier bit. */ __forceinline void setBarrier() { -#if defined(__X86_64__) +#if defined(__64BIT__) assert(!isBarrier()); ptr |= barrier_mask; #else @@ -112,7 +112,7 @@ namespace embree /*! Clears the barrier bit. */ __forceinline void clearBarrier() { -#if defined(__X86_64__) +#if defined(__64BIT__) ptr &= ~barrier_mask; #else assert(false); diff --git a/kernels/bvh/bvh_refit.cpp b/kernels/bvh/bvh_refit.cpp index bfe650d499..bf5c8538ba 100644 --- a/kernels/bvh/bvh_refit.cpp +++ b/kernels/bvh/bvh_refit.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_refit.h" @@ -10,6 +10,7 @@ #include "../geometry/trianglei.h" #include "../geometry/quadv.h" #include "../geometry/object.h" +#include "../geometry/instance.h" namespace embree { @@ -231,5 +232,16 @@ namespace embree Builder* BVH8VirtualMeshRefitSAH (void* accel, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,UserGeometry,Object>((BVH8*)accel,BVH8VirtualMeshBuilderSAH(accel,mesh,geomID,mode),mesh,mode); } #endif #endif + +#if defined(EMBREE_GEOMETRY_INSTANCE) + Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode); + Builder* BVH4InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<4,Instance,InstancePrimitive>((BVH4*)accel,BVH4InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); } + +#if defined(__AVX__) + Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode); + Builder* BVH8InstanceMeshRefitSAH (void* accel, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new BVHNRefitT<8,Instance,InstancePrimitive>((BVH8*)accel,BVH8InstanceMeshBuilderSAH(accel,mesh,gtype,geomID,mode),mesh,mode); } +#endif +#endif + } } diff --git a/kernels/bvh/bvh_refit.h b/kernels/bvh/bvh_refit.h index 4aa9bdd7cc..09bb3d8da5 100644 --- a/kernels/bvh/bvh_refit.h +++ b/kernels/bvh/bvh_refit.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_rotate.cpp b/kernels/bvh/bvh_rotate.cpp index 2bb431bf0e..460bd60c62 100644 --- a/kernels/bvh/bvh_rotate.cpp +++ b/kernels/bvh/bvh_rotate.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_rotate.h" diff --git a/kernels/bvh/bvh_rotate.h b/kernels/bvh/bvh_rotate.h index 009bef339e..61ef64a679 100644 --- a/kernels/bvh/bvh_rotate.h +++ b/kernels/bvh/bvh_rotate.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_statistics.cpp b/kernels/bvh/bvh_statistics.cpp index 05460843af..40f9043736 100644 --- a/kernels/bvh/bvh_statistics.cpp +++ b/kernels/bvh/bvh_statistics.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bvh_statistics.h" @@ -159,7 +159,7 @@ namespace embree template class BVHNStatistics<8>; #endif -#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42) +#if !defined(__AVX__) || (!defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)) || defined(__aarch64__) template class BVHNStatistics<4>; #endif } diff --git a/kernels/bvh/bvh_statistics.h b/kernels/bvh/bvh_statistics.h index 73dfc6fbcc..a28e115f1c 100644 --- a/kernels/bvh/bvh_statistics.h +++ b/kernels/bvh/bvh_statistics.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/bvh_traverser1.h b/kernels/bvh/bvh_traverser1.h index 7f17084b81..8ce01b57f5 100644 --- a/kernels/bvh/bvh_traverser1.h +++ b/kernels/bvh/bvh_traverser1.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,213 +14,9 @@ namespace embree namespace isa { /*! BVH regular node traversal for single rays. */ - template + template class BVHNNodeTraverser1Hit; - /*! Helper functions for fast sorting using AVX512 instructions. */ -#if defined(__AVX512ER__) - - /* KNL code path */ - __forceinline void isort_update(vfloat16 &dist, vllong8 &ptr, const vfloat16 &d, const vllong8 &p) - { - const vfloat16 dist_shift = align_shift_right<15>(dist,dist); - const vllong8 ptr_shift = align_shift_right<7>(ptr,ptr); - const vbool16 m_geq = d >= dist; - const vbool16 m_geq_shift = m_geq << 1; - dist = select(m_geq,d,dist); - ptr = select(vboold8(m_geq),p,ptr); - dist = select(m_geq_shift,dist_shift,dist); - ptr = select(vboold8(m_geq_shift),ptr_shift,ptr); - } - - __forceinline void isort_quick_update(vfloat16 &dist, vllong8 &ptr, const vfloat16 &d, const vllong8 &p) - { - //dist = align_shift_right<15>(dist,d); - //ptr = align_shift_right<7>(ptr,p); - dist = align_shift_right<15>(dist,permute(d,vint16(zero))); - ptr = align_shift_right<7>(ptr,permute(p,vllong8(zero))); - } - - template - __forceinline void traverseClosestHitAVX512(NodeRef& cur, - size_t mask, - const vfloat& tNear, - StackItemT*& stackPtr, - StackItemT* stackEnd) - { - assert(mask != 0); - const BaseNode* node = cur.baseNode(); - - vllong8 children( vllong::loadu((void*)node->children) ); - children = vllong8::compact((int)mask,children); - vfloat16 distance = tNear; - distance = vfloat16::compact((int)mask,distance,tNear); - - cur = toScalar(children); - BVHN::prefetch(cur,types); - - mask &= mask-1; - if (likely(mask == 0)) return; - - /* 2 hits: order A0 B0 */ - const vllong8 c0(children); - const vfloat16 d0(distance); - children = align_shift_right<1>(children,children); - distance = align_shift_right<1>(distance,distance); - const vllong8 c1(children); - const vfloat16 d1(distance); - - cur = toScalar(children); - BVHN::prefetch(cur,types); - - /* a '<' keeps the order for equal distances, scenes like powerplant largely benefit from it */ - const vboolf16 m_dist = d0 < d1; - const vfloat16 dist_A0 = select(m_dist, d0, d1); - const vfloat16 dist_B0 = select(m_dist, d1, d0); - const vllong8 ptr_A0 = select(vboold8(m_dist), c0, c1); - const vllong8 ptr_B0 = select(vboold8(m_dist), c1, c0); - - mask &= mask-1; - if (likely(mask == 0)) { - cur = toScalar(ptr_A0); - stackPtr[0].ptr = toScalar(ptr_B0); - *(float*)&stackPtr[0].dist = toScalar(dist_B0); - stackPtr++; - return; - } - - /* 3 hits: order A1 B1 C1 */ - - children = align_shift_right<1>(children,children); - distance = align_shift_right<1>(distance,distance); - - const vllong8 c2(children); - const vfloat16 d2(distance); - - cur = toScalar(children); - BVHN::prefetch(cur,types); - - const vboolf16 m_dist1 = dist_A0 <= d2; - const vfloat16 dist_tmp_B1 = select(m_dist1, d2, dist_A0); - const vllong8 ptr_A1 = select(vboold8(m_dist1), ptr_A0, c2); - const vllong8 ptr_tmp_B1 = select(vboold8(m_dist1), c2, ptr_A0); - - const vboolf16 m_dist2 = dist_B0 <= dist_tmp_B1; - const vfloat16 dist_B1 = select(m_dist2, dist_B0 , dist_tmp_B1); - const vfloat16 dist_C1 = select(m_dist2, dist_tmp_B1, dist_B0); - const vllong8 ptr_B1 = select(vboold8(m_dist2), ptr_B0, ptr_tmp_B1); - const vllong8 ptr_C1 = select(vboold8(m_dist2), ptr_tmp_B1, ptr_B0); - - mask &= mask-1; - if (likely(mask == 0)) { - cur = toScalar(ptr_A1); - stackPtr[0].ptr = toScalar(ptr_C1); - *(float*)&stackPtr[0].dist = toScalar(dist_C1); - stackPtr[1].ptr = toScalar(ptr_B1); - *(float*)&stackPtr[1].dist = toScalar(dist_B1); - stackPtr+=2; - return; - } - - /* 4 hits: order A2 B2 C2 D2 */ - - const vfloat16 dist_A1 = select(m_dist1, dist_A0, d2); - - children = align_shift_right<1>(children,children); - distance = align_shift_right<1>(distance,distance); - - const vllong8 c3(children); - const vfloat16 d3(distance); - - cur = toScalar(children); - BVHN::prefetch(cur,types); - - const vboolf16 m_dist3 = dist_A1 <= d3; - const vfloat16 dist_tmp_B2 = select(m_dist3, d3, dist_A1); - const vllong8 ptr_A2 = select(vboold8(m_dist3), ptr_A1, c3); - const vllong8 ptr_tmp_B2 = select(vboold8(m_dist3), c3, ptr_A1); - - const vboolf16 m_dist4 = dist_B1 <= dist_tmp_B2; - const vfloat16 dist_B2 = select(m_dist4, dist_B1 , dist_tmp_B2); - const vfloat16 dist_tmp_C2 = select(m_dist4, dist_tmp_B2, dist_B1); - const vllong8 ptr_B2 = select(vboold8(m_dist4), ptr_B1, ptr_tmp_B2); - const vllong8 ptr_tmp_C2 = select(vboold8(m_dist4), ptr_tmp_B2, ptr_B1); - - const vboolf16 m_dist5 = dist_C1 <= dist_tmp_C2; - const vfloat16 dist_C2 = select(m_dist5, dist_C1 , dist_tmp_C2); - const vfloat16 dist_D2 = select(m_dist5, dist_tmp_C2, dist_C1); - const vllong8 ptr_C2 = select(vboold8(m_dist5), ptr_C1, ptr_tmp_C2); - const vllong8 ptr_D2 = select(vboold8(m_dist5), ptr_tmp_C2, ptr_C1); - - mask &= mask-1; - if (likely(mask == 0)) { - cur = toScalar(ptr_A2); - stackPtr[0].ptr = toScalar(ptr_D2); - *(float*)&stackPtr[0].dist = toScalar(dist_D2); - stackPtr[1].ptr = toScalar(ptr_C2); - *(float*)&stackPtr[1].dist = toScalar(dist_C2); - stackPtr[2].ptr = toScalar(ptr_B2); - *(float*)&stackPtr[2].dist = toScalar(dist_B2); - stackPtr+=3; - return; - } - - /* >=5 hits: reverse to descending order for writing to stack */ - - const size_t hits = 4 + popcnt(mask); - const vfloat16 dist_A2 = select(m_dist3, dist_A1, d3); - vfloat16 dist(neg_inf); - vllong8 ptr(zero); - - - isort_quick_update(dist,ptr,dist_A2,ptr_A2); - isort_quick_update(dist,ptr,dist_B2,ptr_B2); - isort_quick_update(dist,ptr,dist_C2,ptr_C2); - isort_quick_update(dist,ptr,dist_D2,ptr_D2); - - do { - - children = align_shift_right<1>(children,children); - distance = align_shift_right<1>(distance,distance); - - cur = toScalar(children); - BVHN::prefetch(cur,types); - - const vfloat16 new_dist(permute(distance,vint16(zero))); - const vllong8 new_ptr(permute(children,vllong8(zero))); - - mask &= mask-1; - isort_update(dist,ptr,new_dist,new_ptr); - - } while(mask); - - const vboold8 m_stack_ptr(0x55); // 10101010 (lsb -> msb) - const vboolf16 m_stack_dist(0x4444); // 0010001000100010 (lsb -> msb) - - /* extract current noderef */ - cur = toScalar(permute(ptr,vllong8(hits-1))); - /* rearrange pointers to beginning of 16 bytes block */ - vllong8 stackElementA0; - stackElementA0 = vllong8::expand(m_stack_ptr,ptr,stackElementA0); - /* put distances in between */ - vuint16 stackElementA1((__m512i)stackElementA0); - stackElementA1 = vuint16::expand(m_stack_dist,asUInt(dist),stackElementA1); - /* write out first 4 x 16 bytes block to stack */ - vuint16::storeu(stackPtr,stackElementA1); - /* get upper half of dist and ptr */ - dist = align_shift_right<4>(dist,dist); - ptr = align_shift_right<4>(ptr,ptr); - /* assemble and write out second block */ - vllong8 stackElementB0; - stackElementB0 = vllong8::expand(m_stack_ptr,ptr,stackElementB0); - vuint16 stackElementB1((__m512i)stackElementB0); - stackElementB1 = vuint16::expand(m_stack_dist,asUInt(dist),stackElementB1); - vuint16::storeu(stackPtr + 4,stackElementB1); - /* increase stack pointer */ - stackPtr += hits-1; - } -#endif - #if defined(__AVX512VL__) // SKX template @@ -249,8 +45,8 @@ namespace embree #endif /* Specialization for BVH4. */ - template - class BVHNNodeTraverser1Hit<4, Nx, types> + template + class BVHNNodeTraverser1Hit<4, types> { typedef BVH4 BVH; typedef BVH4::NodeRef NodeRef; @@ -261,14 +57,11 @@ namespace embree /* Traverses a node with at least one hit child. Optimized for finding the closest hit (intersection). */ static __forceinline void traverseClosestHit(NodeRef& cur, size_t mask, - const vfloat& tNear, + const vfloat4& tNear, StackItemT*& stackPtr, StackItemT* stackEnd) { assert(mask != 0); -#if defined(__AVX512ER__) - traverseClosestHitAVX512<4,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd); -#else const BaseNode* node = cur.baseNode(); /*! one child is hit, continue with that child */ @@ -343,14 +136,13 @@ namespace embree assert(c != BVH::emptyNode); sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]); cur = (NodeRef) stackPtr[-1].ptr; stackPtr--; -#endif #endif } /* Traverses a node with at least one hit child. Optimized for finding any hit (occlusion). */ static __forceinline void traverseAnyHit(NodeRef& cur, size_t mask, - const vfloat& tNear, + const vfloat4& tNear, NodeRef*& stackPtr, NodeRef* stackEnd) { @@ -380,8 +172,8 @@ namespace embree }; /* Specialization for BVH8. */ - template - class BVHNNodeTraverser1Hit<8, Nx, types> + template + class BVHNNodeTraverser1Hit<8, types> { typedef BVH8 BVH; typedef BVH8::NodeRef NodeRef; @@ -485,10 +277,10 @@ namespace embree const size_t hits = 4 + popcnt(mask); vint8 dist(INT_MIN); // this will work with -0.0f (0x80000000) as distance, isort_update uses >= to insert - isort_quick_update(dist,dist_A2); - isort_quick_update(dist,dist_B2); - isort_quick_update(dist,dist_C2); - isort_quick_update(dist,dist_D2); + isort_quick_update<8>(dist,dist_A2); + isort_quick_update<8>(dist,dist_B2); + isort_quick_update<8>(dist,dist_C2); + isort_quick_update<8>(dist,dist_D2); do { @@ -497,7 +289,7 @@ namespace embree BVH::prefetch(cur,types); const vint8 new_dist(permute(distance_i,vint8(zero))); mask &= mask-1; - isort_update(dist,new_dist); + isort_update<8>(dist,new_dist); } while(mask); @@ -518,14 +310,12 @@ namespace embree public: static __forceinline void traverseClosestHit(NodeRef& cur, size_t mask, - const vfloat& tNear, + const vfloat8& tNear, StackItemT*& stackPtr, StackItemT* stackEnd) { assert(mask != 0); -#if defined(__AVX512ER__) - traverseClosestHitAVX512<8,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd); -#elif defined(__AVX512VL__) +#if defined(__AVX512VL__) traverseClosestHitAVX512VL8(cur,mask,tNear,stackPtr,stackEnd); #else @@ -644,7 +434,7 @@ namespace embree static __forceinline void traverseAnyHit(NodeRef& cur, size_t mask, - const vfloat& tNear, + const vfloat8& tNear, NodeRef*& stackPtr, NodeRef* stackEnd) { diff --git a/kernels/bvh/bvh_traverser_stream.h b/kernels/bvh/bvh_traverser_stream.h index 9c603babf0..852981e69d 100644 --- a/kernels/bvh/bvh_traverser_stream.h +++ b/kernels/bvh/bvh_traverser_stream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,7 +11,7 @@ namespace embree { namespace isa { - template + template class BVHNNodeTraverserStreamHitCoherent { typedef BVHN BVH; @@ -22,8 +22,8 @@ namespace embree template static __forceinline void traverseClosestHit(NodeRef& cur, size_t& m_trav_active, - const vbool& vmask, - const vfloat& tNear, + const vbool& vmask, + const vfloat& tNear, const T* const tMask, StackItemMaskCoherent*& stackPtr) { @@ -79,14 +79,9 @@ namespace embree /*! slow path for more than two hits */ size_t hits = movemask(vmask); - const vint dist_i = select(vmask, (asInt(tNear) & 0xfffffff8) | vint(step), 0); - #if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL - const vint tmp = extractN(dist_i); - const vint dist_i_sorted = usort_descending(tmp); - #else - const vint dist_i_sorted = usort_descending(dist_i); - #endif - const vint sorted_index = dist_i_sorted & 7; + const vint dist_i = select(vmask, (asInt(tNear) & 0xfffffff8) | vint(step), 0); + const vint dist_i_sorted = usort_descending(dist_i); + const vint sorted_index = dist_i_sorted & 7; size_t i = 0; for (;;) @@ -112,7 +107,7 @@ namespace embree template static __forceinline void traverseAnyHit(NodeRef& cur, size_t& m_trav_active, - const vbool& vmask, + const vbool& vmask, const T* const tMask, StackItemMaskCoherent*& stackPtr) { diff --git a/kernels/bvh/node_intersector.h b/kernels/bvh/node_intersector.h index a978c0c459..25edaf295d 100644 --- a/kernels/bvh/node_intersector.h +++ b/kernels/bvh/node_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/bvh/node_intersector1.h b/kernels/bvh/node_intersector1.h index b1e63ce345..17641fa888 100644 --- a/kernels/bvh/node_intersector1.h +++ b/kernels/bvh/node_intersector1.h @@ -1,10 +1,19 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "node_intersector.h" +#if defined(__AVX2__) +#define __FMA_X4__ +#endif + +#if defined(__aarch64__) +#define __FMA_X4__ +#endif + + namespace embree { namespace isa @@ -13,12 +22,12 @@ namespace embree // Ray structure used in single-ray traversal ////////////////////////////////////////////////////////////////////////////////////// - template + template struct TravRayBase; /* Base (without tnear and tfar) */ - template - struct TravRayBase + template + struct TravRayBase { __forceinline TravRayBase() {} @@ -29,9 +38,15 @@ namespace embree org = Vec3vf(ray_org.x,ray_org.y,ray_org.z); dir = Vec3vf(ray_dir.x,ray_dir.y,ray_dir.z); rdir = Vec3vf(ray_rdir.x,ray_rdir.y,ray_rdir.z); -#if defined(__AVX2__) +#if defined(__FMA_X4__) const Vec3fa ray_org_rdir = ray_org*ray_rdir; +#if !defined(__aarch64__) org_rdir = Vec3vf(ray_org_rdir.x,ray_org_rdir.y,ray_org_rdir.z); +#else + //for aarch64, we do not have msub equal instruction, so we negeate orig and use madd + //x86 will use msub + neg_org_rdir = Vec3vf(-ray_org_rdir.x,-ray_org_rdir.y,-ray_org_rdir.z); +#endif #endif nearX = ray_rdir.x >= 0.0f ? 0*sizeof(vfloat) : 1*sizeof(vfloat); nearY = ray_rdir.y >= 0.0f ? 2*sizeof(vfloat) : 3*sizeof(vfloat); @@ -39,28 +54,22 @@ namespace embree farX = nearX ^ sizeof(vfloat); farY = nearY ^ sizeof(vfloat); farZ = nearZ ^ sizeof(vfloat); - -#if defined(__AVX512ER__) // KNL+ - /* optimization works only for 8-wide BVHs with 16-wide SIMD */ - const vint<16> id(step); - const vint<16> id2 = align_shift_right<16/2>(id, id); - permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2); - permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2); - permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2); -#endif - } template - __forceinline TravRayBase(size_t k, const Vec3vf& ray_org, const Vec3vf& ray_dir, - const Vec3vf& ray_rdir, const Vec3vi& nearXYZ, - size_t flip = sizeof(vfloat)) + __forceinline void init(size_t k, const Vec3vf& ray_org, const Vec3vf& ray_dir, + const Vec3vf& ray_rdir, const Vec3vi& nearXYZ, + size_t flip = sizeof(vfloat)) { - org = Vec3vf(ray_org.x[k], ray_org.y[k], ray_org.z[k]); - dir = Vec3vf(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]); - rdir = Vec3vf(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]); -#if defined(__AVX2__) - org_rdir = org*rdir; + org = Vec3vf(ray_org.x[k], ray_org.y[k], ray_org.z[k]); + dir = Vec3vf(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]); + rdir = Vec3vf(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]); +#if defined(__FMA_X4__) +#if !defined(__aarch64__) + org_rdir = org*rdir; +#else + neg_org_rdir = -(org*rdir); +#endif #endif nearX = nearXYZ.x[k]; nearY = nearXYZ.y[k]; @@ -68,33 +77,26 @@ namespace embree farX = nearX ^ flip; farY = nearY ^ flip; farZ = nearZ ^ flip; - -#if defined(__AVX512ER__) // KNL+ - /* optimization works only for 8-wide BVHs with 16-wide SIMD */ - const vint<16> id(step); - const vint<16> id2 = align_shift_right<16/2>(id, id); - permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2); - permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2); - permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2); -#endif } Vec3fa org_xyz, dir_xyz; - Vec3vf org, dir, rdir; -#if defined(__AVX2__) - Vec3vf org_rdir; + Vec3vf org, dir, rdir; +#if defined(__FMA_X4__) +#if !defined(__aarch64__) + Vec3vf org_rdir; +#else + //aarch64 version are keeping negation of the org_rdir and use madd + //x86 uses msub + Vec3vf neg_org_rdir; #endif -#if defined(__AVX512ER__) // KNL+ - vint16 permX, permY, permZ; #endif - size_t nearX, nearY, nearZ; size_t farX, farY, farZ; }; /* Base (without tnear and tfar) */ - template - struct TravRayBase + template + struct TravRayBase { __forceinline TravRayBase() {} @@ -117,28 +119,19 @@ namespace embree farX = nearX ^ sizeof(vfloat); farY = nearY ^ sizeof(vfloat); farZ = nearZ ^ sizeof(vfloat); - -#if defined(__AVX512ER__) // KNL+ - /* optimization works only for 8-wide BVHs with 16-wide SIMD */ - const vint<16> id(step); - const vint<16> id2 = align_shift_right<16/2>(id, id); - permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2); - permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2); - permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2); -#endif } template - __forceinline TravRayBase(size_t k, const Vec3vf& ray_org, const Vec3vf& ray_dir, - const Vec3vf& ray_rdir, const Vec3vi& nearXYZ, - size_t flip = sizeof(vfloat)) + __forceinline void init(size_t k, const Vec3vf& ray_org, const Vec3vf& ray_dir, + const Vec3vf& ray_rdir, const Vec3vi& nearXYZ, + size_t flip = sizeof(vfloat)) { - const vfloat round_down = 1.0f-3.0f*float(ulp); - const vfloat round_up = 1.0f+3.0f*float(ulp); - org = Vec3vf(ray_org.x[k], ray_org.y[k], ray_org.z[k]); - dir = Vec3vf(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]); - rdir_near = round_down*Vec3vf(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]); - rdir_far = round_up *Vec3vf(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]); + const vfloat round_down = 1.0f-3.0f*float(ulp); + const vfloat round_up = 1.0f+3.0f*float(ulp); + org = Vec3vf(ray_org.x[k], ray_org.y[k], ray_org.z[k]); + dir = Vec3vf(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]); + rdir_near = round_down*Vec3vf(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]); + rdir_far = round_up *Vec3vf(ray_rdir.x[k], ray_rdir.y[k], ray_rdir.z[k]); nearX = nearXYZ.x[k]; nearY = nearXYZ.y[k]; @@ -146,47 +139,36 @@ namespace embree farX = nearX ^ flip; farY = nearY ^ flip; farZ = nearZ ^ flip; - -#if defined(__AVX512ER__) // KNL+ - /* optimization works only for 8-wide BVHs with 16-wide SIMD */ - const vint<16> id(step); - const vint<16> id2 = align_shift_right<16/2>(id, id); - permX = select(vfloat<16>(dir.x) >= 0.0f, id, id2); - permY = select(vfloat<16>(dir.y) >= 0.0f, id, id2); - permZ = select(vfloat<16>(dir.z) >= 0.0f, id, id2); -#endif } Vec3fa org_xyz, dir_xyz; - Vec3vf org, dir, rdir_near, rdir_far; -#if defined(__AVX512ER__) // KNL+ - vint16 permX, permY, permZ; -#endif - + Vec3vf org, dir, rdir_near, rdir_far; size_t nearX, nearY, nearZ; size_t farX, farY, farZ; }; /* Full (with tnear and tfar) */ - template - struct TravRay : TravRayBase + template + struct TravRay : TravRayBase { __forceinline TravRay() {} __forceinline TravRay(const Vec3fa& ray_org, const Vec3fa& ray_dir, float ray_tnear, float ray_tfar) - : TravRayBase(ray_org, ray_dir), + : TravRayBase(ray_org, ray_dir), tnear(ray_tnear), tfar(ray_tfar) {} template - __forceinline TravRay(size_t k, const Vec3vf& ray_org, const Vec3vf& ray_dir, - const Vec3vf& ray_rdir, const Vec3vi& nearXYZ, - float ray_tnear, float ray_tfar, - size_t flip = sizeof(vfloat)) - : TravRayBase(k, ray_org, ray_dir, ray_rdir, nearXYZ, flip), - tnear(ray_tnear), tfar(ray_tfar) {} + __forceinline void init(size_t k, const Vec3vf& ray_org, const Vec3vf& ray_dir, + const Vec3vf& ray_rdir, const Vec3vi& nearXYZ, + float ray_tnear, float ray_tfar, + size_t flip = sizeof(vfloat)) + { + TravRayBase::template init(k, ray_org, ray_dir, ray_rdir, nearXYZ, flip); + tnear = ray_tnear; tfar = ray_tfar; + } - vfloat tnear; - vfloat tfar; + vfloat tnear; + vfloat tfar; }; ////////////////////////////////////////////////////////////////////////////////////// @@ -441,19 +423,28 @@ namespace embree // Fast AABBNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template - __forceinline size_t intersectNode(const typename BVHN::AABBNode* node, const TravRay& ray, vfloat& dist); + template + __forceinline size_t intersectNode(const typename BVHN::AABBNode* node, const TravRay& ray, vfloat& dist); template<> - __forceinline size_t intersectNode<4,4>(const typename BVH4::AABBNode* node, const TravRay<4,4,false>& ray, vfloat4& dist) - { -#if defined(__AVX2__) + __forceinline size_t intersectNode<4>(const typename BVH4::AABBNode* node, const TravRay<4,false>& ray, vfloat4& dist) + { +#if defined(__FMA_X4__) +#if defined(__aarch64__) + const vfloat4 tNearX = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat4 tNearY = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat4 tNearZ = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.neg_org_rdir.z); + const vfloat4 tFarX = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat4 tFarY = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat4 tFarZ = madd(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat4 tNearX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x); const vfloat4 tNearY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y); const vfloat4 tNearZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z); const vfloat4 tFarX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x); const vfloat4 tFarY = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y); const vfloat4 tFarZ = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z); +#endif #else const vfloat4 tNearX = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x; const vfloat4 tNearY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y; @@ -462,13 +453,18 @@ namespace embree const vfloat4 tFarY = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir.y; const vfloat4 tFarZ = (vfloat4::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir.z; #endif - -#if defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW + +#if defined(__aarch64__) + const vfloat4 tNear = maxi(tNearX, tNearY, tNearZ, ray.tnear); + const vfloat4 tFar = mini(tFarX, tFarY, tFarZ, ray.tfar); + const vbool4 vmask = asInt(tNear) <= asInt(tFar); + const size_t mask = movemask(vmask); +#elif defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool4 vmask = asInt(tNear) > asInt(tFar); const size_t mask = movemask(vmask) ^ ((1<<4)-1); -#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#elif defined(__AVX512F__) // SKX const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool4 vmask = asInt(tNear) <= asInt(tFar); @@ -486,15 +482,25 @@ namespace embree #if defined(__AVX__) template<> - __forceinline size_t intersectNode<8,8>(const typename BVH8::AABBNode* node, const TravRay<8,8,false>& ray, vfloat8& dist) + __forceinline size_t intersectNode<8>(const typename BVH8::AABBNode* node, const TravRay<8,false>& ray, vfloat8& dist) { #if defined(__AVX2__) +#if defined(__aarch64__) + const vfloat8 tNearX = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat8 tNearY = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat8 tNearZ = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.neg_org_rdir.z); + const vfloat8 tFarX = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat8 tFarY = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat8 tFarZ = madd(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat8 tNearX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x); const vfloat8 tNearY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y); const vfloat8 tNearZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z); const vfloat8 tFarX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x); const vfloat8 tFarY = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y); const vfloat8 tFarZ = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z); +#endif + #else const vfloat8 tNearX = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x; const vfloat8 tNearY = (vfloat8::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y; @@ -509,7 +515,7 @@ namespace embree const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool8 vmask = asInt(tNear) > asInt(tFar); const size_t mask = movemask(vmask) ^ ((1<<8)-1); -#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#elif defined(__AVX512F__) // SKX const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool8 vmask = asInt(tNear) <= asInt(tFar); @@ -524,54 +530,14 @@ namespace embree return mask; } -#endif - -#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL - - template<> - __forceinline size_t intersectNode<4,16>(const typename BVH4::AABBNode* node, const TravRay<4,16,false>& ray, vfloat16& dist) - { - const vfloat16 tNearX = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x); - const vfloat16 tNearY = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y); - const vfloat16 tNearZ = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z); - const vfloat16 tFarX = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x); - const vfloat16 tFarY = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y); - const vfloat16 tFarZ = msub(vfloat16(*(vfloat4*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z); - const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear); - const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar); - const vbool16 vmask = le(vbool16(0xf),tNear,tFar); - const size_t mask = movemask(vmask); - dist = tNear; - return mask; - } - - template<> - __forceinline size_t intersectNode<8,16>(const typename BVH8::AABBNode* node, const TravRay<8,16,false>& ray, vfloat16& dist) - { - const vllong8 invalid((size_t)BVH8::emptyNode); - const vboold8 m_valid(invalid != vllong8::loadu(node->children)); - const vfloat16 bminmaxX = permute(vfloat16::load((const float*)&node->lower_x), ray.permX); - const vfloat16 bminmaxY = permute(vfloat16::load((const float*)&node->lower_y), ray.permY); - const vfloat16 bminmaxZ = permute(vfloat16::load((const float*)&node->lower_z), ray.permZ); - const vfloat16 tNearFarX = msub(bminmaxX, ray.rdir.x, ray.org_rdir.x); - const vfloat16 tNearFarY = msub(bminmaxY, ray.rdir.y, ray.org_rdir.y); - const vfloat16 tNearFarZ = msub(bminmaxZ, ray.rdir.z, ray.org_rdir.z); - const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, ray.tnear); - const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, ray.tfar); - const vbool16 vmask = le(vboolf16(m_valid),tNear,align_shift_right<8>(tFar, tFar)); - const size_t mask = movemask(vmask); - dist = tNear; - return mask; - } - #endif ////////////////////////////////////////////////////////////////////////////////////// // Robust AABBNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template - __forceinline size_t intersectNodeRobust(const typename BVHN::AABBNode* node, const TravRay& ray, vfloat& dist) + template + __forceinline size_t intersectNodeRobust(const typename BVHN::AABBNode* node, const TravRay& ray, vfloat& dist) { const vfloat tNearX = (vfloat::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x; const vfloat tNearY = (vfloat::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y; @@ -587,50 +553,12 @@ namespace embree return mask; } -#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL - - template<> - __forceinline size_t intersectNodeRobust<4,16>(const typename BVHN<4>::AABBNode* node, const TravRay<4,16,true>& ray, vfloat<16>& dist) - { - const vfloat16 tNearX = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x; - const vfloat16 tNearY = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y; - const vfloat16 tNearZ = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z; - const vfloat16 tFarX = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x; - const vfloat16 tFarY = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y; - const vfloat16 tFarZ = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z; - const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear); - const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar); - const vbool16 vmask = le((1 << 4)-1,tNear,tFar); - const size_t mask = movemask(vmask); - dist = tNear; - return mask; - } - - template<> - __forceinline size_t intersectNodeRobust<8,16>(const typename BVHN<8>::AABBNode* node, const TravRay<8,16,true>& ray, vfloat<16>& dist) - { - const vfloat16 tNearX = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x; - const vfloat16 tNearY = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y; - const vfloat16 tNearZ = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z; - const vfloat16 tFarX = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x; - const vfloat16 tFarY = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y; - const vfloat16 tFarZ = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z; - const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear); - const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar); - const vbool16 vmask = le((1 << 8)-1,tNear,tFar); - const size_t mask = movemask(vmask); - dist = tNear; - return mask; - } - -#endif - ////////////////////////////////////////////////////////////////////////////////////// // Fast AABBNodeMB intersection ////////////////////////////////////////////////////////////////////////////////////// template - __forceinline size_t intersectNode(const typename BVHN::AABBNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + __forceinline size_t intersectNode(const typename BVHN::AABBNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { const vfloat* pNearX = (const vfloat*)((const char*)&node->lower_x+ray.nearX); const vfloat* pNearY = (const vfloat*)((const char*)&node->lower_x+ray.nearY); @@ -638,13 +566,22 @@ namespace embree const vfloat* pFarX = (const vfloat*)((const char*)&node->lower_x+ray.farX); const vfloat* pFarY = (const vfloat*)((const char*)&node->lower_x+ray.farY); const vfloat* pFarZ = (const vfloat*)((const char*)&node->lower_x+ray.farZ); -#if defined(__AVX2__) +#if defined(__FMA_X4__) +#if defined(__aarch64__) + const vfloat tNearX = madd(madd(time,pNearX[6],vfloat(pNearX[0])), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat tNearY = madd(madd(time,pNearY[6],vfloat(pNearY[0])), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat tNearZ = madd(madd(time,pNearZ[6],vfloat(pNearZ[0])), ray.rdir.z, ray.neg_org_rdir.z); + const vfloat tFarX = madd(madd(time,pFarX [6],vfloat(pFarX [0])), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat tFarY = madd(madd(time,pFarY [6],vfloat(pFarY [0])), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat tFarZ = madd(madd(time,pFarZ [6],vfloat(pFarZ [0])), ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat tNearX = msub(madd(time,pNearX[6],vfloat(pNearX[0])), ray.rdir.x, ray.org_rdir.x); const vfloat tNearY = msub(madd(time,pNearY[6],vfloat(pNearY[0])), ray.rdir.y, ray.org_rdir.y); const vfloat tNearZ = msub(madd(time,pNearZ[6],vfloat(pNearZ[0])), ray.rdir.z, ray.org_rdir.z); const vfloat tFarX = msub(madd(time,pFarX [6],vfloat(pFarX [0])), ray.rdir.x, ray.org_rdir.x); const vfloat tFarY = msub(madd(time,pFarY [6],vfloat(pFarY [0])), ray.rdir.y, ray.org_rdir.y); const vfloat tFarZ = msub(madd(time,pFarZ [6],vfloat(pFarZ [0])), ray.rdir.z, ray.org_rdir.z); +#endif #else const vfloat tNearX = (madd(time,pNearX[6],vfloat(pNearX[0])) - ray.org.x) * ray.rdir.x; const vfloat tNearY = (madd(time,pNearY[6],vfloat(pNearY[0])) - ray.org.y) * ray.rdir.y; @@ -653,12 +590,12 @@ namespace embree const vfloat tFarY = (madd(time,pFarY [6],vfloat(pFarY [0])) - ray.org.y) * ray.rdir.y; const vfloat tFarZ = (madd(time,pFarZ [6],vfloat(pFarZ [0])) - ray.org.z) * ray.rdir.z; #endif -#if defined(__AVX2__) && !defined(__AVX512F__) // HSW +#if defined(__FMA_X4__) && !defined(__AVX512F__) // HSW const vfloat tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool vmask = asInt(tNear) > asInt(tFar); const size_t mask = movemask(vmask) ^ ((1< tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool vmask = asInt(tNear) <= asInt(tFar); @@ -678,7 +615,7 @@ namespace embree ////////////////////////////////////////////////////////////////////////////////////// template - __forceinline size_t intersectNodeRobust(const typename BVHN::AABBNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + __forceinline size_t intersectNodeRobust(const typename BVHN::AABBNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { const vfloat* pNearX = (const vfloat*)((const char*)&node->lower_x+ray.nearX); const vfloat* pNearY = (const vfloat*)((const char*)&node->lower_x+ray.nearY); @@ -704,7 +641,7 @@ namespace embree ////////////////////////////////////////////////////////////////////////////////////// template - __forceinline size_t intersectNodeMB4D(const typename BVHN::NodeRef ref, const TravRay& ray, const float time, vfloat& dist) + __forceinline size_t intersectNodeMB4D(const typename BVHN::NodeRef ref, const TravRay& ray, const float time, vfloat& dist) { const typename BVHN::AABBNodeMB* node = ref.getAABBNodeMB(); @@ -714,13 +651,22 @@ namespace embree const vfloat* pFarX = (const vfloat*)((const char*)&node->lower_x+ray.farX); const vfloat* pFarY = (const vfloat*)((const char*)&node->lower_x+ray.farY); const vfloat* pFarZ = (const vfloat*)((const char*)&node->lower_x+ray.farZ); -#if defined (__AVX2__) +#if defined (__FMA_X4__) +#if defined(__aarch64__) + const vfloat tNearX = madd(madd(time,pNearX[6],vfloat(pNearX[0])), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat tNearY = madd(madd(time,pNearY[6],vfloat(pNearY[0])), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat tNearZ = madd(madd(time,pNearZ[6],vfloat(pNearZ[0])), ray.rdir.z, ray.neg_org_rdir.z); + const vfloat tFarX = madd(madd(time,pFarX [6],vfloat(pFarX [0])), ray.rdir.x, ray.neg_org_rdir.x); + const vfloat tFarY = madd(madd(time,pFarY [6],vfloat(pFarY [0])), ray.rdir.y, ray.neg_org_rdir.y); + const vfloat tFarZ = madd(madd(time,pFarZ [6],vfloat(pFarZ [0])), ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat tNearX = msub(madd(time,pNearX[6],vfloat(pNearX[0])), ray.rdir.x, ray.org_rdir.x); const vfloat tNearY = msub(madd(time,pNearY[6],vfloat(pNearY[0])), ray.rdir.y, ray.org_rdir.y); const vfloat tNearZ = msub(madd(time,pNearZ[6],vfloat(pNearZ[0])), ray.rdir.z, ray.org_rdir.z); const vfloat tFarX = msub(madd(time,pFarX [6],vfloat(pFarX [0])), ray.rdir.x, ray.org_rdir.x); const vfloat tFarY = msub(madd(time,pFarY [6],vfloat(pFarY [0])), ray.rdir.y, ray.org_rdir.y); const vfloat tFarZ = msub(madd(time,pFarZ [6],vfloat(pFarZ [0])), ray.rdir.z, ray.org_rdir.z); +#endif #else const vfloat tNearX = (madd(time,pNearX[6],vfloat(pNearX[0])) - ray.org.x) * ray.rdir.x; const vfloat tNearY = (madd(time,pNearY[6],vfloat(pNearY[0])) - ray.org.y) * ray.rdir.y; @@ -729,7 +675,7 @@ namespace embree const vfloat tFarY = (madd(time,pFarY [6],vfloat(pFarY [0])) - ray.org.y) * ray.rdir.y; const vfloat tFarZ = (madd(time,pFarZ [6],vfloat(pFarZ [0])) - ray.org.z) * ray.rdir.z; #endif -#if defined(__AVX2__) && !defined(__AVX512F__) +#if defined(__FMA_X4__) && !defined(__AVX512F__) const vfloat tNear = maxi(maxi(tNearX,tNearY),maxi(tNearZ,ray.tnear)); const vfloat tFar = mini(mini(tFarX ,tFarY ),mini(tFarZ ,ray.tfar )); #else @@ -751,7 +697,7 @@ namespace embree ////////////////////////////////////////////////////////////////////////////////////// template - __forceinline size_t intersectNodeMB4DRobust(const typename BVHN::NodeRef ref, const TravRay& ray, const float time, vfloat& dist) + __forceinline size_t intersectNodeMB4DRobust(const typename BVHN::NodeRef ref, const TravRay& ray, const float time, vfloat& dist) { const typename BVHN::AABBNodeMB* node = ref.getAABBNodeMB(); @@ -783,11 +729,11 @@ namespace embree // Fast QuantizedBaseNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template - __forceinline size_t intersectNode(const typename BVHN::QuantizedBaseNode* node, const TravRay& ray, vfloat& dist); + template + __forceinline size_t intersectNode(const typename BVHN::QuantizedBaseNode* node, const TravRay& ray, vfloat& dist); template<> - __forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,4,false>& ray, vfloat4& dist) + __forceinline size_t intersectNode<4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,false>& ray, vfloat4& dist) { const size_t mvalid = movemask(node->validMask()); const vfloat4 start_x(node->start.x); @@ -803,13 +749,22 @@ namespace embree const vfloat4 lower_z = madd(node->dequantize<4>(ray.nearZ >> 2),scale_z,start_z); const vfloat4 upper_z = madd(node->dequantize<4>(ray.farZ >> 2),scale_z,start_z); -#if defined(__AVX2__) +#if defined(__FMA_X4__) +#if defined(__aarch64__) + const vfloat4 tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat4 tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat4 tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat4 tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat4 tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat4 tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat4 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x); const vfloat4 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y); const vfloat4 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z); const vfloat4 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x); const vfloat4 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y); const vfloat4 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z); +#endif #else const vfloat4 tNearX = (lower_x - ray.org.x) * ray.rdir.x; const vfloat4 tNearY = (lower_y - ray.org.y) * ray.rdir.y; @@ -819,12 +774,12 @@ namespace embree const vfloat4 tFarZ = (upper_z - ray.org.z) * ray.rdir.z; #endif -#if defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW +#if defined(__aarch64__) || defined(__SSE4_1__) && !defined(__AVX512F__) // up to HSW const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool4 vmask = asInt(tNear) > asInt(tFar); const size_t mask = movemask(vmask) ^ ((1<<4)-1); -#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#elif defined(__AVX512F__) // SKX const vfloat4 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat4 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool4 vmask = asInt(tNear) <= asInt(tFar); @@ -840,7 +795,7 @@ namespace embree } template<> - __forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,4,true>& ray, vfloat4& dist) + __forceinline size_t intersectNode<4>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,true>& ray, vfloat4& dist) { const size_t mvalid = movemask(node->validMask()); const vfloat4 start_x(node->start.x); @@ -875,7 +830,7 @@ namespace embree #if defined(__AVX__) template<> - __forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,8,false>& ray, vfloat8& dist) + __forceinline size_t intersectNode<8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,false>& ray, vfloat8& dist) { const size_t mvalid = movemask(node->validMask()); const vfloat8 start_x(node->start.x); @@ -892,12 +847,21 @@ namespace embree const vfloat8 upper_z = madd(node->dequantize<8>(ray.farZ >> 2),scale_z,start_z); #if defined(__AVX2__) +#if defined(__aarch64__) + const vfloat8 tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat8 tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat8 tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat8 tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat8 tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat8 tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat8 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x); const vfloat8 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y); const vfloat8 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z); const vfloat8 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x); const vfloat8 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y); const vfloat8 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z); +#endif #else const vfloat8 tNearX = (lower_x - ray.org.x) * ray.rdir.x; const vfloat8 tNearY = (lower_y - ray.org.y) * ray.rdir.y; @@ -912,7 +876,7 @@ namespace embree const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool8 vmask = asInt(tNear) > asInt(tFar); const size_t mask = movemask(vmask) ^ ((1<<8)-1); -#elif defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#elif defined(__AVX512F__) // SKX const vfloat8 tNear = maxi(tNearX,tNearY,tNearZ,ray.tnear); const vfloat8 tFar = mini(tFarX ,tFarY ,tFarZ ,ray.tfar); const vbool8 vmask = asInt(tNear) <= asInt(tFar); @@ -928,7 +892,7 @@ namespace embree } template<> - __forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,8,true>& ray, vfloat8& dist) + __forceinline size_t intersectNode<8>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,true>& ray, vfloat8& dist) { const size_t mvalid = movemask(node->validMask()); const vfloat8 start_x(node->start.x); @@ -963,113 +927,8 @@ namespace embree #endif -#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL - - template<> - __forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,16,false>& ray, vfloat16& dist) - { - const size_t mvalid = movemask(node->validMask()); - const vfloat16 start_x(node->start.x); - const vfloat16 scale_x(node->scale.x); - const vfloat16 lower_x = madd(vfloat16(node->dequantize<4>(ray.nearX >> 2)),scale_x,start_x); - const vfloat16 upper_x = madd(vfloat16(node->dequantize<4>(ray.farX >> 2)),scale_x,start_x); - const vfloat16 start_y(node->start.y); - const vfloat16 scale_y(node->scale.y); - const vfloat16 lower_y = madd(vfloat16(node->dequantize<4>(ray.nearY >> 2)),scale_y,start_y); - const vfloat16 upper_y = madd(vfloat16(node->dequantize<4>(ray.farY >> 2)),scale_y,start_y); - const vfloat16 start_z(node->start.z); - const vfloat16 scale_z(node->scale.z); - const vfloat16 lower_z = madd(vfloat16(node->dequantize<4>(ray.nearZ >> 2)),scale_z,start_z); - const vfloat16 upper_z = madd(vfloat16(node->dequantize<4>(ray.farZ >> 2)),scale_z,start_z); - - const vfloat16 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x); - const vfloat16 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y); - const vfloat16 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z); - const vfloat16 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x); - const vfloat16 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y); - const vfloat16 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z); - const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear); - const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar); - const vbool16 vmask = le(vbool16(0xf),tNear,tFar); - const size_t mask = movemask(vmask) & mvalid; - dist = tNear; - return mask; - } - - template<> - __forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedBaseNode* node, const TravRay<4,16,true>& ray, vfloat16& dist) - { - const size_t mvalid = movemask(node->validMask()); - const vfloat16 start_x(node->start.x); - const vfloat16 scale_x(node->scale.x); - const vfloat16 lower_x = madd(vfloat16(node->dequantize<4>(ray.nearX >> 2)),scale_x,start_x); - const vfloat16 upper_x = madd(vfloat16(node->dequantize<4>(ray.farX >> 2)),scale_x,start_x); - const vfloat16 start_y(node->start.y); - const vfloat16 scale_y(node->scale.y); - const vfloat16 lower_y = madd(vfloat16(node->dequantize<4>(ray.nearY >> 2)),scale_y,start_y); - const vfloat16 upper_y = madd(vfloat16(node->dequantize<4>(ray.farY >> 2)),scale_y,start_y); - const vfloat16 start_z(node->start.z); - const vfloat16 scale_z(node->scale.z); - const vfloat16 lower_z = madd(vfloat16(node->dequantize<4>(ray.nearZ >> 2)),scale_z,start_z); - const vfloat16 upper_z = madd(vfloat16(node->dequantize<4>(ray.farZ >> 2)),scale_z,start_z); - - const vfloat16 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x; - const vfloat16 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y; - const vfloat16 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z; - const vfloat16 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x; - const vfloat16 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y; - const vfloat16 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z; - - const vfloat16 tNear = max(tNearX,tNearY,tNearZ,ray.tnear); - const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar); - const vbool16 vmask = le(vbool16(0xf),tNear,tFar); - const size_t mask = movemask(vmask) & mvalid; - dist = tNear; - return mask; - } - - template<> - __forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,16,false>& ray, vfloat16& dist) - { - const vbool16 m_valid(node->validMask16()); - const vfloat16 bminmaxX = node->dequantizeLowerUpperX(ray.permX); - const vfloat16 bminmaxY = node->dequantizeLowerUpperY(ray.permY); - const vfloat16 bminmaxZ = node->dequantizeLowerUpperZ(ray.permZ); - const vfloat16 tNearFarX = msub(bminmaxX, ray.rdir.x, ray.org_rdir.x); - const vfloat16 tNearFarY = msub(bminmaxY, ray.rdir.y, ray.org_rdir.y); - const vfloat16 tNearFarZ = msub(bminmaxZ, ray.rdir.z, ray.org_rdir.z); - const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, ray.tnear); - const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, ray.tfar); - const vbool16 vmask = le(m_valid,tNear,align_shift_right<8>(tFar, tFar)); - const size_t mask = movemask(vmask); - dist = tNear; - return mask; - } - - template<> - __forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedBaseNode* node, const TravRay<8,16,true>& ray, vfloat16& dist) - { - const vbool16 m_valid(node->validMask16()); - const vfloat16 bminmaxX = node->dequantizeLowerUpperX(ray.permX); - const vfloat16 bminmaxY = node->dequantizeLowerUpperY(ray.permY); - const vfloat16 bminmaxZ = node->dequantizeLowerUpperZ(ray.permZ); - const vfloat16 tNearFarX = (bminmaxX - ray.org.x) * ray.rdir_far.x; // FIXME: this is not conservative !!!!!!!!! - const vfloat16 tNearFarY = (bminmaxY - ray.org.y) * ray.rdir_far.y; - const vfloat16 tNearFarZ = (bminmaxZ - ray.org.z) * ray.rdir_far.z; - const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, ray.tnear); - const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, ray.tfar); - const vbool16 vmask = le(m_valid,tNear,align_shift_right<8>(tFar, tFar)); - const size_t mask = movemask(vmask); - dist = tNear; - return mask; - } - - -#endif - - - template - __forceinline size_t intersectNode(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + template + __forceinline size_t intersectNode(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { const vboolf mvalid = node->validMask(); const vfloat lower_x = node->dequantizeLowerX(time); @@ -1078,13 +937,22 @@ namespace embree const vfloat upper_y = node->dequantizeUpperY(time); const vfloat lower_z = node->dequantizeLowerZ(time); const vfloat upper_z = node->dequantizeUpperZ(time); -#if defined(__AVX2__) +#if defined(__FMA_X4__) +#if defined(__aarch64__) + const vfloat tNearX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat tNearY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat tNearZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat tFarX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat tFarY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat tFarZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x); const vfloat tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y); const vfloat tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z); const vfloat tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x); const vfloat tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y); const vfloat tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z); +#endif #else const vfloat tNearX = (lower_x - ray.org.x) * ray.rdir.x; const vfloat tNearY = (lower_y - ray.org.y) * ray.rdir.y; @@ -1102,7 +970,7 @@ namespace embree const vfloat tmaxZ = maxi(tNearZ,tFarZ); const vfloat tNear = maxi(tminX,tminY,tminZ,ray.tnear); const vfloat tFar = mini(tmaxX,tmaxY,tmaxZ,ray.tfar); -#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#if defined(__AVX512F__) // SKX const vbool vmask = le(mvalid,asInt(tNear),asInt(tFar)); #else const vbool vmask = (asInt(tNear) <= asInt(tFar)) & mvalid; @@ -1112,8 +980,8 @@ namespace embree return mask; } - template - __forceinline size_t intersectNode(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + template + __forceinline size_t intersectNode(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { const vboolf mvalid = node->validMask(); const vfloat lower_x = node->dequantizeLowerX(time); @@ -1137,7 +1005,7 @@ namespace embree const vfloat tmaxZ = maxi(tNearZ,tFarZ); const vfloat tNear = maxi(tminX,tminY,tminZ,ray.tnear); const vfloat tFar = mini(tmaxX,tmaxY,tmaxZ,ray.tfar); -#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#if defined(__AVX512F__) // SKX const vbool vmask = le(mvalid,asInt(tNear),asInt(tFar)); #else const vbool vmask = (asInt(tNear) <= asInt(tFar)) & mvalid; @@ -1147,83 +1015,12 @@ namespace embree return mask; } - -#if defined(__AVX512ER__) - // for KNL - template<> - __forceinline size_t intersectNode<4,16>(const typename BVHN<4>::QuantizedBaseNodeMB* node, const TravRay<4,16,false>& ray, const float time, vfloat<4>& dist) - { - const size_t mvalid = movemask(node->validMask()); - const vfloat16 lower_x = node->dequantizeLowerX(time); - const vfloat16 upper_x = node->dequantizeUpperX(time); - const vfloat16 lower_y = node->dequantizeLowerY(time); - const vfloat16 upper_y = node->dequantizeUpperY(time); - const vfloat16 lower_z = node->dequantizeLowerZ(time); - const vfloat16 upper_z = node->dequantizeUpperZ(time); - - const vfloat16 tNearX = msub(lower_x, ray.rdir.x, ray.org_rdir.x); - const vfloat16 tNearY = msub(lower_y, ray.rdir.y, ray.org_rdir.y); - const vfloat16 tNearZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z); - const vfloat16 tFarX = msub(upper_x, ray.rdir.x, ray.org_rdir.x); - const vfloat16 tFarY = msub(upper_y, ray.rdir.y, ray.org_rdir.y); - const vfloat16 tFarZ = msub(upper_z, ray.rdir.z, ray.org_rdir.z); - - const vfloat16 tminX = min(tNearX,tFarX); - const vfloat16 tmaxX = max(tNearX,tFarX); - const vfloat16 tminY = min(tNearY,tFarY); - const vfloat16 tmaxY = max(tNearY,tFarY); - const vfloat16 tminZ = min(tNearZ,tFarZ); - const vfloat16 tmaxZ = max(tNearZ,tFarZ); - const vfloat16 tNear = max(tminX,tminY,tminZ,ray.tnear); - const vfloat16 tFar = min(tmaxX,tmaxY,tmaxZ,ray.tfar ); - const vbool16 vmask = tNear <= tFar; - const size_t mask = movemask(vmask) & mvalid; - dist = extractN<4,0>(tNear); - return mask; - } - - - // for KNL - template<> - __forceinline size_t intersectNode<4,16>(const typename BVHN<4>::QuantizedBaseNodeMB* node, const TravRay<4,16,true>& ray, const float time, vfloat<4>& dist) - { - const size_t mvalid = movemask(node->validMask()); - const vfloat16 lower_x = node->dequantizeLowerX(time); - const vfloat16 upper_x = node->dequantizeUpperX(time); - const vfloat16 lower_y = node->dequantizeLowerY(time); - const vfloat16 upper_y = node->dequantizeUpperY(time); - const vfloat16 lower_z = node->dequantizeLowerZ(time); - const vfloat16 upper_z = node->dequantizeUpperZ(time); - - const vfloat16 tNearX = (lower_x - ray.org.x) * ray.rdir_near.x; - const vfloat16 tNearY = (lower_y - ray.org.y) * ray.rdir_near.y; - const vfloat16 tNearZ = (lower_z - ray.org.z) * ray.rdir_near.z; - const vfloat16 tFarX = (upper_x - ray.org.x) * ray.rdir_far.x; - const vfloat16 tFarY = (upper_y - ray.org.y) * ray.rdir_far.y; - const vfloat16 tFarZ = (upper_z - ray.org.z) * ray.rdir_far.z; - - const vfloat16 tminX = min(tNearX,tFarX); - const vfloat16 tmaxX = max(tNearX,tFarX); - const vfloat16 tminY = min(tNearY,tFarY); - const vfloat16 tmaxY = max(tNearY,tFarY); - const vfloat16 tminZ = min(tNearZ,tFarZ); - const vfloat16 tmaxZ = max(tNearZ,tFarZ); - const vfloat16 tNear = max(tminX,tminY,tminZ,ray.tnear); - const vfloat16 tFar = min(tmaxX,tmaxY,tmaxZ,ray.tfar ); - const vbool16 vmask = tNear <= tFar; - const size_t mask = movemask(vmask) & mvalid; - dist = extractN<4,0>(tNear); - return mask; - } - -#endif - ////////////////////////////////////////////////////////////////////////////////////// // Fast OBBNode intersection ////////////////////////////////////////////////////////////////////////////////////// template - __forceinline size_t intersectNode(const typename BVHN::OBBNode* node, const TravRay& ray, vfloat& dist) + __forceinline size_t intersectNode(const typename BVHN::OBBNode* node, const TravRay& ray, vfloat& dist) { const Vec3vf dir = xfmVector(node->naabb,ray.dir); //const Vec3vf nrdir = Vec3vf(vfloat(-1.0f))/dir; @@ -1254,7 +1051,7 @@ namespace embree ////////////////////////////////////////////////////////////////////////////////////// template - __forceinline size_t intersectNode(const typename BVHN::OBBNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + __forceinline size_t intersectNode(const typename BVHN::OBBNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { const AffineSpace3vf xfm = node->space0; const Vec3vf b0_lower = zero; @@ -1493,13 +1290,13 @@ namespace embree ////////////////////////////////////////////////////////////////////////////////////// /*! Intersects N nodes with 1 ray */ - template + template struct BVHNNodeIntersector1; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNode(node.getAABBNode(), ray, dist); @@ -1507,10 +1304,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNodeRobust(node.getAABBNode(), ray, dist); @@ -1518,10 +1315,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNode(node.getAABBNodeMB(), ray, time, dist); @@ -1529,10 +1326,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNodeRobust(node.getAABBNodeMB(), ray, time, dist); @@ -1540,10 +1337,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNodeMB4D(node, ray, time, dist); @@ -1551,10 +1348,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNodeMB4DRobust(node, ray, time, dist); @@ -1562,10 +1359,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (likely(node.isAABBNode())) mask = intersectNode(node.getAABBNode(), ray, dist); else if (unlikely(node.isOBBNode())) mask = intersectNode(node.ungetAABBNode(), ray, dist); @@ -1574,10 +1371,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (likely(node.isAABBNode())) mask = intersectNodeRobust(node.getAABBNode(), ray, dist); else if (unlikely(node.isOBBNode())) mask = intersectNode(node.ungetAABBNode(), ray, dist); @@ -1586,10 +1383,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (likely(node.isAABBNodeMB())) mask = intersectNode(node.getAABBNodeMB(), ray, time, dist); else if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist); @@ -1598,10 +1395,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (likely(node.isAABBNodeMB())) mask = intersectNodeRobust(node.getAABBNodeMB(), ray, time, dist); else if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist); @@ -1610,10 +1407,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist); @@ -1622,10 +1419,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; if (unlikely(node.isOBBNodeMB())) mask = intersectNode(node.ungetAABBNodeMB(), ray, time, dist); @@ -1634,10 +1431,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNode((const typename BVHN::QuantizedNode*)node.quantizedNode(), ray, dist); @@ -1645,10 +1442,10 @@ namespace embree } }; - template - struct BVHNNodeIntersector1 + template + struct BVHNNodeIntersector1 { - static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) + static __forceinline bool intersect(const typename BVHN::NodeRef& node, const TravRay& ray, float time, vfloat& dist, size_t& mask) { if (unlikely(node.isLeaf())) return false; mask = intersectNodeRobust((const typename BVHN::QuantizedNode*)node.quantizedNode(), ray, dist); @@ -1657,33 +1454,33 @@ namespace embree }; /*! Intersects N nodes with K rays */ - template + template struct BVHNQuantizedBaseNodeIntersector1; - template - struct BVHNQuantizedBaseNodeIntersector1 + template + struct BVHNQuantizedBaseNodeIntersector1 { - static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNode* node, const TravRay& ray, vfloat& dist) + static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNode* node, const TravRay& ray, vfloat& dist) { return intersectNode(node,ray,dist); } - static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { return intersectNode(node,ray,time,dist); } }; - template - struct BVHNQuantizedBaseNodeIntersector1 + template + struct BVHNQuantizedBaseNodeIntersector1 { - static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNode* node, const TravRay& ray, vfloat& dist) + static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNode* node, const TravRay& ray, vfloat& dist) { return intersectNode(node,ray,dist); } - static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) + static __forceinline size_t intersect(const typename BVHN::QuantizedBaseNodeMB* node, const TravRay& ray, const float time, vfloat& dist) { return intersectNode(node,ray,time,dist); } diff --git a/kernels/bvh/node_intersector_frustum.h b/kernels/bvh/node_intersector_frustum.h index dbce469324..cad4e6de2d 100644 --- a/kernels/bvh/node_intersector_frustum.h +++ b/kernels/bvh/node_intersector_frustum.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -37,12 +37,6 @@ namespace embree { __forceinline Frustum() {} - template - __forceinline Frustum(const vbool& valid, const Vec3vf& org, const Vec3vf& rdir, const vfloat& ray_tnear, const vfloat& ray_tfar, int N) - { - init(valid, org, rdir, ray_tnear, ray_tfar, N); - } - template __forceinline void init(const vbool& valid, const Vec3vf& org, const Vec3vf& rdir, const vfloat& ray_tnear, const vfloat& ray_tfar, int N) { @@ -81,9 +75,13 @@ namespace embree min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir); max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir); +#if defined (__aarch64__) + neg_min_org_rdir = -(min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org)); + neg_max_org_rdir = -(max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org)); +#else min_org_rdir = min_rdir * select(pos_rdir, reduced_max_org, reduced_min_org); max_org_rdir = max_rdir * select(pos_rdir, reduced_min_org, reduced_max_org); - +#endif min_dist = reduced_min_dist; max_dist = reduced_max_dist; @@ -101,9 +99,13 @@ namespace embree Vec3fa min_rdir; Vec3fa max_rdir; +#if defined (__aarch64__) + Vec3fa neg_min_org_rdir; + Vec3fa neg_max_org_rdir; +#else Vec3fa min_org_rdir; Vec3fa max_org_rdir; - +#endif float min_dist; float max_dist; }; @@ -116,12 +118,6 @@ namespace embree { __forceinline Frustum() {} - template - __forceinline Frustum(const vbool& valid, const Vec3vf& org, const Vec3vf& rdir, const vfloat& ray_tnear, const vfloat& ray_tfar, int N) - { - init(valid, org, rdir, ray_tnear, ray_tfar, N); - } - template __forceinline void init(const vbool& valid, const Vec3vf& org, const Vec3vf& rdir, const vfloat& ray_tnear, const vfloat& ray_tfar, int N) { @@ -192,28 +188,36 @@ namespace embree // Fast AABBNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template + template __forceinline size_t intersectNodeFrustum(const typename BVHN::AABBNode* __restrict__ node, - const FrustumFast& frustum, vfloat& dist) + const FrustumFast& frustum, vfloat& dist) { - const vfloat bminX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearX); - const vfloat bminY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearY); - const vfloat bminZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearZ); - const vfloat bmaxX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farX); - const vfloat bmaxY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farY); - const vfloat bmaxZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farZ); - - const vfloat fminX = msub(bminX, vfloat(frustum.min_rdir.x), vfloat(frustum.min_org_rdir.x)); - const vfloat fminY = msub(bminY, vfloat(frustum.min_rdir.y), vfloat(frustum.min_org_rdir.y)); - const vfloat fminZ = msub(bminZ, vfloat(frustum.min_rdir.z), vfloat(frustum.min_org_rdir.z)); - const vfloat fmaxX = msub(bmaxX, vfloat(frustum.max_rdir.x), vfloat(frustum.max_org_rdir.x)); - const vfloat fmaxY = msub(bmaxY, vfloat(frustum.max_rdir.y), vfloat(frustum.max_org_rdir.y)); - const vfloat fmaxZ = msub(bmaxZ, vfloat(frustum.max_rdir.z), vfloat(frustum.max_org_rdir.z)); - - const vfloat fmin = maxi(fminX, fminY, fminZ, vfloat(frustum.min_dist)); + const vfloat bminX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearX); + const vfloat bminY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearY); + const vfloat bminZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearZ); + const vfloat bmaxX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farX); + const vfloat bmaxY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farY); + const vfloat bmaxZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farZ); + +#if defined (__aarch64__) + const vfloat fminX = madd(bminX, vfloat(frustum.min_rdir.x), vfloat(frustum.neg_min_org_rdir.x)); + const vfloat fminY = madd(bminY, vfloat(frustum.min_rdir.y), vfloat(frustum.neg_min_org_rdir.y)); + const vfloat fminZ = madd(bminZ, vfloat(frustum.min_rdir.z), vfloat(frustum.neg_min_org_rdir.z)); + const vfloat fmaxX = madd(bmaxX, vfloat(frustum.max_rdir.x), vfloat(frustum.neg_max_org_rdir.x)); + const vfloat fmaxY = madd(bmaxY, vfloat(frustum.max_rdir.y), vfloat(frustum.neg_max_org_rdir.y)); + const vfloat fmaxZ = madd(bmaxZ, vfloat(frustum.max_rdir.z), vfloat(frustum.neg_max_org_rdir.z)); +#else + const vfloat fminX = msub(bminX, vfloat(frustum.min_rdir.x), vfloat(frustum.min_org_rdir.x)); + const vfloat fminY = msub(bminY, vfloat(frustum.min_rdir.y), vfloat(frustum.min_org_rdir.y)); + const vfloat fminZ = msub(bminZ, vfloat(frustum.min_rdir.z), vfloat(frustum.min_org_rdir.z)); + const vfloat fmaxX = msub(bmaxX, vfloat(frustum.max_rdir.x), vfloat(frustum.max_org_rdir.x)); + const vfloat fmaxY = msub(bmaxY, vfloat(frustum.max_rdir.y), vfloat(frustum.max_org_rdir.y)); + const vfloat fmaxZ = msub(bmaxZ, vfloat(frustum.max_rdir.z), vfloat(frustum.max_org_rdir.z)); +#endif + const vfloat fmin = maxi(fminX, fminY, fminZ, vfloat(frustum.min_dist)); dist = fmin; - const vfloat fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat(frustum.max_dist)); - const vbool vmask_node_hit = fmin <= fmax; + const vfloat fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat(frustum.max_dist)); + const vbool vmask_node_hit = fmin <= fmax; size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1); return m_node; } @@ -222,30 +226,30 @@ namespace embree // Robust AABBNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template + template __forceinline size_t intersectNodeFrustum(const typename BVHN::AABBNode* __restrict__ node, - const FrustumRobust& frustum, vfloat& dist) + const FrustumRobust& frustum, vfloat& dist) { - const vfloat bminX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearX); - const vfloat bminY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearY); - const vfloat bminZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearZ); - const vfloat bmaxX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farX); - const vfloat bmaxY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farY); - const vfloat bmaxZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farZ); - - const vfloat fminX = (bminX - vfloat(frustum.min_org.x)) * vfloat(frustum.min_rdir.x); - const vfloat fminY = (bminY - vfloat(frustum.min_org.y)) * vfloat(frustum.min_rdir.y); - const vfloat fminZ = (bminZ - vfloat(frustum.min_org.z)) * vfloat(frustum.min_rdir.z); - const vfloat fmaxX = (bmaxX - vfloat(frustum.max_org.x)) * vfloat(frustum.max_rdir.x); - const vfloat fmaxY = (bmaxY - vfloat(frustum.max_org.y)) * vfloat(frustum.max_rdir.y); - const vfloat fmaxZ = (bmaxZ - vfloat(frustum.max_org.z)) * vfloat(frustum.max_rdir.z); + const vfloat bminX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearX); + const vfloat bminY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearY); + const vfloat bminZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.nearZ); + const vfloat bmaxX = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farX); + const vfloat bmaxY = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farY); + const vfloat bmaxZ = *(const vfloat*)((const char*)&node->lower_x + frustum.nf.farZ); + + const vfloat fminX = (bminX - vfloat(frustum.min_org.x)) * vfloat(frustum.min_rdir.x); + const vfloat fminY = (bminY - vfloat(frustum.min_org.y)) * vfloat(frustum.min_rdir.y); + const vfloat fminZ = (bminZ - vfloat(frustum.min_org.z)) * vfloat(frustum.min_rdir.z); + const vfloat fmaxX = (bmaxX - vfloat(frustum.max_org.x)) * vfloat(frustum.max_rdir.x); + const vfloat fmaxY = (bmaxY - vfloat(frustum.max_org.y)) * vfloat(frustum.max_rdir.y); + const vfloat fmaxZ = (bmaxZ - vfloat(frustum.max_org.z)) * vfloat(frustum.max_rdir.z); const float round_down = 1.0f-2.0f*float(ulp); // FIXME: use per instruction rounding for AVX512 const float round_up = 1.0f+2.0f*float(ulp); - const vfloat fmin = max(fminX, fminY, fminZ, vfloat(frustum.min_dist)); + const vfloat fmin = max(fminX, fminY, fminZ, vfloat(frustum.min_dist)); dist = fmin; - const vfloat fmax = min(fmaxX, fmaxY, fmaxZ, vfloat(frustum.max_dist)); - const vbool vmask_node_hit = (round_down*fmin <= round_up*fmax); + const vfloat fmax = min(fmaxX, fmaxY, fmaxZ, vfloat(frustum.max_dist)); + const vbool vmask_node_hit = (round_down*fmin <= round_up*fmax); size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1); return m_node; } diff --git a/kernels/bvh/node_intersector_packet.h b/kernels/bvh/node_intersector_packet.h index 1cc0d47fab..4deacd620d 100644 --- a/kernels/bvh/node_intersector_packet.h +++ b/kernels/bvh/node_intersector_packet.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -39,7 +39,9 @@ namespace embree org = ray_org; dir = ray_dir; rdir = rcp_safe(ray_dir); -#if defined(__AVX2__) +#if defined(__aarch64__) + neg_org_rdir = -(org * rdir); +#elif defined(__AVX2__) org_rdir = org * rdir; #endif @@ -55,7 +57,9 @@ namespace embree Vec3vf org; Vec3vf dir; Vec3vf rdir; -#if defined(__AVX2__) +#if defined(__aarch64__) + Vec3vf neg_org_rdir; +#elif defined(__AVX2__) Vec3vf org_rdir; #endif Vec3vi nearXYZ; @@ -119,7 +123,14 @@ namespace embree const TravRayKFast& ray, vfloat& dist) { - #if defined(__AVX2__) +#if defined(__aarch64__) + const vfloat lclipMinX = madd(node->lower_x[i], ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMinY = madd(node->lower_y[i], ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMinZ = madd(node->lower_z[i], ray.rdir.z, ray.neg_org_rdir.z); + const vfloat lclipMaxX = madd(node->upper_x[i], ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMaxY = madd(node->upper_y[i], ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMaxZ = madd(node->upper_z[i], ray.rdir.z, ray.neg_org_rdir.z); +#elif defined(__AVX2__) const vfloat lclipMinX = msub(node->lower_x[i], ray.rdir.x, ray.org_rdir.x); const vfloat lclipMinY = msub(node->lower_y[i], ray.rdir.y, ray.org_rdir.y); const vfloat lclipMinZ = msub(node->lower_z[i], ray.rdir.z, ray.org_rdir.z); @@ -135,7 +146,7 @@ namespace embree const vfloat lclipMaxZ = (node->upper_z[i] - ray.org.z) * ray.rdir.z; #endif - #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX + #if defined(__AVX512F__) // SKX if (K == 16) { /* use mixed float/int min/max */ @@ -150,7 +161,7 @@ namespace embree { const vfloat lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ)); const vfloat lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ)); - #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX + #if defined(__AVX512F__) // SKX const vbool lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar)); #else const vbool lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar); @@ -199,7 +210,14 @@ namespace embree const vfloat vupper_y = madd(time, vfloat(node->upper_dy[i]), vfloat(node->upper_y[i])); const vfloat vupper_z = madd(time, vfloat(node->upper_dz[i]), vfloat(node->upper_z[i])); -#if defined(__AVX2__) +#if defined(__aarch64__) + const vfloat lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z); +#elif defined(__AVX2__) const vfloat lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x); const vfloat lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y); const vfloat lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z); @@ -215,7 +233,7 @@ namespace embree const vfloat lclipMaxZ = (vupper_z - ray.org.z) * ray.rdir.z; #endif -#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#if defined(__AVX512F__) // SKX if (K == 16) { /* use mixed float/int min/max */ @@ -230,7 +248,7 @@ namespace embree { const vfloat lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ)); const vfloat lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ)); -#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#if defined(__AVX512F__) // SKX const vbool lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar)); #else const vbool lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar); @@ -265,7 +283,7 @@ namespace embree const float round_up = 1.0f+3.0f*float(ulp); const float round_down = 1.0f-3.0f*float(ulp); -#if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX +#if defined(__AVX512F__) // SKX if (K == 16) { const vfloat lnearP = round_down*maxi(min(lclipMinX, lclipMaxX), min(lclipMinY, lclipMaxY), min(lclipMinZ, lclipMaxZ)); @@ -302,7 +320,14 @@ namespace embree const vfloat vupper_y = madd(time, vfloat(node->upper_dy[i]), vfloat(node->upper_y[i])); const vfloat vupper_z = madd(time, vfloat(node->upper_dz[i]), vfloat(node->upper_z[i])); -#if defined(__AVX2__) +#if defined(__aarch64__) + const vfloat lclipMinX = madd(vlower_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMinY = madd(vlower_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMinZ = madd(vlower_z, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat lclipMaxX = madd(vupper_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMaxY = madd(vupper_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMaxZ = madd(vupper_z, ray.rdir.z, ray.neg_org_rdir.z); +#elif defined(__AVX2__) const vfloat lclipMinX = msub(vlower_x, ray.rdir.x, ray.org_rdir.x); const vfloat lclipMinY = msub(vlower_y, ray.rdir.y, ray.org_rdir.y); const vfloat lclipMinZ = msub(vlower_z, ray.rdir.z, ray.org_rdir.z); @@ -464,7 +489,14 @@ namespace embree const vfloat lower_z = node->dequantizeLowerZ(); const vfloat upper_z = node->dequantizeUpperZ(); - #if defined(__AVX2__) + #if defined(__aarch64__) + const vfloat lclipMinX = madd(lower_x[i], ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMinY = madd(lower_y[i], ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMinZ = madd(lower_z[i], ray.rdir.z, ray.neg_org_rdir.z); + const vfloat lclipMaxX = madd(upper_x[i], ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMaxY = madd(upper_y[i], ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMaxZ = madd(upper_z[i], ray.rdir.z, ray.neg_org_rdir.z); + #elif defined(__AVX2__) const vfloat lclipMinX = msub(lower_x[i], ray.rdir.x, ray.org_rdir.x); const vfloat lclipMinY = msub(lower_y[i], ray.rdir.y, ray.org_rdir.y); const vfloat lclipMinZ = msub(lower_z[i], ray.rdir.z, ray.org_rdir.z); @@ -480,7 +512,7 @@ namespace embree const vfloat lclipMaxZ = (upper_z[i] - ray.org.z) * ray.rdir.z; #endif - #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX + #if defined(__AVX512F__) // SKX if (K == 16) { /* use mixed float/int min/max */ @@ -495,7 +527,7 @@ namespace embree { const vfloat lnearP = maxi(mini(lclipMinX, lclipMaxX), mini(lclipMinY, lclipMaxY), mini(lclipMinZ, lclipMaxZ)); const vfloat lfarP = mini(maxi(lclipMinX, lclipMaxX), maxi(lclipMinY, lclipMaxY), maxi(lclipMinZ, lclipMaxZ)); - #if defined(__AVX512F__) && !defined(__AVX512ER__) // SKX + #if defined(__AVX512F__) // SKX const vbool lhit = asInt(maxi(lnearP, ray.tnear)) <= asInt(mini(lfarP, ray.tfar)); #else const vbool lhit = maxi(lnearP, ray.tnear) <= mini(lfarP, ray.tfar); @@ -542,14 +574,21 @@ namespace embree { assert(movemask(node->validMask()) & ((size_t)1 << i)); - const vfloat lower_x = node->dequantizeLowerX(i,time); - const vfloat upper_x = node->dequantizeUpperX(i,time); - const vfloat lower_y = node->dequantizeLowerY(i,time); - const vfloat upper_y = node->dequantizeUpperY(i,time); - const vfloat lower_z = node->dequantizeLowerZ(i,time); - const vfloat upper_z = node->dequantizeUpperZ(i,time); + const vfloat lower_x = node->template dequantizeLowerX(i,time); + const vfloat upper_x = node->template dequantizeUpperX(i,time); + const vfloat lower_y = node->template dequantizeLowerY(i,time); + const vfloat upper_y = node->template dequantizeUpperY(i,time); + const vfloat lower_z = node->template dequantizeLowerZ(i,time); + const vfloat upper_z = node->template dequantizeUpperZ(i,time); -#if defined(__AVX2__) +#if defined(__aarch64__) + const vfloat lclipMinX = madd(lower_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMinY = madd(lower_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMinZ = madd(lower_z, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat lclipMaxX = madd(upper_x, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat lclipMaxY = madd(upper_y, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat lclipMaxZ = madd(upper_z, ray.rdir.z, ray.neg_org_rdir.z); +#elif defined(__AVX2__) const vfloat lclipMinX = msub(lower_x, ray.rdir.x, ray.org_rdir.x); const vfloat lclipMinY = msub(lower_y, ray.rdir.y, ray.org_rdir.y); const vfloat lclipMinZ = msub(lower_z, ray.rdir.z, ray.org_rdir.z); @@ -579,12 +618,12 @@ namespace embree { assert(movemask(node->validMask()) & ((size_t)1 << i)); - const vfloat lower_x = node->dequantizeLowerX(i,time); - const vfloat upper_x = node->dequantizeUpperX(i,time); - const vfloat lower_y = node->dequantizeLowerY(i,time); - const vfloat upper_y = node->dequantizeUpperY(i,time); - const vfloat lower_z = node->dequantizeLowerZ(i,time); - const vfloat upper_z = node->dequantizeUpperZ(i,time); + const vfloat lower_x = node->template dequantizeLowerX(i,time); + const vfloat upper_x = node->template dequantizeUpperX(i,time); + const vfloat lower_y = node->template dequantizeLowerY(i,time); + const vfloat upper_y = node->template dequantizeUpperY(i,time); + const vfloat lower_z = node->template dequantizeLowerZ(i,time); + const vfloat upper_z = node->template dequantizeUpperZ(i,time); const vfloat lclipMinX = (lower_x - ray.org.x) * ray.rdir.x; const vfloat lclipMinY = (lower_y - ray.org.y) * ray.rdir.y; diff --git a/kernels/bvh/node_intersector_packet_stream.h b/kernels/bvh/node_intersector_packet_stream.h index c2b5b0cb7a..943fd7043f 100644 --- a/kernels/bvh/node_intersector_packet_stream.h +++ b/kernels/bvh/node_intersector_packet_stream.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -32,11 +32,19 @@ namespace embree __forceinline void init(const Vec3vf& ray_org, const Vec3vf& ray_dir) { rdir = rcp_safe(ray_dir); +#if defined(__aarch64__) + neg_org_rdir = -(ray_org * rdir); +#else org_rdir = ray_org * rdir; +#endif } Vec3vf rdir; +#if defined(__aarch64__) + Vec3vf neg_org_rdir; +#else Vec3vf org_rdir; +#endif vfloat tnear; vfloat tfar; }; @@ -76,27 +84,36 @@ namespace embree // Fast AABBNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template + template __forceinline size_t intersectNode1(const typename BVHN::AABBNode* __restrict__ node, const TravRayKStreamFast& ray, size_t k, const NearFarPrecalculations& nf) { - const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); - const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); - const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); - const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); - const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); - const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); - - const vfloat rminX = msub(bminX, vfloat(ray.rdir.x[k]), vfloat(ray.org_rdir.x[k])); - const vfloat rminY = msub(bminY, vfloat(ray.rdir.y[k]), vfloat(ray.org_rdir.y[k])); - const vfloat rminZ = msub(bminZ, vfloat(ray.rdir.z[k]), vfloat(ray.org_rdir.z[k])); - const vfloat rmaxX = msub(bmaxX, vfloat(ray.rdir.x[k]), vfloat(ray.org_rdir.x[k])); - const vfloat rmaxY = msub(bmaxY, vfloat(ray.rdir.y[k]), vfloat(ray.org_rdir.y[k])); - const vfloat rmaxZ = msub(bmaxZ, vfloat(ray.rdir.z[k]), vfloat(ray.org_rdir.z[k])); - const vfloat rmin = maxi(rminX, rminY, rminZ, vfloat(ray.tnear[k])); - const vfloat rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat(ray.tfar[k])); - - const vbool vmask_first_hit = rmin <= rmax; + const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); + const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); + const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); + const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); + const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); + const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); + +#if defined (__aarch64__) + const vfloat rminX = madd(bminX, vfloat(ray.rdir.x[k]), vfloat(ray.neg_org_rdir.x[k])); + const vfloat rminY = madd(bminY, vfloat(ray.rdir.y[k]), vfloat(ray.neg_org_rdir.y[k])); + const vfloat rminZ = madd(bminZ, vfloat(ray.rdir.z[k]), vfloat(ray.neg_org_rdir.z[k])); + const vfloat rmaxX = madd(bmaxX, vfloat(ray.rdir.x[k]), vfloat(ray.neg_org_rdir.x[k])); + const vfloat rmaxY = madd(bmaxY, vfloat(ray.rdir.y[k]), vfloat(ray.neg_org_rdir.y[k])); + const vfloat rmaxZ = madd(bmaxZ, vfloat(ray.rdir.z[k]), vfloat(ray.neg_org_rdir.z[k])); +#else + const vfloat rminX = msub(bminX, vfloat(ray.rdir.x[k]), vfloat(ray.org_rdir.x[k])); + const vfloat rminY = msub(bminY, vfloat(ray.rdir.y[k]), vfloat(ray.org_rdir.y[k])); + const vfloat rminZ = msub(bminZ, vfloat(ray.rdir.z[k]), vfloat(ray.org_rdir.z[k])); + const vfloat rmaxX = msub(bmaxX, vfloat(ray.rdir.x[k]), vfloat(ray.org_rdir.x[k])); + const vfloat rmaxY = msub(bmaxY, vfloat(ray.rdir.y[k]), vfloat(ray.org_rdir.y[k])); + const vfloat rmaxZ = msub(bmaxZ, vfloat(ray.rdir.z[k]), vfloat(ray.org_rdir.z[k])); +#endif + const vfloat rmin = maxi(rminX, rminY, rminZ, vfloat(ray.tnear[k])); + const vfloat rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat(ray.tfar[k])); + + const vbool vmask_first_hit = rmin <= rmax; return movemask(vmask_first_hit) & (((size_t)1 << N)-1); } @@ -113,12 +130,21 @@ namespace embree const vfloat bmaxY = *(const float*)(ptr + nf.farY); const vfloat bmaxZ = *(const float*)(ptr + nf.farZ); +#if defined (__aarch64__) + const vfloat rminX = madd(bminX, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat rminY = madd(bminY, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat rminZ = madd(bminZ, ray.rdir.z, ray.neg_org_rdir.z); + const vfloat rmaxX = madd(bmaxX, ray.rdir.x, ray.neg_org_rdir.x); + const vfloat rmaxY = madd(bmaxY, ray.rdir.y, ray.neg_org_rdir.y); + const vfloat rmaxZ = madd(bmaxZ, ray.rdir.z, ray.neg_org_rdir.z); +#else const vfloat rminX = msub(bminX, ray.rdir.x, ray.org_rdir.x); const vfloat rminY = msub(bminY, ray.rdir.y, ray.org_rdir.y); const vfloat rminZ = msub(bminZ, ray.rdir.z, ray.org_rdir.z); const vfloat rmaxX = msub(bmaxX, ray.rdir.x, ray.org_rdir.x); const vfloat rmaxY = msub(bmaxY, ray.rdir.y, ray.org_rdir.y); const vfloat rmaxZ = msub(bmaxZ, ray.rdir.z, ray.org_rdir.z); +#endif const vfloat rmin = maxi(rminX, rminY, rminZ, ray.tnear); const vfloat rmax = mini(rmaxX, rmaxY, rmaxZ, ray.tfar); @@ -132,28 +158,28 @@ namespace embree // Robust AABBNode intersection ////////////////////////////////////////////////////////////////////////////////////// - template + template __forceinline size_t intersectNode1(const typename BVHN::AABBNode* __restrict__ node, const TravRayKStreamRobust& ray, size_t k, const NearFarPrecalculations& nf) { - const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); - const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); - const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); - const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); - const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); - const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); - - const vfloat rminX = (bminX - vfloat(ray.org.x[k])) * vfloat(ray.rdir.x[k]); - const vfloat rminY = (bminY - vfloat(ray.org.y[k])) * vfloat(ray.rdir.y[k]); - const vfloat rminZ = (bminZ - vfloat(ray.org.z[k])) * vfloat(ray.rdir.z[k]); - const vfloat rmaxX = (bmaxX - vfloat(ray.org.x[k])) * vfloat(ray.rdir.x[k]); - const vfloat rmaxY = (bmaxY - vfloat(ray.org.y[k])) * vfloat(ray.rdir.y[k]); - const vfloat rmaxZ = (bmaxZ - vfloat(ray.org.z[k])) * vfloat(ray.rdir.z[k]); + const vfloat bminX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearX)); + const vfloat bminY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearY)); + const vfloat bminZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.nearZ)); + const vfloat bmaxX = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farX)); + const vfloat bmaxY = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farY)); + const vfloat bmaxZ = vfloat(*(const vfloat*)((const char*)&node->lower_x + nf.farZ)); + + const vfloat rminX = (bminX - vfloat(ray.org.x[k])) * vfloat(ray.rdir.x[k]); + const vfloat rminY = (bminY - vfloat(ray.org.y[k])) * vfloat(ray.rdir.y[k]); + const vfloat rminZ = (bminZ - vfloat(ray.org.z[k])) * vfloat(ray.rdir.z[k]); + const vfloat rmaxX = (bmaxX - vfloat(ray.org.x[k])) * vfloat(ray.rdir.x[k]); + const vfloat rmaxY = (bmaxY - vfloat(ray.org.y[k])) * vfloat(ray.rdir.y[k]); + const vfloat rmaxZ = (bmaxZ - vfloat(ray.org.z[k])) * vfloat(ray.rdir.z[k]); const float round_up = 1.0f+3.0f*float(ulp); // FIXME: use per instruction rounding for AVX512 - const vfloat rmin = max(rminX, rminY, rminZ, vfloat(ray.tnear[k])); - const vfloat rmax = round_up *min(rmaxX, rmaxY, rmaxZ, vfloat(ray.tfar[k])); + const vfloat rmin = max(rminX, rminY, rminZ, vfloat(ray.tnear[k])); + const vfloat rmax = round_up *min(rmaxX, rmaxY, rmaxZ, vfloat(ray.tfar[k])); - const vbool vmask_first_hit = rmin <= rmax; + const vbool vmask_first_hit = rmin <= rmax; return movemask(vmask_first_hit) & (((size_t)1 << N)-1); } diff --git a/kernels/common/accel.h b/kernels/common/accel.h index f332d36555..d24326ce92 100644 --- a/kernels/common/accel.h +++ b/kernels/common/accel.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -332,7 +332,7 @@ namespace embree intersectorN.intersect(this,rayN,N,context); } -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) __forceinline void intersect(const vbool4& valid, RayHitK<4>& ray, IntersectContext* context) { const vint<4> mask = valid.mask32(); intersect4(&mask,(RTCRayHit4&)ray,context); @@ -388,7 +388,7 @@ namespace embree intersectorN.occluded(this,rayN,N,context); } -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) __forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) { const vint<4> mask = valid.mask32(); occluded4(&mask,(RTCRay4&)ray,context); diff --git a/kernels/common/accelinstance.h b/kernels/common/accelinstance.h index d74b96df3f..c63ef998bd 100644 --- a/kernels/common/accelinstance.h +++ b/kernels/common/accelinstance.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/acceln.cpp b/kernels/common/acceln.cpp index c9f7e92193..111c62083d 100644 --- a/kernels/common/acceln.cpp +++ b/kernels/common/acceln.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "acceln.h" @@ -97,7 +97,7 @@ namespace embree for (size_t i=0; iaccels.size(); i++) { if (This->accels[i]->isEmpty()) continue; This->accels[i]->intersectors.occluded4(valid,ray,context); -#if defined(__SSE2__) +#if defined(__SSE2__) || defined(__ARM_NEON) vbool4 valid0 = asBool(((vint4*)valid)[0]); vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero); if (unlikely(none(valid0 & hit0))) break; @@ -111,7 +111,7 @@ namespace embree for (size_t i=0; iaccels.size(); i++) { if (This->accels[i]->isEmpty()) continue; This->accels[i]->intersectors.occluded8(valid,ray,context); -#if defined(__SSE2__) // FIXME: use higher ISA +#if defined(__SSE2__) || defined(__ARM_NEON) // FIXME: use higher ISA vbool4 valid0 = asBool(((vint4*)valid)[0]); vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero); vbool4 valid1 = asBool(((vint4*)valid)[1]); @@ -127,7 +127,7 @@ namespace embree for (size_t i=0; iaccels.size(); i++) { if (This->accels[i]->isEmpty()) continue; This->accels[i]->intersectors.occluded16(valid,ray,context); -#if defined(__SSE2__) // FIXME: use higher ISA +#if defined(__SSE2__) || defined(__ARM_NEON) // FIXME: use higher ISA vbool4 valid0 = asBool(((vint4*)valid)[0]); vbool4 hit0 = ((vfloat4*)ray.tfar)[0] >= vfloat4(zero); vbool4 valid1 = asBool(((vint4*)valid)[1]); diff --git a/kernels/common/acceln.h b/kernels/common/acceln.h index 2edd98f647..0445b2e811 100644 --- a/kernels/common/acceln.h +++ b/kernels/common/acceln.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/accelset.cpp b/kernels/common/accelset.cpp index 79be1c4301..8c18f31776 100644 --- a/kernels/common/accelset.cpp +++ b/kernels/common/accelset.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "accelset.h" diff --git a/kernels/common/accelset.h b/kernels/common/accelset.h index 7177957923..1b67120c97 100644 --- a/kernels/common/accelset.h +++ b/kernels/common/accelset.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,21 +14,14 @@ namespace embree struct IntersectFunctionNArguments; struct OccludedFunctionNArguments; - typedef void (*ReportIntersectionFunc) (IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args); - typedef void (*ReportOcclusionFunc) (OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args); - struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments { - IntersectContext* internal_context; Geometry* geometry; - ReportIntersectionFunc report; }; struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments { - IntersectContext* internal_context; Geometry* geometry; - ReportOcclusionFunc report; }; /*! Base class for set of acceleration structures. */ @@ -68,7 +61,7 @@ namespace embree __forceinline bool valid(size_t i, const range& itime_range) const { for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) - if (!isvalid(bounds(i,itime))) return false; + if (!isvalid_non_empty(bounds(i,itime))) return false; return true; } @@ -109,7 +102,7 @@ namespace embree { const BBox3fa b = bounds(i); if (bbox) *bbox = b; - return isvalid(b); + return isvalid_non_empty(b); } /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */ @@ -117,7 +110,7 @@ namespace embree { const LBBox3fa bounds = linearBounds(i,itime); bbox = bounds.bounds0; // use bounding box of first timestep to build BVH - return isvalid(bounds); + return isvalid_non_empty(bounds); } /*! calculates the linear bounds of the i'th primitive for the specified time range */ @@ -145,7 +138,7 @@ namespace embree public: /*! Intersects a single ray with the scene. */ - __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report) + __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context) { assert(primID < size()); assert(intersectorN.intersect); @@ -159,15 +152,13 @@ namespace embree args.N = 1; args.geomID = geomID; args.primID = primID; - args.internal_context = context; args.geometry = this; - args.report = report; intersectorN.intersect(&args); } /*! Tests if single ray is occluded by the scene. */ - __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report) + __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context) { assert(primID < size()); assert(intersectorN.occluded); @@ -181,16 +172,14 @@ namespace embree args.N = 1; args.geomID = geomID; args.primID = primID; - args.internal_context = context; args.geometry = this; - args.report = report; intersectorN.occluded(&args); } /*! Intersects a packet of K rays with the scene. */ template - __forceinline void intersect (const vbool& valid, RayHitK& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report) + __forceinline void intersect (const vbool& valid, RayHitK& ray, unsigned int geomID, unsigned int primID, IntersectContext* context) { assert(primID < size()); assert(intersectorN.intersect); @@ -204,16 +193,14 @@ namespace embree args.N = K; args.geomID = geomID; args.primID = primID; - args.internal_context = context; args.geometry = this; - args.report = report; intersectorN.intersect(&args); } /*! Tests if a packet of K rays is occluded by the scene. */ template - __forceinline void occluded (const vbool& valid, RayK& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report) + __forceinline void occluded (const vbool& valid, RayK& ray, unsigned int geomID, unsigned int primID, IntersectContext* context) { assert(primID < size()); assert(intersectorN.occluded); @@ -227,9 +214,7 @@ namespace embree args.N = K; args.geomID = geomID; args.primID = primID; - args.internal_context = context; args.geometry = this; - args.report = report; intersectorN.occluded(&args); } diff --git a/kernels/common/alloc.cpp b/kernels/common/alloc.cpp index f958a16f56..38a76225f4 100644 --- a/kernels/common/alloc.cpp +++ b/kernels/common/alloc.cpp @@ -1,8 +1,11 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "alloc.h" #include "../../common/sys/thread.h" +#if defined(APPLE) && defined(__aarch64__) +#include "../../common/sys/barrier.h" +#endif namespace embree { diff --git a/kernels/common/alloc.h b/kernels/common/alloc.h index 3a5bb966b8..b71263178f 100644 --- a/kernels/common/alloc.h +++ b/kernels/common/alloc.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,6 +8,10 @@ #include "scene.h" #include "primref.h" +#if defined(APPLE) && defined(__aarch64__) +#include +#endif + namespace embree { class FastAllocator @@ -26,7 +30,7 @@ namespace embree public: struct ThreadLocal2; - enum AllocationType { ALIGNED_MALLOC, OS_MALLOC, SHARED, ANY_TYPE }; + enum AllocationType { ALIGNED_MALLOC, EMBREE_OS_MALLOC, SHARED, ANY_TYPE }; /*! Per thread structure holding the current memory block. */ struct __aligned(64) ThreadLocal @@ -132,7 +136,11 @@ namespace embree { assert(alloc_i); if (alloc.load() == alloc_i) return; +#if defined(APPLE) && defined(__aarch64__) + std::scoped_lock lock(mutex); +#else Lock lock(mutex); +#endif //if (alloc.load() == alloc_i) return; // not required as only one thread calls bind if (alloc.load()) { alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes(); @@ -150,7 +158,11 @@ namespace embree { assert(alloc_i); if (alloc.load() != alloc_i) return; +#if defined(APPLE) && defined(__aarch64__) + std::scoped_lock lock(mutex); +#else Lock lock(mutex); +#endif if (alloc.load() != alloc_i) return; // required as a different thread calls unbind alloc.load()->bytesUsed += alloc0.getUsedBytes() + alloc1.getUsedBytes(); alloc.load()->bytesFree += alloc0.getFreeBytes() + alloc1.getFreeBytes(); @@ -161,7 +173,11 @@ namespace embree } public: +#if defined(APPLE) && defined(__aarch64__) + std::mutex mutex; +#else SpinLock mutex; //!< required as unbind is called from other threads +#endif std::atomic alloc; //!< parent allocator ThreadLocal alloc0; ThreadLocal alloc1; @@ -169,7 +185,7 @@ namespace embree FastAllocator (Device* device, bool osAllocation) : device(device), slotMask(0), usedBlocks(nullptr), freeBlocks(nullptr), use_single_mode(false), defaultBlockSize(PAGE_SIZE), estimatedSize(0), - growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? OS_MALLOC : ALIGNED_MALLOC), + growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? EMBREE_OS_MALLOC : ALIGNED_MALLOC), primrefarray(device,0) { for (size_t i=0; i lock(s_thread_local_allocators_lock); +#endif s_thread_local_allocators.push_back(make_unique(alloc)); } return alloc; @@ -227,7 +247,11 @@ namespace embree __forceinline void join(ThreadLocal2* alloc) { +#if defined(APPLE) && defined(__aarch64__) + std::scoped_lock lock(s_thread_local_allocators_lock); +#else Lock lock(thread_local_allocators_lock); +#endif thread_local_allocators.push_back(alloc); } @@ -297,11 +321,7 @@ namespace embree } static const size_t threadLocalAllocOverhead = 20; //! 20 means 5% parallel allocation overhead through unfilled thread local blocks -#if defined(__AVX512ER__) // KNL - static const size_t mainAllocOverheadStatic = 15; //! 15 means 7.5% allocation overhead through unfilled main alloc blocks -#else static const size_t mainAllocOverheadStatic = 20; //! 20 means 5% allocation overhead through unfilled main alloc blocks -#endif static const size_t mainAllocOverheadDynamic = 8; //! 20 means 12.5% allocation overhead through unfilled main alloc blocks /* calculates a single threaded threshold for the builders such @@ -496,7 +516,11 @@ namespace embree /* parallel block creation in case of no freeBlocks, avoids single global mutex */ if (likely(freeBlocks.load() == nullptr)) { +#if defined(APPLE) && defined(__aarch64__) + std::scoped_lock lock(slotMutex[slot]); +#else Lock lock(slotMutex[slot]); +#endif if (myUsedBlocks == threadUsedBlocks[slot]) { const size_t alignedBytes = (bytes+(align-1)) & ~(align-1); const size_t allocSize = max(min(growSize,maxGrowSize),alignedBytes); @@ -509,7 +533,11 @@ namespace embree /* if this fails allocate new block */ { - Lock lock(mutex); +#if defined(APPLE) && defined(__aarch64__) + std::scoped_lock lock(mutex); +#else + Lock lock(mutex); +#endif if (myUsedBlocks == threadUsedBlocks[slot]) { if (freeBlocks.load() != nullptr) { @@ -531,7 +559,11 @@ namespace embree /*! add new block */ void addBlock(void* ptr, ssize_t bytes) { +#if defined(APPLE) && defined(__aarch64__) + std::scoped_lock lock(mutex); +#else Lock lock(mutex); +#endif const size_t sizeof_Header = offsetof(Block,data[0]); void* aptr = (void*) ((((size_t)ptr)+maxAlignment-1) & ~(maxAlignment-1)); size_t ofs = (size_t) aptr - (size_t) ptr; @@ -617,8 +649,8 @@ namespace embree bytesWasted(alloc->bytesWasted), stat_all(alloc,ANY_TYPE), stat_malloc(alloc,ALIGNED_MALLOC), - stat_4K(alloc,OS_MALLOC,false), - stat_2M(alloc,OS_MALLOC,true), + stat_4K(alloc,EMBREE_OS_MALLOC,false), + stat_2M(alloc,EMBREE_OS_MALLOC,true), stat_shared(alloc,SHARED) {} AllStatistics (size_t bytesUsed, @@ -711,7 +743,7 @@ namespace embree /* We avoid using os_malloc for small blocks as this could * cause a risk of fragmenting the virtual address space and * reach the limit of vm.max_map_count = 65k under Linux. */ - if (atype == OS_MALLOC && bytesAllocate < maxAllocationSize) + if (atype == EMBREE_OS_MALLOC && bytesAllocate < maxAllocationSize) atype = ALIGNED_MALLOC; /* we need to additionally allocate some header */ @@ -720,7 +752,7 @@ namespace embree bytesReserve = sizeof_Header+bytesReserve; /* consume full 4k pages with using os_malloc */ - if (atype == OS_MALLOC) { + if (atype == EMBREE_OS_MALLOC) { bytesAllocate = ((bytesAllocate+PAGE_SIZE-1) & ~(PAGE_SIZE-1)); bytesReserve = ((bytesReserve +PAGE_SIZE-1) & ~(PAGE_SIZE-1)); } @@ -752,11 +784,11 @@ namespace embree return new (ptr) Block(ALIGNED_MALLOC,bytesAllocate-sizeof_Header,bytesAllocate-sizeof_Header,next,alignment); } } - else if (atype == OS_MALLOC) + else if (atype == EMBREE_OS_MALLOC) { if (device) device->memoryMonitor(bytesAllocate,false); bool huge_pages; ptr = os_malloc(bytesReserve,huge_pages); - return new (ptr) Block(OS_MALLOC,bytesAllocate-sizeof_Header,bytesReserve-sizeof_Header,next,0,huge_pages); + return new (ptr) Block(EMBREE_OS_MALLOC,bytesAllocate-sizeof_Header,bytesReserve-sizeof_Header,next,0,huge_pages); } else assert(false); @@ -800,7 +832,7 @@ namespace embree if (device) device->memoryMonitor(-sizeof_Alloced,true); } - else if (atype == OS_MALLOC) { + else if (atype == EMBREE_OS_MALLOC) { size_t sizeof_This = sizeof_Header+reserveEnd; os_free(this,sizeof_This,huge_pages); if (device) device->memoryMonitor(-sizeof_Alloced,true); @@ -861,7 +893,7 @@ namespace embree bool hasType(AllocationType atype_i, bool huge_pages_i) const { if (atype_i == ANY_TYPE ) return true; - else if (atype == OS_MALLOC) return atype_i == atype && huge_pages_i == huge_pages; + else if (atype == EMBREE_OS_MALLOC) return atype_i == atype && huge_pages_i == huge_pages; else return atype_i == atype; } @@ -910,7 +942,7 @@ namespace embree void print_block() const { if (atype == ALIGNED_MALLOC) std::cout << "A"; - else if (atype == OS_MALLOC) std::cout << "O"; + else if (atype == EMBREE_OS_MALLOC) std::cout << "O"; else if (atype == SHARED) std::cout << "S"; if (huge_pages) std::cout << "H"; size_t bytesUsed = getBlockUsedBytes(); @@ -940,7 +972,11 @@ namespace embree std::atomic freeBlocks; std::atomic threadBlocks[MAX_THREAD_USED_BLOCK_SLOTS]; +#if defined(APPLE) && defined(__aarch64__) + std::mutex slotMutex[MAX_THREAD_USED_BLOCK_SLOTS]; +#else SpinLock slotMutex[MAX_THREAD_USED_BLOCK_SLOTS]; +#endif bool use_single_mode; size_t defaultBlockSize; @@ -954,7 +990,11 @@ namespace embree static __thread ThreadLocal2* thread_local_allocator2; static SpinLock s_thread_local_allocators_lock; static std::vector> s_thread_local_allocators; +#if defined(APPLE) && defined(__aarch64__) + std::mutex thread_local_allocators_lock; +#else SpinLock thread_local_allocators_lock; +#endif std::vector thread_local_allocators; AllocationType atype; mvector primrefarray; //!< primrefarray used to allocate nodes diff --git a/kernels/common/buffer.h b/kernels/common/buffer.h index 02d319c59d..793012c04d 100644 --- a/kernels/common/buffer.h +++ b/kernels/common/buffer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/builder.h b/kernels/common/builder.h index d2a1cfe3ce..07fe7b069b 100644 --- a/kernels/common/builder.h +++ b/kernels/common/builder.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/context.h b/kernels/common/context.h index d0185a74f2..ccd88bdeac 100644 --- a/kernels/common/context.h +++ b/kernels/common/context.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/default.h b/kernels/common/default.h index 3db53413bc..f15d61b768 100644 --- a/kernels/common/default.h +++ b/kernels/common/default.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/device.cpp b/kernels/common/device.cpp index ca4c3b38fc..194d06504f 100644 --- a/kernels/common/device.cpp +++ b/kernels/common/device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "device.h" @@ -38,18 +38,53 @@ namespace embree Device::Device (const char* cfg) { - /* check CPU */ - if (!hasISA(ISA)) + /* check that CPU supports lowest ISA */ + if (!hasISA(ISA)) { throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support " ISA_STR); + } + + /* set default frequency level for detected CPU */ + switch (getCPUModel()) { + case CPU::UNKNOWN: frequency_level = FREQUENCY_SIMD256; break; + case CPU::XEON_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break; + case CPU::CORE_ICE_LAKE: frequency_level = FREQUENCY_SIMD256; break; + case CPU::CORE_TIGER_LAKE: frequency_level = FREQUENCY_SIMD128; break; + case CPU::CORE_COMET_LAKE: frequency_level = FREQUENCY_SIMD128; break; + case CPU::CORE_CANNON_LAKE:frequency_level = FREQUENCY_SIMD128; break; + case CPU::CORE_KABY_LAKE: frequency_level = FREQUENCY_SIMD128; break; + case CPU::XEON_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break; + case CPU::CORE_SKY_LAKE: frequency_level = FREQUENCY_SIMD128; break; + case CPU::XEON_BROADWELL: frequency_level = FREQUENCY_SIMD256; break; + case CPU::CORE_BROADWELL: frequency_level = FREQUENCY_SIMD256; break; + case CPU::XEON_HASWELL: frequency_level = FREQUENCY_SIMD256; break; + case CPU::CORE_HASWELL: frequency_level = FREQUENCY_SIMD256; break; + case CPU::XEON_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break; + case CPU::CORE_IVY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break; + case CPU::SANDY_BRIDGE: frequency_level = FREQUENCY_SIMD256; break; + case CPU::NEHALEM: frequency_level = FREQUENCY_SIMD128; break; + case CPU::CORE2: frequency_level = FREQUENCY_SIMD128; break; + case CPU::CORE1: frequency_level = FREQUENCY_SIMD128; break; + case CPU::XEON_PHI_KNIGHTS_MILL : frequency_level = FREQUENCY_SIMD512; break; + case CPU::XEON_PHI_KNIGHTS_LANDING: frequency_level = FREQUENCY_SIMD512; break; +#if defined(__APPLE__) + case CPU::ARM: frequency_level = FREQUENCY_SIMD256; break; // Apple M1 supports high throughput for SIMD4 +#else + case CPU::ARM: frequency_level = FREQUENCY_SIMD128; break; +#endif + } /* initialize global state */ +#if defined(EMBREE_CONFIG) + State::parseString(EMBREE_CONFIG); +#endif State::parseString(cfg); - if (!ignore_config_files && FileName::executableFolder() != FileName("")) - State::parseFile(FileName::executableFolder()+FileName(".embree" TOSTRING(RTC_VERSION_MAJOR))); - if (!ignore_config_files && FileName::homeFolder() != FileName("")) - State::parseFile(FileName::homeFolder()+FileName(".embree" TOSTRING(RTC_VERSION_MAJOR))); State::verify(); + /* check whether selected ISA is supported by the HW, as the user could have forced an unsupported ISA */ + if (!checkISASupport()) { + throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"CPU does not support selected ISA"); + } + /*! do some internal tests */ assert(isa::Cylinder::verify()); @@ -74,8 +109,9 @@ namespace embree //exceptions &= ~_MM_MASK_UNDERFLOW; //exceptions &= ~_MM_MASK_INEXACT; _MM_SET_EXCEPTION_MASK(exceptions); + (void) exceptions; } - + /* print info header */ if (State::verbosity(1)) print(); @@ -95,7 +131,7 @@ namespace embree /* ray stream SOA to AOS conversion */ #if defined(EMBREE_RAY_PACKETS) RayStreamFilterFuncsType rayStreamFilterFuncs; - SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(enabled_cpu_features,rayStreamFilterFuncs); + SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(enabled_cpu_features,rayStreamFilterFuncs); rayStreamFilters = rayStreamFilterFuncs(); #endif } @@ -121,11 +157,8 @@ namespace embree #if defined(EMBREE_TARGET_AVX2) v += "AVX2 "; #endif -#if defined(EMBREE_TARGET_AVX512KNL) - v += "AVX512KNL "; -#endif -#if defined(EMBREE_TARGET_AVX512SKX) - v += "AVX512SKX "; +#if defined(EMBREE_TARGET_AVX512) + v += "AVX512 "; #endif return v; } @@ -139,6 +172,9 @@ namespace embree #if defined (EMBREE_BACKFACE_CULLING) v += "backfaceculling "; #endif +#if defined (EMBREE_BACKFACE_CULLING_CURVES) + v += "backfacecullingcurves "; +#endif #if defined(EMBREE_FILTER_FUNCTION) v += "intersection_filter "; #endif @@ -177,7 +213,11 @@ namespace embree std::cout << " Tasking : "; #if defined(TASKING_TBB) std::cout << "TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR << " "; + #if TBB_INTERFACE_VERSION >= 12002 + std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << TBB_runtime_interface_version() << " "; + #else std::cout << "TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version() << " "; + #endif #endif #if defined(TASKING_INTERNAL) std::cout << "internal_tasking_system "; @@ -406,7 +446,7 @@ namespace embree #endif #if defined(EMBREE_TARGET_SIMD16) && defined(EMBREE_RAY_PACKETS) - case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return hasISA(AVX512KNL) | hasISA(AVX512SKX); + case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return hasISA(AVX512); #else case RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: return 0; #endif @@ -429,6 +469,12 @@ namespace embree case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: return 0; #endif +#if defined(EMBREE_BACKFACE_CULLING_CURVES) + case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 1; +#else + case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0; +#endif + #if defined(EMBREE_COMPACT_POLYS) case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1; #else diff --git a/kernels/common/device.h b/kernels/common/device.h index e9a81bb109..21c42c654d 100644 --- a/kernels/common/device.h +++ b/kernels/common/device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/geometry.cpp b/kernels/common/geometry.cpp index b3aa8e3396..d8d3f65a5c 100644 --- a/kernels/common/geometry.cpp +++ b/kernels/common/geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry.h" diff --git a/kernels/common/geometry.h b/kernels/common/geometry.h index 2d77efd75a..593990f5b1 100644 --- a/kernels/common/geometry.h +++ b/kernels/common/geometry.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -91,7 +91,7 @@ namespace embree size_t numFilterFunctions; //!< number of geometries with filter functions enabled size_t numTriangles; //!< number of enabled triangles - size_t numMBTriangles; //!< number of enabled motion blured triangles + size_t numMBTriangles; //!< number of enabled motion blurred triangles size_t numQuads; //!< number of enabled quads size_t numMBQuads; //!< number of enabled motion blurred quads size_t numBezierCurves; //!< number of enabled curves @@ -99,7 +99,7 @@ namespace embree size_t numLineSegments; //!< number of enabled line segments size_t numMBLineSegments; //!< number of enabled line motion blurred segments size_t numSubdivPatches; //!< number of enabled subdivision patches - size_t numMBSubdivPatches; //!< number of enabled motion blured subdivision patches + size_t numMBSubdivPatches; //!< number of enabled motion blurred subdivision patches size_t numUserGeometries; //!< number of enabled user geometries size_t numMBUserGeometries; //!< number of enabled motion blurred user geometries size_t numInstancesCheap; //!< number of enabled cheap instances @@ -124,6 +124,7 @@ namespace embree GTY_FLAT_LINEAR_CURVE = 0, GTY_ROUND_LINEAR_CURVE = 1, GTY_ORIENTED_LINEAR_CURVE = 2, + GTY_CONE_LINEAR_CURVE = 3, GTY_FLAT_BEZIER_CURVE = 4, GTY_ROUND_BEZIER_CURVE = 5, @@ -179,6 +180,7 @@ namespace embree { MTY_FLAT_LINEAR_CURVE = 1ul << GTY_FLAT_LINEAR_CURVE, MTY_ROUND_LINEAR_CURVE = 1ul << GTY_ROUND_LINEAR_CURVE, + MTY_CONE_LINEAR_CURVE = 1ul << GTY_CONE_LINEAR_CURVE, MTY_ORIENTED_LINEAR_CURVE = 1ul << GTY_ORIENTED_LINEAR_CURVE, MTY_FLAT_BEZIER_CURVE = 1ul << GTY_FLAT_BEZIER_CURVE, @@ -197,7 +199,7 @@ namespace embree MTY_ROUND_CATMULL_ROM_CURVE = 1ul << GTY_ROUND_CATMULL_ROM_CURVE, MTY_ORIENTED_CATMULL_ROM_CURVE = 1ul << GTY_ORIENTED_CATMULL_ROM_CURVE, - MTY_CURVE2 = MTY_FLAT_LINEAR_CURVE | MTY_ROUND_LINEAR_CURVE | MTY_ORIENTED_LINEAR_CURVE, + MTY_CURVE2 = MTY_FLAT_LINEAR_CURVE | MTY_ROUND_LINEAR_CURVE | MTY_CONE_LINEAR_CURVE | MTY_ORIENTED_LINEAR_CURVE, MTY_CURVE4 = MTY_FLAT_BEZIER_CURVE | MTY_ROUND_BEZIER_CURVE | MTY_ORIENTED_BEZIER_CURVE | MTY_FLAT_BSPLINE_CURVE | MTY_ROUND_BSPLINE_CURVE | MTY_ORIENTED_BSPLINE_CURVE | @@ -299,7 +301,7 @@ namespace embree template __forceinline vint timeSegment(const vfloat& time, vfloat& ftime) const { - return getTimeSegment(time,vfloat(time_range.lower),vfloat(time_range.upper),vfloat(fnumTimeSegments),ftime); + return getTimeSegment(time,vfloat(time_range.lower),vfloat(time_range.upper),vfloat(fnumTimeSegments),ftime); } /* calculate overlapping time segment range */ diff --git a/kernels/common/hit.h b/kernels/common/hit.h index 32a198cdfe..fd1a9d6391 100644 --- a/kernels/common/hit.h +++ b/kernels/common/hit.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -22,7 +22,7 @@ namespace embree { for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) instID[l] = RTC_INVALID_GEOMETRY_ID; - instance_id_stack::copy(context->instID, instID); + instance_id_stack::copy_UV(context->instID, instID); } /* Returns the size of the hit */ @@ -48,7 +48,7 @@ namespace embree __forceinline HitK(const RTCIntersectContext* context, unsigned int geomID, unsigned int primID, float u, float v, const Vec3fa& Ng) : Ng(Ng.x,Ng.y,Ng.z), u(u), v(v), primID(primID), geomID(geomID) { - instance_id_stack::copy(context->instID, instID); + instance_id_stack::copy_UU(context->instID, instID); } /* Returns the size of the hit */ @@ -96,7 +96,7 @@ namespace embree ray.v = hit.v; ray.primID = hit.primID; ray.geomID = hit.geomID; - instance_id_stack::copy(hit.instID, ray.instID); + instance_id_stack::copy_UU(hit.instID, ray.instID); } template @@ -109,6 +109,6 @@ namespace embree vfloat::storeu(mask,&ray.v, hit.v); vuint::storeu(mask,&ray.primID, hit.primID); vuint::storeu(mask,&ray.geomID, hit.geomID); - instance_id_stack::copy(hit.instID, ray.instID, mask); + instance_id_stack::copy_VV(hit.instID, ray.instID, mask); } } diff --git a/kernels/common/instance_stack.h b/kernels/common/instance_stack.h index d7e3637f7b..d3c0a643f1 100644 --- a/kernels/common/instance_stack.h +++ b/kernels/common/instance_stack.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -56,144 +56,124 @@ RTC_FORCEINLINE void pop(RTCIntersectContext* context) #endif } -/******************************************************************************* +/* * Optimized instance id stack copy. - * The copy() function at the bottom of this block will either copy full + * The copy() functions will either copy full * stacks or copy only until the last valid element has been copied, depending * on RTC_MAX_INSTANCE_LEVEL_COUNT. - ******************************************************************************/ - -/* - * Plain array assignment. This works for scalar->scalar, - * scalar->vector, and vector->vector. */ -template -RTC_FORCEINLINE void level_copy(unsigned level, Src* src, Tgt* tgt) +RTC_FORCEINLINE void copy_UU(const unsigned* src, unsigned* tgt) { - tgt[level] = src[level]; +#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) + tgt[0] = src[0]; + +#else + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + tgt[l] = src[l]; + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) + if (src[l] == RTC_INVALID_GEOMETRY_ID) + break; + } +#endif } -/* - * Masked SIMD vector->vector store. - */ template -RTC_FORCEINLINE void level_copy(unsigned level, const vuint* src, vuint* tgt, const vbool& mask) +RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint* tgt) { - vuint::storeu(mask, tgt + level, src[level]); -} +#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) + tgt[0] = src[0]; -/* - * Masked scalar->SIMD vector store. - */ -template -RTC_FORCEINLINE void level_copy(unsigned level, const unsigned* src, vuint* tgt, const vbool& mask) -{ - vuint::store(mask, tgt + level, src[level]); +#else + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + tgt[l] = src[l]; + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) + if (src[l] == RTC_INVALID_GEOMETRY_ID) + break; + } +#endif } -/* - * Indexed assign from vector to scalar. - */ template -RTC_FORCEINLINE void level_copy(unsigned level, const vuint* src, unsigned* tgt, const size_t& idx) +RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint* tgt, size_t j) { - tgt[level] = src[level][idx]; -} +#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) + tgt[0][j] = src[0]; -/* - * Indexed assign from scalar to vector. - */ -template -RTC_FORCEINLINE void level_copy(unsigned level, const unsigned* src, vuint* tgt, const size_t& idx) -{ - tgt[level][idx] = src[level]; +#else + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + tgt[l][j] = src[l]; + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) + if (src[l] == RTC_INVALID_GEOMETRY_ID) + break; + } +#endif } -/* - * Indexed assign from vector to vector. - */ template -RTC_FORCEINLINE void level_copy(unsigned level, const vuint* src, vuint* tgt, const size_t& i, const size_t& j) +RTC_FORCEINLINE void copy_UV(const unsigned* src, vuint* tgt, const vbool& mask) { - tgt[level][j] = src[level][i]; -} +#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) + vuint::store(mask, tgt, src[0]); -/* - * Check if the given stack level is valid. - * These are only used for large max stack sizes. - */ -RTC_FORCEINLINE bool level_valid(unsigned level, const unsigned* stack) -{ - return stack[level] != RTC_INVALID_GEOMETRY_ID; -} -RTC_FORCEINLINE bool level_valid(unsigned level, const unsigned* stack, const size_t& /*i*/) -{ - return stack[level] != RTC_INVALID_GEOMETRY_ID; -} -template -RTC_FORCEINLINE bool level_valid(unsigned level, const unsigned* stack, const vbool& /*mask*/) -{ - return stack[level] != RTC_INVALID_GEOMETRY_ID; +#else + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + vuint::store(mask, tgt + l, src[l]); + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) + if (src[l] == RTC_INVALID_GEOMETRY_ID) + break; + } +#endif } template -RTC_FORCEINLINE bool level_valid(unsigned level, const vuint* stack) +RTC_FORCEINLINE void copy_VU(const vuint* src, unsigned* tgt, size_t i) { - return any(stack[level] != RTC_INVALID_GEOMETRY_ID); -} -template -RTC_FORCEINLINE bool level_valid(unsigned level, const vuint* stack, const vbool& mask) -{ - return any(mask & (stack[level] != RTC_INVALID_GEOMETRY_ID)); -} +#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) + tgt[0] = src[0][i]; -template -RTC_FORCEINLINE bool level_valid(unsigned level, const vuint* stack, const size_t& i) -{ - return stack[level][i] != RTC_INVALID_GEOMETRY_ID; +#else + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + tgt[l] = src[l][i]; + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) + if (src[l][i] == RTC_INVALID_GEOMETRY_ID) + break; + } +#endif } + template -RTC_FORCEINLINE bool level_valid(unsigned level, const vuint* stack, const size_t& i, const size_t& /*j*/) +RTC_FORCEINLINE void copy_VV(const vuint* src, vuint* tgt, size_t i, size_t j) { - return stack[level][i] != RTC_INVALID_GEOMETRY_ID; +#if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) + tgt[0][j] = src[0][i]; + +#else + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + tgt[l][j] = src[l][i]; + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) + if (src[l][i] == RTC_INVALID_GEOMETRY_ID) + break; + } +#endif } -/* - * Copy an instance ID stack. - * - * This function automatically selects a LevelFunctor from the above Assign - * structs. - */ -template -RTC_FORCEINLINE void copy(Src src, Tgt tgt, Args&&... args) +template +RTC_FORCEINLINE void copy_VV(const vuint* src, vuint* tgt, const vbool& mask) { #if (RTC_MAX_INSTANCE_LEVEL_COUNT == 1) - /* - * Avoid all loops for only one level. - */ - level_copy(0, src, tgt, std::forward(args)...); - -#elif (RTC_MAX_INSTANCE_LEVEL_COUNT <= 4) - /* - * It is faster to avoid the valid test for low level counts. - * Just copy the whole stack. - */ - for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) - level_copy(l, src, tgt, std::forward(args)...); + vuint::store(mask, tgt, src[0]); #else - /* - * For general stack sizes, it pays off to test for validity. - */ - bool valid = true; - for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT && valid; ++l) - { - level_copy(l, src, tgt, std::forward(args)...); - valid = level_valid(l, src, std::forward(args)...); + vbool done = !mask; + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) { + vuint::store(mask, tgt + l, src[l]); + if (RTC_MAX_INSTANCE_LEVEL_COUNT > 4) { + done |= src[l] == RTC_INVALID_GEOMETRY_ID; + if (all(done)) break; + } } #endif } } // namespace instance_id_stack } // namespace embree - diff --git a/kernels/common/isa.h b/kernels/common/isa.h index 9fd1ea58b7..9e1132e1a0 100644 --- a/kernels/common/isa.h +++ b/kernels/common/isa.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -13,23 +13,21 @@ namespace embree name##Func name; #define DECLARE_SYMBOL2(type,name) \ - namespace sse2 { extern type name(); } \ - namespace sse42 { extern type name(); } \ - namespace avx { extern type name(); } \ - namespace avx2 { extern type name(); } \ - namespace avx512knl { extern type name(); } \ - namespace avx512skx { extern type name(); } \ + namespace sse2 { extern type name(); } \ + namespace sse42 { extern type name(); } \ + namespace avx { extern type name(); } \ + namespace avx2 { extern type name(); } \ + namespace avx512 { extern type name(); } \ void name##_error2() { throw_RTCError(RTC_ERROR_UNKNOWN,"internal error in ISA selection for " TOSTRING(name)); } \ type name##_error() { return type(name##_error2); } \ type name##_zero() { return type(nullptr); } #define DECLARE_ISA_FUNCTION(type,symbol,args) \ - namespace sse2 { extern type symbol(args); } \ - namespace sse42 { extern type symbol(args); } \ - namespace avx { extern type symbol(args); } \ - namespace avx2 { extern type symbol(args); } \ - namespace avx512knl { extern type symbol(args); } \ - namespace avx512skx { extern type symbol(args); } \ + namespace sse2 { extern type symbol(args); } \ + namespace sse42 { extern type symbol(args); } \ + namespace avx { extern type symbol(args); } \ + namespace avx2 { extern type symbol(args); } \ + namespace avx512 { extern type symbol(args); } \ inline type symbol##_error(args) { throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"function " TOSTRING(symbol) " not supported by your CPU"); } \ typedef type (*symbol##Ty)(args); \ @@ -46,7 +44,7 @@ namespace embree #define SELECT_SYMBOL_DEFAULT(features,intersector) \ intersector = isa::intersector; -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) #if !defined(EMBREE_TARGET_SIMD4) #define EMBREE_TARGET_SIMD4 #endif @@ -84,24 +82,14 @@ namespace embree #define SELECT_SYMBOL_AVX2(features,intersector) #endif -#if defined(EMBREE_TARGET_AVX512KNL) +#if defined(EMBREE_TARGET_AVX512) #if !defined(EMBREE_TARGET_SIMD16) #define EMBREE_TARGET_SIMD16 #endif -#define SELECT_SYMBOL_AVX512KNL(features,intersector) \ - if ((features & AVX512KNL) == AVX512KNL) intersector = avx512knl::intersector; +#define SELECT_SYMBOL_AVX512(features,intersector) \ + if ((features & AVX512) == AVX512) intersector = avx512::intersector; #else -#define SELECT_SYMBOL_AVX512KNL(features,intersector) -#endif - -#if defined(EMBREE_TARGET_AVX512SKX) -#if !defined(EMBREE_TARGET_SIMD16) -#define EMBREE_TARGET_SIMD16 -#endif -#define SELECT_SYMBOL_AVX512SKX(features,intersector) \ - if ((features & AVX512SKX) == AVX512SKX) intersector = avx512skx::intersector; -#else -#define SELECT_SYMBOL_AVX512SKX(features,intersector) +#define SELECT_SYMBOL_AVX512(features,intersector) #endif #define SELECT_SYMBOL_DEFAULT_SSE42(features,intersector) \ @@ -119,39 +107,37 @@ namespace embree SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); -#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_SSE42(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_SSE42(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_SSE42(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); #define SELECT_SYMBOL_DEFAULT_AVX(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ @@ -162,21 +148,19 @@ namespace embree SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); -#define SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_AVX(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ - SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); - -#define SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL_AVX512SKX(features,intersector) \ + SELECT_SYMBOL_AVX(features,intersector); + +#define SELECT_SYMBOL_DEFAULT_AVX_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_DEFAULT_AVX_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_AVX_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); #define SELECT_SYMBOL_INIT_AVX(features,intersector) \ INIT_SYMBOL(features,intersector); \ @@ -187,11 +171,11 @@ namespace embree SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); -#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,intersector) \ INIT_SYMBOL(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); #define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2(features,intersector) \ INIT_SYMBOL(features,intersector); \ @@ -199,57 +183,49 @@ namespace embree SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); -#define SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,intersector) \ +#define SELECT_SYMBOL_INIT_AVX(features,intersector) \ INIT_SYMBOL(features,intersector); \ - SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); + SELECT_SYMBOL_AVX(features,intersector); -#define SELECT_SYMBOL_INIT_AVX_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_INIT_AVX_AVX512(features,intersector) \ INIT_SYMBOL(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL(features,intersector) \ +#define SELECT_SYMBOL_INIT_AVX_AVX2(features,intersector) \ INIT_SYMBOL(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ - SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); + SELECT_SYMBOL_AVX2(features,intersector); -#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512(features,intersector) \ INIT_SYMBOL(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2_AVX512(features,intersector) \ INIT_SYMBOL(features,intersector); \ SELECT_SYMBOL_SSE42(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_ZERO_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_ZERO_SSE42_AVX_AVX2_AVX512(features,intersector) \ ZERO_SYMBOL(features,intersector); \ SELECT_SYMBOL_SSE42(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(features,intersector) \ SELECT_SYMBOL_DEFAULT(features,intersector); \ SELECT_SYMBOL_AVX(features,intersector); \ SELECT_SYMBOL_AVX2(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); -#define SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,intersector) \ +#define SELECT_SYMBOL_INIT_AVX512(features,intersector) \ INIT_SYMBOL(features,intersector); \ - SELECT_SYMBOL_AVX512KNL(features,intersector); \ - SELECT_SYMBOL_AVX512SKX(features,intersector); + SELECT_SYMBOL_AVX512(features,intersector); #define SELECT_SYMBOL_SSE42_AVX_AVX2(features,intersector) \ SELECT_SYMBOL_SSE42(features,intersector); \ @@ -262,10 +238,9 @@ namespace embree else return getISA(depth-1); } }; - namespace sse2 { int getISA(); }; - namespace sse42 { int getISA(); }; - namespace avx { int getISA(); }; - namespace avx2 { int getISA(); }; - namespace avx512knl { int getISA(); }; - namespace avx512skx { int getISA(); }; + namespace sse2 { int getISA(); }; + namespace sse42 { int getISA(); }; + namespace avx { int getISA(); }; + namespace avx2 { int getISA(); }; + namespace avx512 { int getISA(); }; } diff --git a/kernels/common/motion_derivative.cpp b/kernels/common/motion_derivative.cpp index 0e0d73a9f2..b9f9dd04bf 100644 --- a/kernels/common/motion_derivative.cpp +++ b/kernels/common/motion_derivative.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "motion_derivative.h" diff --git a/kernels/common/motion_derivative.h b/kernels/common/motion_derivative.h index 82953f0e89..c619d6a675 100644 --- a/kernels/common/motion_derivative.h +++ b/kernels/common/motion_derivative.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/point_query.h b/kernels/common/point_query.h index 27d158ca3a..7d55c91fff 100644 --- a/kernels/common/point_query.h +++ b/kernels/common/point_query.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/primref.h b/kernels/common/primref.h index 3d4f9c0d44..d61763487b 100644 --- a/kernels/common/primref.h +++ b/kernels/common/primref.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -29,7 +29,7 @@ namespace embree __forceinline PrimRef (const BBox3fa& bounds, size_t id) { -#if defined(__X86_64__) +#if defined(__64BIT__) lower = Vec3fx(bounds.lower, (unsigned)(id & 0xFFFFFFFF)); upper = Vec3fx(bounds.upper, (unsigned)((id >> 32) & 0xFFFFFFFF)); #else @@ -79,7 +79,7 @@ namespace embree /*! returns an size_t sized ID */ __forceinline size_t ID() const { -#if defined(__X86_64__) +#if defined(__64BIT__) return size_t(lower.u) + (size_t(upper.u) << 32); #else return size_t(lower.u); diff --git a/kernels/common/primref_mb.h b/kernels/common/primref_mb.h index 2e0e664c46..fb08a05003 100644 --- a/kernels/common/primref_mb.h +++ b/kernels/common/primref_mb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -32,7 +32,7 @@ namespace embree : lbounds((LBBox3fx)lbounds_i), time_range(time_range) { assert(activeTimeSegments > 0); -#if defined(__X86_64__) +#if defined(__64BIT__) lbounds.bounds0.lower.a = id & 0xFFFFFFFF; lbounds.bounds0.upper.a = (id >> 32) & 0xFFFFFFFF; #else @@ -47,7 +47,7 @@ namespace embree : lbounds((LBBox3fx)lbounds_i), time_range(time_range) { assert(activeTimeSegments > 0); -#if defined(__X86_64__) +#if defined(__64BIT__) lbounds.bounds0.lower.u = id & 0xFFFFFFFF; lbounds.bounds0.upper.u = (id >> 32) & 0xFFFFFFFF; #else @@ -115,7 +115,7 @@ namespace embree /*! returns an size_t sized ID */ __forceinline size_t ID() const { -#if defined(__X86_64__) +#if defined(__64BIT__) return size_t(lbounds.bounds0.lower.u) + (size_t(lbounds.bounds0.upper.u) << 32); #else return size_t(lbounds.bounds0.lower.u); @@ -134,7 +134,7 @@ namespace embree /*! Outputs primitive reference to a stream. */ friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) { - return cout << "{ bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }"; + return cout << "{ time_range = " << ref.time_range << ", bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }"; } public: @@ -163,7 +163,7 @@ namespace embree : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range) { assert(activeTimeSegments > 0); -#if defined(__X86_64__) +#if defined(__64BIT__) bbox.lower.u = id & 0xFFFFFFFF; bbox.upper.u = (id >> 32) & 0xFFFFFFFF; #else @@ -229,7 +229,7 @@ namespace embree /*! returns an size_t sized ID */ __forceinline size_t ID() const { -#if defined(__X86_64__) +#if defined(__64BIT__) return size_t(bbox.lower.u) + (size_t(bbox.upper.u) << 32); #else return size_t(bbox.lower.u); diff --git a/kernels/common/profile.h b/kernels/common/profile.h index a7de36414d..5ef7f6ec0f 100644 --- a/kernels/common/profile.h +++ b/kernels/common/profile.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/ray.h b/kernels/common/ray.h index 336d48942c..4e0b77d98a 100644 --- a/kernels/common/ray.h +++ b/kernels/common/ray.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,7 +6,7 @@ #include "default.h" #include "instance_stack.h" -// FIXME: if ray gets seperated into ray* and hit, uload4 needs to be adjusted +// FIXME: if ray gets separated into ray* and hit, uload4 needs to be adjusted namespace embree { @@ -131,7 +131,7 @@ namespace embree __forceinline void verifyHit(const vbool& valid0) const { vbool valid = valid0 & geomID != vuint(RTC_INVALID_GEOMETRY_ID); - const vbool vt = (abs(tfar) <= vfloat(FLT_LARGE)) | (tfar == vfloat(neg_inf)); + const vbool vt = (abs(tfar) < vfloat(inf)) | (tfar == vfloat(neg_inf)); const vbool vu = (abs(u) <= vfloat(FLT_LARGE)); const vbool vv = (abs(u) <= vfloat(FLT_LARGE)); const vbool vnx = abs(Ng.x) <= vfloat(FLT_LARGE); @@ -230,7 +230,7 @@ namespace embree __forceinline void verifyHit() const { if (geomID == RTC_INVALID_GEOMETRY_ID) return; - const bool vt = (abs(tfar) <= FLT_LARGE) || (tfar == float(neg_inf)); + const bool vt = (abs(tfar) < float(inf)) || (tfar == float(neg_inf)); const bool vu = (abs(u) <= FLT_LARGE); const bool vv = (abs(u) <= FLT_LARGE); const bool vnx = abs(Ng.x) <= FLT_LARGE; @@ -292,7 +292,7 @@ namespace embree ray.u = u[i]; ray.v = v[i]; ray.primID = primID[i]; ray.geomID = geomID[i]; - instance_id_stack::copy(instID, ray.instID, i); + instance_id_stack::copy_VU(instID, ray.instID, i); } /* Converts single rays to ray packet */ @@ -331,7 +331,7 @@ namespace embree u[i] = ray.u; v[i] = ray.v; primID[i] = ray.primID; geomID[i] = ray.geomID; - instance_id_stack::copy(ray.instID, instID, i); + instance_id_stack::copy_UV(ray.instID, instID, i); } /* copies a ray packet element into another element*/ @@ -353,7 +353,7 @@ namespace embree u[dest] = u[source]; v[dest] = v[source]; primID[dest] = primID[source]; geomID[dest] = geomID[source]; - instance_id_stack::copy(instID, instID, source, dest); + instance_id_stack::copy_VV(instID, instID, source, dest); } /* Shortcuts */ @@ -1112,7 +1112,7 @@ namespace embree __forceinline RayK getRayByOffset(const vbool& valid, const vint& offset) { const vint valid_offset = select(valid, offset, vintx(zero)); - return getRayByOffset(valid_offset); + return getRayByOffset(valid_offset); } template @@ -1153,7 +1153,7 @@ namespace embree ray_k->primID = ray.primID[k]; ray_k->geomID = ray.geomID[k]; - instance_id_stack::copy(ray.instID, ray_k->instID, k); + instance_id_stack::copy_VU(ray.instID, ray_k->instID, k); } #endif } @@ -1185,7 +1185,7 @@ namespace embree }; template<> - __forceinline Ray4 RayStreamAOS::getRayByOffset(const vint4& offset) + __forceinline Ray4 RayStreamAOS::getRayByOffset<4>(const vint4& offset) { Ray4 ray; @@ -1222,7 +1222,7 @@ namespace embree #if defined(__AVX__) template<> - __forceinline Ray8 RayStreamAOS::getRayByOffset(const vint8& offset) + __forceinline Ray8 RayStreamAOS::getRayByOffset<8>(const vint8& offset) { Ray8 ray; @@ -1260,7 +1260,7 @@ namespace embree #if defined(__AVX512F__) template<> - __forceinline Ray16 RayStreamAOS::getRayByOffset(const vint16& offset) + __forceinline Ray16 RayStreamAOS::getRayByOffset<16>(const vint16& offset) { Ray16 ray; @@ -1332,7 +1332,7 @@ namespace embree __forceinline RayK getRayByIndex(const vbool& valid, const vint& index) { const vint valid_index = select(valid, index, vintx(zero)); - return getRayByIndex(valid_index); + return getRayByIndex(valid_index); } template @@ -1357,7 +1357,7 @@ namespace embree ray_k->v = ray.v[k]; ray_k->primID = ray.primID[k]; ray_k->geomID = ray.geomID[k]; - instance_id_stack::copy(ray.instID, ray_k->instID, k); + instance_id_stack::copy_VU(ray.instID, ray_k->instID, k); } } } @@ -1385,7 +1385,7 @@ namespace embree }; template<> - __forceinline Ray4 RayStreamAOP::getRayByIndex(const vint4& index) + __forceinline Ray4 RayStreamAOP::getRayByIndex<4>(const vint4& index) { Ray4 ray; @@ -1422,7 +1422,7 @@ namespace embree #if defined(__AVX__) template<> - __forceinline Ray8 RayStreamAOP::getRayByIndex(const vint8& index) + __forceinline Ray8 RayStreamAOP::getRayByIndex<8>(const vint8& index) { Ray8 ray; @@ -1460,7 +1460,7 @@ namespace embree #if defined(__AVX512F__) template<> - __forceinline Ray16 RayStreamAOP::getRayByIndex(const vint16& index) + __forceinline Ray16 RayStreamAOP::getRayByIndex<16>(const vint16& index) { Ray16 ray; diff --git a/kernels/common/rtcore.cpp b/kernels/common/rtcore.cpp index 9f02f6855e..95a94319ec 100644 --- a/kernels/common/rtcore.cpp +++ b/kernels/common/rtcore.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define RTC_EXPORT_API @@ -7,6 +7,7 @@ #include "device.h" #include "scene.h" #include "context.h" +#include "../geometry/filter.h" #include "../../include/embree3/rtcore_ray.h" using namespace embree; @@ -479,7 +480,7 @@ RTC_NAMESPACE_BEGIN; IntersectContext context(scene,user_context); #if !defined(EMBREE_RAY_PACKETS) - Ray4* ray4 = (Ray4*) rayhit; + RayHit4* ray4 = (RayHit4*) rayhit; for (size_t i=0; i<4; i++) { if (!valid[i]) continue; RayHit ray1; ray4->get(i,ray1); @@ -510,7 +511,7 @@ RTC_NAMESPACE_BEGIN; IntersectContext context(scene,user_context); #if !defined(EMBREE_RAY_PACKETS) - Ray8* ray8 = (Ray8*) rayhit; + RayHit8* ray8 = (RayHit8*) rayhit; for (size_t i=0; i<8; i++) { if (!valid[i]) continue; RayHit ray1; ray8->get(i,ray1); @@ -543,7 +544,7 @@ RTC_NAMESPACE_BEGIN; IntersectContext context(scene,user_context); #if !defined(EMBREE_RAY_PACKETS) - Ray16* ray16 = (Ray16*) rayhit; + RayHit16* ray16 = (RayHit16*) rayhit; for (size_t i=0; i<16; i++) { if (!valid[i]) continue; RayHit ray1; ray16->get(i,ray1); @@ -1094,13 +1095,13 @@ RTC_NAMESPACE_BEGIN; RTC_API void rtcFilterIntersection(const struct RTCIntersectFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args) { IntersectFunctionNArguments* args = (IntersectFunctionNArguments*) args_i; - args->report(args,filter_args); + isa::reportIntersection1(args, filter_args); } RTC_API void rtcFilterOcclusion(const struct RTCOccludedFunctionNArguments* const args_i, const struct RTCFilterFunctionNArguments* filter_args) { OccludedFunctionNArguments* args = (OccludedFunctionNArguments*) args_i; - args->report(args,filter_args); + isa::reportOcclusion1(args,filter_args); } RTC_API RTCGeometry rtcNewGeometry (RTCDevice hdevice, RTCGeometryType type) @@ -1116,7 +1117,7 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_TRIANGLE) createTriangleMeshTy createTriangleMesh = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createTriangleMesh); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createTriangleMesh); Geometry* geom = createTriangleMesh(device); return (RTCGeometry) geom->refInc(); #else @@ -1128,7 +1129,7 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_QUAD) createQuadMeshTy createQuadMesh = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createQuadMesh); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createQuadMesh); Geometry* geom = createQuadMesh(device); return (RTCGeometry) geom->refInc(); #else @@ -1142,7 +1143,7 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_POINT) createPointsTy createPoints = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_builder_cpu_features, createPoints); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_builder_cpu_features, createPoints); Geometry *geom; switch(type) { @@ -1165,6 +1166,7 @@ RTC_NAMESPACE_BEGIN; #endif } + case RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE: case RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE: case RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE: @@ -1186,12 +1188,13 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_CURVE) createLineSegmentsTy createLineSegments = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createLineSegments); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createLineSegments); createCurvesTy createCurves = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createCurves); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createCurves); Geometry* geom; switch (type) { + case RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_CONE_LINEAR_CURVE); break; case RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_ROUND_LINEAR_CURVE); break; case RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_FLAT_LINEAR_CURVE); break; //case RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_LINEAR_CURVE : geom = createLineSegments (device,Geometry::GTY_ORIENTED_LINEAR_CURVE); break; @@ -1224,7 +1227,7 @@ RTC_NAMESPACE_BEGIN; #if defined(EMBREE_GEOMETRY_SUBDIVISION) createSubdivMeshTy createSubdivMesh = nullptr; SELECT_SYMBOL_DEFAULT_AVX(device->enabled_cpu_features,createSubdivMesh); - //SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createSubdivMesh); // FIXME: this does not work for some reason? + //SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createSubdivMesh); // FIXME: this does not work for some reason? Geometry* geom = createSubdivMesh(device); return (RTCGeometry) geom->refInc(); #else @@ -1236,7 +1239,7 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_USER) createUserGeometryTy createUserGeometry = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createUserGeometry); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createUserGeometry); Geometry* geom = createUserGeometry(device); return (RTCGeometry) geom->refInc(); #else @@ -1248,7 +1251,7 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_INSTANCE) createInstanceTy createInstance = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createInstance); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createInstance); Geometry* geom = createInstance(device); return (RTCGeometry) geom->refInc(); #else @@ -1260,7 +1263,7 @@ RTC_NAMESPACE_BEGIN; { #if defined(EMBREE_GEOMETRY_GRID) createGridMeshTy createGridMesh = nullptr; - SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(device->enabled_cpu_features,createGridMesh); + SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512(device->enabled_cpu_features,createGridMesh); Geometry* geom = createGridMesh(device); return (RTCGeometry) geom->refInc(); #else @@ -1755,4 +1758,19 @@ RTC_NAMESPACE_BEGIN; return nullptr; } + RTC_API RTCGeometry rtcGetGeometryThreadSafe (RTCScene hscene, unsigned int geomID) + { + Scene* scene = (Scene*) hscene; + RTC_CATCH_BEGIN; + RTC_TRACE(rtcGetGeometryThreadSafe); +#if defined(DEBUG) + RTC_VERIFY_HANDLE(hscene); + RTC_VERIFY_GEOMID(geomID); +#endif + Ref geom = scene->get_locked(geomID); + return (RTCGeometry) geom.ptr; + RTC_CATCH_END2(scene); + return nullptr; + } + RTC_NAMESPACE_END diff --git a/kernels/common/rtcore.h b/kernels/common/rtcore.h index 4bbff508a6..4e4b24e9c2 100644 --- a/kernels/common/rtcore.h +++ b/kernels/common/rtcore.h @@ -1,10 +1,10 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../../include/embree3/rtcore.h" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE namespace embree { diff --git a/kernels/common/rtcore_builder.cpp b/kernels/common/rtcore_builder.cpp index 6bb96bba07..29e3bdca20 100644 --- a/kernels/common/rtcore_builder.cpp +++ b/kernels/common/rtcore_builder.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define RTC_EXPORT_API @@ -371,7 +371,7 @@ RTC_NAMESPACE_BEGIN bvh->allocator.init_estimate(arguments->primitiveCount*sizeof(BBox3fa)); bvh->allocator.reset(); - /* switch between differnet builders based on quality level */ + /* switch between different builders based on quality level */ if (arguments->buildQuality == RTC_BUILD_QUALITY_LOW) return rtcBuildBVHMorton(arguments); else if (arguments->buildQuality == RTC_BUILD_QUALITY_MEDIUM) diff --git a/kernels/common/scene.cpp b/kernels/common/scene.cpp index 0a0173dd0f..0040627a0e 100644 --- a/kernels/common/scene.cpp +++ b/kernels/common/scene.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene.h" @@ -27,16 +27,6 @@ namespace embree { device->refInc(); -#if defined(TASKING_INTERNAL) - scheduler = nullptr; -#elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION - group = new tbb::isolated_task_group; -#elif defined(TASKING_TBB) - group = new tbb::task_group; -#elif defined(TASKING_PPL) - group = new concurrency::task_group; -#endif - intersectors = Accel::Intersectors(missing_rtcCommit); /* one can overwrite flags through device for debugging */ @@ -46,11 +36,8 @@ namespace embree scene_flags = (RTCSceneFlags) device->scene_flags; } - Scene::~Scene () + Scene::~Scene() noexcept { -#if defined(TASKING_TBB) || defined(TASKING_PPL) - delete group; group = nullptr; -#endif device->refDec(); } @@ -480,16 +467,27 @@ namespace embree void Scene::createInstanceAccel() { #if defined(EMBREE_GEOMETRY_INSTANCE) - //if (device->object_accel == "default") + // if (device->object_accel == "default") { #if defined (EMBREE_TARGET_SIMD8) - if (device->canUseAVX() && !isCompactAccel()) - accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC)); + if (device->canUseAVX() && !isCompactAccel()) { + if (quality_flags != RTC_BUILD_QUALITY_LOW) { + accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::STATIC)); + } else { + accels_add(device->bvh8_factory->BVH8Instance(this, false, BVHFactory::BuildVariant::DYNAMIC)); + } + } else #endif - accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC)); + { + if (quality_flags != RTC_BUILD_QUALITY_LOW) { + accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::STATIC)); + } else { + accels_add(device->bvh4_factory->BVH4Instance(this, false, BVHFactory::BuildVariant::DYNAMIC)); + } + } } - //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel); + // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel); #endif } @@ -512,16 +510,27 @@ namespace embree void Scene::createInstanceExpensiveAccel() { #if defined(EMBREE_GEOMETRY_INSTANCE) - //if (device->object_accel == "default") + // if (device->object_accel == "default") { #if defined (EMBREE_TARGET_SIMD8) - if (device->canUseAVX() && !isCompactAccel()) - accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC)); + if (device->canUseAVX() && !isCompactAccel()) { + if (quality_flags != RTC_BUILD_QUALITY_LOW) { + accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::STATIC)); + } else { + accels_add(device->bvh8_factory->BVH8Instance(this, true, BVHFactory::BuildVariant::DYNAMIC)); + } + } else #endif - accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC)); + { + if (quality_flags != RTC_BUILD_QUALITY_LOW) { + accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::STATIC)); + } else { + accels_add(device->bvh4_factory->BVH4Instance(this, true, BVHFactory::BuildVariant::DYNAMIC)); + } + } } - //else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel); + // else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown instance accel "+device->instance_accel); #endif } @@ -544,6 +553,7 @@ namespace embree void Scene::createGridAccel() { BVHFactory::IntersectVariant ivariant = isRobustAccel() ? BVHFactory::IntersectVariant::ROBUST : BVHFactory::IntersectVariant::FAST; + (void) ivariant; #if defined(EMBREE_GEOMETRY_GRID) if (device->grid_accel == "default") { @@ -620,9 +630,7 @@ namespace embree if (geometry == null) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"invalid geometry"); - if (geometry->isEnabled()) { - setModified (); - } + setModified (); accels_deleteGeometry(unsigned(geomID)); id_pool.deallocate((unsigned)geomID); geometries[geomID] = null; @@ -704,7 +712,7 @@ namespace embree accels_select(hasFilterFunction()); /* build all hierarchies of this scene */ - accels_build(); + accels_build(); /* make static geometry immutable */ if (!isDynamicAccel()) { @@ -821,12 +829,12 @@ namespace embree #if USE_TASK_ARENA if (join) { - device->arena->execute([&]{ group->wait(); }); + device->arena->execute([&]{ group.wait(); }); } else #endif { - group->wait(); + group.wait(); } pause_cpu(); @@ -853,19 +861,19 @@ namespace embree if (join) { device->arena->execute([&]{ - group->run([&]{ + group.run([&]{ tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx); }); - group->wait(); + group.wait(); }); } else #endif { - group->run([&]{ + group.run([&]{ tbb::parallel_for (size_t(0), size_t(1), size_t(1), [&] (size_t) { commit_task(); }, ctx); }); - group->wait(); + group.wait(); } /* reset MXCSR register again */ @@ -906,10 +914,10 @@ namespace embree try { - group->run([&]{ + group.run([&]{ concurrency::parallel_for(size_t(0), size_t(1), size_t(1), [&](size_t) { commit_task(); }); }); - group->wait(); + group.wait(); /* reset MXCSR register again */ _mm_setcsr(mxcsr); diff --git a/kernels/common/scene.h b/kernels/common/scene.h index a40731ee3f..5ed80a63f6 100644 --- a/kernels/common/scene.h +++ b/kernels/common/scene.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -26,7 +26,7 @@ namespace embree /*! Base class all scenes are derived from */ class Scene : public AccelN { - ALIGNED_CLASS_(16); + ALIGNED_CLASS_(std::alignment_of::value); public: template @@ -137,7 +137,7 @@ namespace embree Scene (Device* device); /*! Scene destruction */ - ~Scene (); + ~Scene () noexcept; private: /*! class is non-copyable */ @@ -201,7 +201,6 @@ namespace embree { Ref& g = geometries[geomID]; if (!g) return false; - if (!g->isEnabled()) return false; return g->getModCounter() > geometryModCounters_[geomID]; } @@ -303,11 +302,11 @@ namespace embree MutexSys schedulerMutex; Ref scheduler; #elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION - tbb::isolated_task_group* group; + tbb::isolated_task_group group; #elif defined(TASKING_TBB) - tbb::task_group* group; + tbb::task_group group; #elif defined(TASKING_PPL) - concurrency::task_group* group; + concurrency::task_group group; #endif public: diff --git a/kernels/common/scene_curves.cpp b/kernels/common/scene_curves.cpp index 8cfc223c64..7355d843f3 100644 --- a/kernels/common/scene_curves.cpp +++ b/kernels/common/scene_curves.cpp @@ -1,15 +1,9 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_curves.h" #include "scene.h" -#include "../subdiv/bezier_curve.h" -#include "../subdiv/hermite_curve.h" -#include "../subdiv/bspline_curve.h" -#include "../subdiv/catmullrom_curve.h" -#include "../subdiv/linear_bezier_patch.h" - namespace embree { #if defined(EMBREE_LOWEST_ISA) @@ -380,339 +374,11 @@ namespace embree namespace isa { - BBox3fa enlarge_bounds(const BBox3fa& bounds) + __forceinline BBox3fa enlarge_bounds(const BBox3fa& bounds) { const float size = reduce_max(max(abs(bounds.lower),abs(bounds.upper))); return enlarge(bounds,Vec3fa(4.0f*float(ulp)*size)); - } - - template class Curve> - struct CurveGeometryInterface : public CurveGeometry - { - typedef Curve Curve3ff; - typedef Curve Curve3fa; - typedef Curve Curve4vf; - - CurveGeometryInterface (Device* device, Geometry::GType gtype) - : CurveGeometry(device,gtype) {} - - __forceinline const Curve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const - { - const unsigned int index = curve(i); - Vec3ff v0 = vertex(index+0,itime); - Vec3ff v1 = vertex(index+1,itime); - Vec3ff v2 = vertex(index+2,itime); - Vec3ff v3 = vertex(index+3,itime); - v0.w *= maxRadiusScale; - v1.w *= maxRadiusScale; - v2.w *= maxRadiusScale; - v3.w *= maxRadiusScale; - return Curve3ff (v0,v1,v2,v3); - } - - __forceinline const Curve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const - { - const unsigned int index = curve(i); - const Vec3ff v0 = vertex(index+0,itime); - const Vec3ff v1 = vertex(index+1,itime); - const Vec3ff v2 = vertex(index+2,itime); - const Vec3ff v3 = vertex(index+3,itime); - const Vec3ff w0(xfmPoint(space,(Vec3fa)v0), maxRadiusScale*v0.w); - const Vec3ff w1(xfmPoint(space,(Vec3fa)v1), maxRadiusScale*v1.w); - const Vec3ff w2(xfmPoint(space,(Vec3fa)v2), maxRadiusScale*v2.w); - const Vec3ff w3(xfmPoint(space,(Vec3fa)v3), maxRadiusScale*v3.w); - return Curve3ff(w0,w1,w2,w3); - } - - __forceinline const Curve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const - { - const float r_scale = r_scale0*scale; - const unsigned int index = curve(i); - const Vec3ff v0 = vertex(index+0,itime); - const Vec3ff v1 = vertex(index+1,itime); - const Vec3ff v2 = vertex(index+2,itime); - const Vec3ff v3 = vertex(index+3,itime); - const Vec3ff w0(xfmPoint(space,((Vec3fa)v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale); - const Vec3ff w1(xfmPoint(space,((Vec3fa)v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale); - const Vec3ff w2(xfmPoint(space,((Vec3fa)v2-ofs)*Vec3fa(scale)), maxRadiusScale*v2.w*r_scale); - const Vec3ff w3(xfmPoint(space,((Vec3fa)v3-ofs)*Vec3fa(scale)), maxRadiusScale*v3.w*r_scale); - return Curve3ff(w0,w1,w2,w3); - } - - __forceinline const Curve3fa getNormalCurve(size_t i, size_t itime = 0) const - { - const unsigned int index = curve(i); - const Vec3fa n0 = normal(index+0,itime); - const Vec3fa n1 = normal(index+1,itime); - const Vec3fa n2 = normal(index+2,itime); - const Vec3fa n3 = normal(index+3,itime); - return Curve3fa (n0,n1,n2,n3); - } - - __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const - { - const Curve3ff center = getCurveScaledRadius(i,itime); - const Curve3fa normal = getNormalCurve(i,itime); - const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal); - return ocurve; - } - - __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const { - return getOrientedCurveScaledRadius(i,itime).xfm(space); - } - - __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const { - return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale); - } - - /*! check if the i'th primitive is valid at the itime'th time step */ - __forceinline bool valid(Geometry::GType ctype, size_t i, const range& itime_range) const - { - const unsigned int index = curve(i); - if (index+3 >= numVertices()) return false; - - for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) - { - const float r0 = radius(index+0,itime); - const float r1 = radius(index+1,itime); - const float r2 = radius(index+2,itime); - const float r3 = radius(index+3,itime); - if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3)) - return false; - - const Vec3fa v0 = vertex(index+0,itime); - const Vec3fa v1 = vertex(index+1,itime); - const Vec3fa v2 = vertex(index+2,itime); - const Vec3fa v3 = vertex(index+3,itime); - if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3)) - return false; - - if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) - { - const Vec3fa n0 = normal(index+0,itime); - const Vec3fa n1 = normal(index+1,itime); - if (!isvalid(n0) || !isvalid(n1)) - return false; - } - } - - return true; - } - - void interpolate(const RTCInterpolateArguments* const args) - { - unsigned int primID = args->primID; - float u = args->u; - RTCBufferType bufferType = args->bufferType; - unsigned int bufferSlot = args->bufferSlot; - float* P = args->P; - float* dPdu = args->dPdu; - float* ddPdudu = args->ddPdudu; - unsigned int valueCount = args->valueCount; - - /* calculate base pointer and stride */ - assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || - (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); - const char* src = nullptr; - size_t stride = 0; - if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { - src = vertexAttribs[bufferSlot].getPtr(); - stride = vertexAttribs[bufferSlot].getStride(); - } else { - src = vertices[bufferSlot].getPtr(); - stride = vertices[bufferSlot].getStride(); - } - - for (unsigned int i=0; i class Curve> - struct HermiteCurveGeometryInterface : public CurveGeometry - { - typedef Curve HermiteCurve3ff; - typedef Curve HermiteCurve3fa; - - HermiteCurveGeometryInterface (Device* device, Geometry::GType gtype) - : CurveGeometry(device,gtype) {} - - __forceinline const HermiteCurve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const - { - const unsigned int index = curve(i); - Vec3ff v0 = vertex(index+0,itime); - Vec3ff v1 = vertex(index+1,itime); - Vec3ff t0 = tangent(index+0,itime); - Vec3ff t1 = tangent(index+1,itime); - v0.w *= maxRadiusScale; - v1.w *= maxRadiusScale; - t0.w *= maxRadiusScale; - t1.w *= maxRadiusScale; - return HermiteCurve3ff (v0,t0,v1,t1); - } - - __forceinline const HermiteCurve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const - { - const unsigned int index = curve(i); - const Vec3ff v0 = vertex(index+0,itime); - const Vec3ff v1 = vertex(index+1,itime); - const Vec3ff t0 = tangent(index+0,itime); - const Vec3ff t1 = tangent(index+1,itime); - const Vec3ff V0(xfmPoint(space,(Vec3fa)v0),maxRadiusScale*v0.w); - const Vec3ff V1(xfmPoint(space,(Vec3fa)v1),maxRadiusScale*v1.w); - const Vec3ff T0(xfmVector(space,(Vec3fa)t0),maxRadiusScale*t0.w); - const Vec3ff T1(xfmVector(space,(Vec3fa)t1),maxRadiusScale*t1.w); - return HermiteCurve3ff(V0,T0,V1,T1); - } - - __forceinline const HermiteCurve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const - { - const float r_scale = r_scale0*scale; - const unsigned int index = curve(i); - const Vec3ff v0 = vertex(index+0,itime); - const Vec3ff v1 = vertex(index+1,itime); - const Vec3ff t0 = tangent(index+0,itime); - const Vec3ff t1 = tangent(index+1,itime); - const Vec3ff V0(xfmPoint(space,(v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale); - const Vec3ff V1(xfmPoint(space,(v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale); - const Vec3ff T0(xfmVector(space,t0*Vec3fa(scale)), maxRadiusScale*t0.w*r_scale); - const Vec3ff T1(xfmVector(space,t1*Vec3fa(scale)), maxRadiusScale*t1.w*r_scale); - return HermiteCurve3ff(V0,T0,V1,T1); - } - - __forceinline const HermiteCurve3fa getNormalCurve(size_t i, size_t itime = 0) const - { - const unsigned int index = curve(i); - const Vec3fa n0 = normal(index+0,itime); - const Vec3fa n1 = normal(index+1,itime); - const Vec3fa dn0 = dnormal(index+0,itime); - const Vec3fa dn1 = dnormal(index+1,itime); - return HermiteCurve3fa (n0,dn0,n1,dn1); - } - - __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const - { - const HermiteCurve3ff center = getCurveScaledRadius(i,itime); - const HermiteCurve3fa normal = getNormalCurve(i,itime); - const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal); - return ocurve; - } - - __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const { - return getOrientedCurveScaledRadius(i,itime).xfm(space); - } - - __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const { - return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale); - } - - /*! check if the i'th primitive is valid at the itime'th time step */ - __forceinline bool valid(Geometry::GType ctype, size_t i, const range& itime_range) const - { - const unsigned int index = curve(i); - if (index+1 >= numVertices()) return false; - - for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) - { - const Vec3ff v0 = vertex(index+0,itime); - const Vec3ff v1 = vertex(index+1,itime); - if (!isvalid4(v0) || !isvalid4(v1)) - return false; - - const Vec3ff t0 = tangent(index+0,itime); - const Vec3ff t1 = tangent(index+1,itime); - if (!isvalid4(t0) || !isvalid4(t1)) - return false; - - if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) - { - const Vec3fa n0 = normal(index+0,itime); - const Vec3fa n1 = normal(index+1,itime); - if (!isvalid(n0) || !isvalid(n1)) - return false; - - const Vec3fa dn0 = dnormal(index+0,itime); - const Vec3fa dn1 = dnormal(index+1,itime); - if (!isvalid(dn0) || !isvalid(dn1)) - return false; - } - } - - return true; - } - - void interpolate(const RTCInterpolateArguments* const args) - { - unsigned int primID = args->primID; - float u = args->u; - RTCBufferType bufferType = args->bufferType; - unsigned int bufferSlot = args->bufferSlot; - float* P = args->P; - float* dPdu = args->dPdu; - float* ddPdudu = args->ddPdudu; - unsigned int valueCount = args->valueCount; - - /* we interpolate vertex attributes linearly for hermite basis */ - if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) - { - assert(bufferSlot <= vertexAttribs.size()); - const char* vsrc = vertexAttribs[bufferSlot].getPtr(); - const size_t vstride = vertexAttribs[bufferSlot].getStride(); - - for (unsigned int i=0; i curve(p0,t0,p1,t1); - if (P ) vfloat4::storeu(valid,P+i, curve.eval(u)); - if (dPdu ) vfloat4::storeu(valid,dPdu+i, curve.eval_du(u)); - if (ddPdudu) vfloat4::storeu(valid,ddPdudu+i,curve.eval_dudu(u)); - } - } - } - }; + } template class Curve> class CurveInterfaceT, template class Curve> struct CurveGeometryISA : public CurveInterfaceT @@ -867,7 +533,6 @@ namespace embree { if (!valid(ctype, j, make_range(0, numTimeSegments()))) continue; const BBox3fa box = bounds(j); - if (box.empty()) continue; // checks oriented curves with invalid normals which cause NaNs here const PrimRef prim(box,geomID,unsigned(j)); pinfo.add_center2(prim); prims[k++] = prim; @@ -882,7 +547,6 @@ namespace embree { if (!valid(ctype, j, this->timeSegmentRange(t0t1))) continue; const LBBox3fa lbox = linearBounds(j,t0t1); - if (lbox.bounds0.empty() || lbox.bounds1.empty()) continue; // checks oriented curves with invalid normals which cause NaNs here const PrimRefMB prim(lbox,this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j)); pinfo.add_primref(prim); prims[k++] = prim; @@ -914,7 +578,7 @@ namespace embree return linearBounds(ofs,scale,r_scale0,space,primID,time_range); } }; - + CurveGeometry* createCurves(Device* device, Geometry::GType gtype) { switch (gtype) { diff --git a/kernels/common/scene_curves.h b/kernels/common/scene_curves.h index 2649ab0e3e..a1ea45d3c7 100644 --- a/kernels/common/scene_curves.h +++ b/kernels/common/scene_curves.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -7,6 +7,12 @@ #include "geometry.h" #include "buffer.h" +#include "../subdiv/bezier_curve.h" +#include "../subdiv/hermite_curve.h" +#include "../subdiv/bspline_curve.h" +#include "../subdiv/catmullrom_curve.h" +#include "../subdiv/linear_bezier_patch.h" + namespace embree { /*! represents an array of bicubic bezier curves */ @@ -336,6 +342,355 @@ namespace embree int tessellationRate; //!< tessellation rate for flat curve float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii }; + + namespace isa + { + + template class Curve> + struct CurveGeometryInterface : public CurveGeometry + { + typedef Curve Curve3ff; + typedef Curve Curve3fa; + + CurveGeometryInterface (Device* device, Geometry::GType gtype) + : CurveGeometry(device,gtype) {} + + __forceinline const Curve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const + { + const unsigned int index = curve(i); + Vec3ff v0 = vertex(index+0,itime); + Vec3ff v1 = vertex(index+1,itime); + Vec3ff v2 = vertex(index+2,itime); + Vec3ff v3 = vertex(index+3,itime); + v0.w *= maxRadiusScale; + v1.w *= maxRadiusScale; + v2.w *= maxRadiusScale; + v3.w *= maxRadiusScale; + return Curve3ff (v0,v1,v2,v3); + } + + __forceinline const Curve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const + { + const unsigned int index = curve(i); + const Vec3ff v0 = vertex(index+0,itime); + const Vec3ff v1 = vertex(index+1,itime); + const Vec3ff v2 = vertex(index+2,itime); + const Vec3ff v3 = vertex(index+3,itime); + const Vec3ff w0(xfmPoint(space,(Vec3fa)v0), maxRadiusScale*v0.w); + const Vec3ff w1(xfmPoint(space,(Vec3fa)v1), maxRadiusScale*v1.w); + const Vec3ff w2(xfmPoint(space,(Vec3fa)v2), maxRadiusScale*v2.w); + const Vec3ff w3(xfmPoint(space,(Vec3fa)v3), maxRadiusScale*v3.w); + return Curve3ff(w0,w1,w2,w3); + } + + __forceinline const Curve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const + { + const float r_scale = r_scale0*scale; + const unsigned int index = curve(i); + const Vec3ff v0 = vertex(index+0,itime); + const Vec3ff v1 = vertex(index+1,itime); + const Vec3ff v2 = vertex(index+2,itime); + const Vec3ff v3 = vertex(index+3,itime); + const Vec3ff w0(xfmPoint(space,((Vec3fa)v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale); + const Vec3ff w1(xfmPoint(space,((Vec3fa)v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale); + const Vec3ff w2(xfmPoint(space,((Vec3fa)v2-ofs)*Vec3fa(scale)), maxRadiusScale*v2.w*r_scale); + const Vec3ff w3(xfmPoint(space,((Vec3fa)v3-ofs)*Vec3fa(scale)), maxRadiusScale*v3.w*r_scale); + return Curve3ff(w0,w1,w2,w3); + } + + __forceinline const Curve3fa getNormalCurve(size_t i, size_t itime = 0) const + { + const unsigned int index = curve(i); + const Vec3fa n0 = normal(index+0,itime); + const Vec3fa n1 = normal(index+1,itime); + const Vec3fa n2 = normal(index+2,itime); + const Vec3fa n3 = normal(index+3,itime); + return Curve3fa (n0,n1,n2,n3); + } + + __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const + { + const Curve3ff center = getCurveScaledRadius(i,itime); + const Curve3fa normal = getNormalCurve(i,itime); + const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal); + return ocurve; + } + + __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const { + return getOrientedCurveScaledRadius(i,itime).xfm(space); + } + + __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const { + return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale); + } + + /*! check if the i'th primitive is valid at the itime'th time step */ + __forceinline bool valid(Geometry::GType ctype, size_t i, const range& itime_range) const + { + const unsigned int index = curve(i); + if (index+3 >= numVertices()) return false; + + for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) + { + const float r0 = radius(index+0,itime); + const float r1 = radius(index+1,itime); + const float r2 = radius(index+2,itime); + const float r3 = radius(index+3,itime); + if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3)) + return false; + + const Vec3fa v0 = vertex(index+0,itime); + const Vec3fa v1 = vertex(index+1,itime); + const Vec3fa v2 = vertex(index+2,itime); + const Vec3fa v3 = vertex(index+3,itime); + if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3)) + return false; + + if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) + { + const Vec3fa n0 = normal(index+0,itime); + const Vec3fa n1 = normal(index+1,itime); + if (!isvalid(n0) || !isvalid(n1)) + return false; + + const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds(); + if (!isvalid(b)) + return false; + } + } + + return true; + } + + template + void interpolate_impl(const RTCInterpolateArguments* const args) + { + unsigned int primID = args->primID; + float u = args->u; + RTCBufferType bufferType = args->bufferType; + unsigned int bufferSlot = args->bufferSlot; + float* P = args->P; + float* dPdu = args->dPdu; + float* ddPdudu = args->ddPdudu; + unsigned int valueCount = args->valueCount; + + /* calculate base pointer and stride */ + assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || + (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); + const char* src = nullptr; + size_t stride = 0; + if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { + src = vertexAttribs[bufferSlot].getPtr(); + stride = vertexAttribs[bufferSlot].getStride(); + } else { + src = vertices[bufferSlot].getPtr(); + stride = vertices[bufferSlot].getStride(); + } + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint((int)valueCount); + const vfloat p0 = mem>::loadu(valid,(float*)&src[(index+0)*stride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&src[(index+1)*stride+ofs]); + const vfloat p2 = mem>::loadu(valid,(float*)&src[(index+2)*stride+ofs]); + const vfloat p3 = mem>::loadu(valid,(float*)&src[(index+3)*stride+ofs]); + + const Curve> curve(p0,p1,p2,p3); + if (P ) mem>::storeu(valid,P+i, curve.eval(u)); + if (dPdu ) mem>::storeu(valid,dPdu+i, curve.eval_du(u)); + if (ddPdudu) mem>::storeu(valid,ddPdudu+i,curve.eval_dudu(u)); + } + } + + void interpolate(const RTCInterpolateArguments* const args) { + interpolate_impl<4>(args); + } + }; + + template class Curve> + struct HermiteCurveGeometryInterface : public CurveGeometry + { + typedef Curve HermiteCurve3ff; + typedef Curve HermiteCurve3fa; + + HermiteCurveGeometryInterface (Device* device, Geometry::GType gtype) + : CurveGeometry(device,gtype) {} + + __forceinline const HermiteCurve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const + { + const unsigned int index = curve(i); + Vec3ff v0 = vertex(index+0,itime); + Vec3ff v1 = vertex(index+1,itime); + Vec3ff t0 = tangent(index+0,itime); + Vec3ff t1 = tangent(index+1,itime); + v0.w *= maxRadiusScale; + v1.w *= maxRadiusScale; + t0.w *= maxRadiusScale; + t1.w *= maxRadiusScale; + return HermiteCurve3ff (v0,t0,v1,t1); + } + + __forceinline const HermiteCurve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const + { + const unsigned int index = curve(i); + const Vec3ff v0 = vertex(index+0,itime); + const Vec3ff v1 = vertex(index+1,itime); + const Vec3ff t0 = tangent(index+0,itime); + const Vec3ff t1 = tangent(index+1,itime); + const Vec3ff V0(xfmPoint(space,(Vec3fa)v0),maxRadiusScale*v0.w); + const Vec3ff V1(xfmPoint(space,(Vec3fa)v1),maxRadiusScale*v1.w); + const Vec3ff T0(xfmVector(space,(Vec3fa)t0),maxRadiusScale*t0.w); + const Vec3ff T1(xfmVector(space,(Vec3fa)t1),maxRadiusScale*t1.w); + return HermiteCurve3ff(V0,T0,V1,T1); + } + + __forceinline const HermiteCurve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const + { + const float r_scale = r_scale0*scale; + const unsigned int index = curve(i); + const Vec3ff v0 = vertex(index+0,itime); + const Vec3ff v1 = vertex(index+1,itime); + const Vec3ff t0 = tangent(index+0,itime); + const Vec3ff t1 = tangent(index+1,itime); + const Vec3ff V0(xfmPoint(space,(v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale); + const Vec3ff V1(xfmPoint(space,(v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale); + const Vec3ff T0(xfmVector(space,t0*Vec3fa(scale)), maxRadiusScale*t0.w*r_scale); + const Vec3ff T1(xfmVector(space,t1*Vec3fa(scale)), maxRadiusScale*t1.w*r_scale); + return HermiteCurve3ff(V0,T0,V1,T1); + } + + __forceinline const HermiteCurve3fa getNormalCurve(size_t i, size_t itime = 0) const + { + const unsigned int index = curve(i); + const Vec3fa n0 = normal(index+0,itime); + const Vec3fa n1 = normal(index+1,itime); + const Vec3fa dn0 = dnormal(index+0,itime); + const Vec3fa dn1 = dnormal(index+1,itime); + return HermiteCurve3fa (n0,dn0,n1,dn1); + } + + __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const + { + const HermiteCurve3ff center = getCurveScaledRadius(i,itime); + const HermiteCurve3fa normal = getNormalCurve(i,itime); + const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal); + return ocurve; + } + + __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const { + return getOrientedCurveScaledRadius(i,itime).xfm(space); + } + + __forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const { + return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale); + } + + /*! check if the i'th primitive is valid at the itime'th time step */ + __forceinline bool valid(Geometry::GType ctype, size_t i, const range& itime_range) const + { + const unsigned int index = curve(i); + if (index+1 >= numVertices()) return false; + + for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) + { + const Vec3ff v0 = vertex(index+0,itime); + const Vec3ff v1 = vertex(index+1,itime); + if (!isvalid4(v0) || !isvalid4(v1)) + return false; + + const Vec3ff t0 = tangent(index+0,itime); + const Vec3ff t1 = tangent(index+1,itime); + if (!isvalid4(t0) || !isvalid4(t1)) + return false; + + if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) + { + const Vec3fa n0 = normal(index+0,itime); + const Vec3fa n1 = normal(index+1,itime); + if (!isvalid(n0) || !isvalid(n1)) + return false; + + const Vec3fa dn0 = dnormal(index+0,itime); + const Vec3fa dn1 = dnormal(index+1,itime); + if (!isvalid(dn0) || !isvalid(dn1)) + return false; + + const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds(); + if (!isvalid(b)) + return false; + } + } + + return true; + } + + template + void interpolate_impl(const RTCInterpolateArguments* const args) + { + unsigned int primID = args->primID; + float u = args->u; + RTCBufferType bufferType = args->bufferType; + unsigned int bufferSlot = args->bufferSlot; + float* P = args->P; + float* dPdu = args->dPdu; + float* ddPdudu = args->ddPdudu; + unsigned int valueCount = args->valueCount; + + /* we interpolate vertex attributes linearly for hermite basis */ + if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) + { + assert(bufferSlot <= vertexAttribs.size()); + const char* vsrc = vertexAttribs[bufferSlot].getPtr(); + const size_t vstride = vertexAttribs[bufferSlot].getStride(); + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint((int)valueCount); + const vfloat p0 = mem>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]); + + if (P ) mem>::storeu(valid,P+i, madd(1.0f-u,p0,u*p1)); + if (dPdu ) mem>::storeu(valid,dPdu+i, p1-p0); + if (ddPdudu) mem>::storeu(valid,ddPdudu+i,vfloat(zero)); + } + } + + /* interpolation for vertex buffers */ + else + { + assert(bufferSlot < numTimeSteps); + const char* vsrc = vertices[bufferSlot].getPtr(); + const char* tsrc = tangents[bufferSlot].getPtr(); + const size_t vstride = vertices[bufferSlot].getStride(); + const size_t tstride = vertices[bufferSlot].getStride(); + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint((int)valueCount); + const vfloat p0 = mem>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]); + const vfloat t0 = mem>::loadu(valid,(float*)&tsrc[(index+0)*tstride+ofs]); + const vfloat t1 = mem>::loadu(valid,(float*)&tsrc[(index+1)*tstride+ofs]); + + const HermiteCurveT> curve(p0,t0,p1,t1); + if (P ) mem>::storeu(valid,P+i, curve.eval(u)); + if (dPdu ) mem>::storeu(valid,dPdu+i, curve.eval_du(u)); + if (ddPdudu) mem>::storeu(valid,ddPdudu+i,curve.eval_dudu(u)); + } + } + } + + void interpolate(const RTCInterpolateArguments* const args) { + interpolate_impl<4>(args); + } + }; + } DECLARE_ISA_FUNCTION(CurveGeometry*, createCurves, Device* COMMA Geometry::GType); } diff --git a/kernels/common/scene_grid_mesh.cpp b/kernels/common/scene_grid_mesh.cpp index da280082b3..ca4ee240a4 100644 --- a/kernels/common/scene_grid_mesh.cpp +++ b/kernels/common/scene_grid_mesh.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_grid_mesh.h" @@ -172,80 +172,12 @@ namespace embree return true; } - void GridMesh::interpolate(const RTCInterpolateArguments* const args) - { - unsigned int primID = args->primID; - float U = args->u; - float V = args->v; - RTCBufferType bufferType = args->bufferType; - unsigned int bufferSlot = args->bufferSlot; - float* P = args->P; - float* dPdu = args->dPdu; - float* dPdv = args->dPdv; - float* ddPdudu = args->ddPdudu; - float* ddPdvdv = args->ddPdvdv; - float* ddPdudv = args->ddPdudv; - unsigned int valueCount = args->valueCount; - - /* calculate base pointer and stride */ - assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || - (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); - const char* src = nullptr; - size_t stride = 0; - if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { - src = vertexAttribs[bufferSlot].getPtr(); - stride = vertexAttribs[bufferSlot].getStride(); - } else { - src = vertices[bufferSlot].getPtr(); - stride = vertices[bufferSlot].getStride(); - } - - const Grid& grid = grids[primID]; - const int grid_width = grid.resX-1; - const int grid_height = grid.resY-1; - const float rcp_grid_width = rcp(float(grid_width)); - const float rcp_grid_height = rcp(float(grid_height)); - const int iu = min((int)floor(U*grid_width ),grid_width); - const int iv = min((int)floor(V*grid_height),grid_height); - const float u = U*grid_width-float(iu); - const float v = V*grid_height-float(iv); - - for (unsigned int i=0; i(args); } #endif - + namespace isa { GridMesh* createGridMesh(Device* device) { diff --git a/kernels/common/scene_grid_mesh.h b/kernels/common/scene_grid_mesh.h index c08658466a..fb6fed445b 100644 --- a/kernels/common/scene_grid_mesh.h +++ b/kernels/common/scene_grid_mesh.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -55,8 +55,87 @@ namespace embree void commit(); bool verify(); void interpolate(const RTCInterpolateArguments* const args); - void addElementsToCount (GeometryCounts & counts) const; + template + void interpolate_impl(const RTCInterpolateArguments* const args) + { + unsigned int primID = args->primID; + float U = args->u; + float V = args->v; + + /* clamp input u,v to [0;1] range */ + U = max(min(U,1.0f),0.0f); + V = max(min(V,1.0f),0.0f); + + RTCBufferType bufferType = args->bufferType; + unsigned int bufferSlot = args->bufferSlot; + float* P = args->P; + float* dPdu = args->dPdu; + float* dPdv = args->dPdv; + float* ddPdudu = args->ddPdudu; + float* ddPdvdv = args->ddPdvdv; + float* ddPdudv = args->ddPdudv; + unsigned int valueCount = args->valueCount; + + /* calculate base pointer and stride */ + assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || + (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); + const char* src = nullptr; + size_t stride = 0; + if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { + src = vertexAttribs[bufferSlot].getPtr(); + stride = vertexAttribs[bufferSlot].getStride(); + } else { + src = vertices[bufferSlot].getPtr(); + stride = vertices[bufferSlot].getStride(); + } + + const Grid& grid = grids[primID]; + const int grid_width = grid.resX-1; + const int grid_height = grid.resY-1; + const float rcp_grid_width = rcp(float(grid_width)); + const float rcp_grid_height = rcp(float(grid_height)); + const int iu = min((int)floor(U*grid_width ),grid_width); + const int iv = min((int)floor(V*grid_height),grid_height); + const float u = U*grid_width-float(iu); + const float v = V*grid_height-float(iv); + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint(int(valueCount)); + const vfloat p0 = mem>::loadu(valid,(float*)&src[(idx0+0)*stride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&src[(idx0+1)*stride+ofs]); + const vfloat p2 = mem>::loadu(valid,(float*)&src[(idx1+1)*stride+ofs]); + const vfloat p3 = mem>::loadu(valid,(float*)&src[(idx1+0)*stride+ofs]); + const vbool left = u+v <= 1.0f; + const vfloat Q0 = select(left,p0,p2); + const vfloat Q1 = select(left,p1,p3); + const vfloat Q2 = select(left,p3,p1); + const vfloat U = select(left,u,vfloat(1.0f)-u); + const vfloat V = select(left,v,vfloat(1.0f)-v); + const vfloat W = 1.0f-U-V; + + if (P) { + mem>::storeu(valid,P+i,madd(W,Q0,madd(U,Q1,V*Q2))); + } + if (dPdu) { + assert(dPdu); mem>::storeu(valid,dPdu+i,select(left,Q1-Q0,Q0-Q1)*rcp_grid_width); + assert(dPdv); mem>::storeu(valid,dPdv+i,select(left,Q2-Q0,Q0-Q2)*rcp_grid_height); + } + if (ddPdudu) { + assert(ddPdudu); mem>::storeu(valid,ddPdudu+i,vfloat(zero)); + assert(ddPdvdv); mem>::storeu(valid,ddPdvdv+i,vfloat(zero)); + assert(ddPdudv); mem>::storeu(valid,ddPdudv+i,vfloat(zero)); + } + } + } + + void addElementsToCount (GeometryCounts & counts) const; + __forceinline unsigned int getNumSubGrids(const size_t gridID) { const Grid &g = grid(gridID); diff --git a/kernels/common/scene_instance.cpp b/kernels/common/scene_instance.cpp index b35643fd19..3467954ca4 100644 --- a/kernels/common/scene_instance.cpp +++ b/kernels/common/scene_instance.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_instance.h" @@ -60,7 +60,7 @@ namespace embree void Instance::preCommit() { #if 0 // disable expensive instance optimization for now - // decide whether we're an expensive instnace or not + // decide whether we're an expensive instance or not auto numExpensiveGeo = static_cast (object)->getNumPrimitives(CurveGeometry::geom_type, false) + static_cast (object)->getNumPrimitives(CurveGeometry::geom_type, true) + static_cast (object)->getNumPrimitives(UserGeometry::geom_type, false) diff --git a/kernels/common/scene_instance.h b/kernels/common/scene_instance.h index f9f30d52ee..773f2b6fec 100644 --- a/kernels/common/scene_instance.h +++ b/kernels/common/scene_instance.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -85,6 +85,34 @@ namespace embree return lbbox; } + /*! calculates the build bounds of the i'th item, if it's valid */ + __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const + { + assert(i==0); + const BBox3fa b = bounds(i); + if (bbox) *bbox = b; + return isvalid(b); + } + + /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */ + __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const + { + assert(i==0); + const LBBox3fa bounds = linearBounds(i,itime); + bbox = bounds.bounds (); + return isvalid(bounds); + } + + /* gets version info of topology */ + unsigned int getTopologyVersion() const { + return numPrimitives; + } + + /* returns true if topology changed */ + bool topologyChanged(unsigned int otherVersion) const { + return numPrimitives != otherVersion; + } + /*! check if the i'th primitive is valid between the specified time range */ __forceinline bool valid(size_t i, const range& itime_range) const { @@ -122,8 +150,8 @@ namespace embree __forceinline AffineSpace3vf getWorld2Local(const vbool& valid, const vfloat& t) const { if (unlikely(gsubtype == GTY_SUBTYPE_INSTANCE_QUATERNION)) - return getWorld2LocalSlerp(valid, t); - return getWorld2LocalLerp(valid, t); + return getWorld2LocalSlerp(valid, t); + return getWorld2LocalLerp(valid, t); } private: @@ -132,7 +160,7 @@ namespace embree __forceinline AffineSpace3vf getWorld2LocalSlerp(const vbool& valid, const vfloat& t) const { vfloat ftime; - const vint itime_k = timeSegment(t, ftime); + const vint itime_k = timeSegment(t, ftime); assert(any(valid)); const size_t index = bsf(movemask(valid)); const int itime = itime_k[index]; @@ -158,7 +186,7 @@ namespace embree __forceinline AffineSpace3vf getWorld2LocalLerp(const vbool& valid, const vfloat& t) const { vfloat ftime; - const vint itime_k = timeSegment(t, ftime); + const vint itime_k = timeSegment(t, ftime); assert(any(valid)); const size_t index = bsf(movemask(valid)); const int itime = itime_k[index]; @@ -198,8 +226,10 @@ namespace embree assert(r.end() == 1); PrimInfo pinfo(empty); - const BBox3fa b = bounds(0); - if (!isvalid(b)) return pinfo; + BBox3fa b = empty; + if (!buildBounds(0,&b)) return pinfo; + // const BBox3fa b = bounds(0); + // if (!isvalid(b)) return pinfo; const PrimRef prim(b,geomID,unsigned(0)); pinfo.add_center2(prim); @@ -213,8 +243,11 @@ namespace embree assert(r.end() == 1); PrimInfo pinfo(empty); - if (!valid(0,range(itime))) return pinfo; - const PrimRef prim(linearBounds(0,itime).bounds(),geomID,unsigned(0)); + BBox3fa b = empty; + if (!buildBounds(0,&b)) return pinfo; + // if (!valid(0,range(itime))) return pinfo; + // const PrimRef prim(linearBounds(0,itime).bounds(),geomID,unsigned(0)); + const PrimRef prim(b,geomID,unsigned(0)); pinfo.add_center2(prim); prims[k++] = prim; return pinfo; diff --git a/kernels/common/scene_line_segments.cpp b/kernels/common/scene_line_segments.cpp index d66e9a9841..1b3f44fef4 100644 --- a/kernels/common/scene_line_segments.cpp +++ b/kernels/common/scene_line_segments.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_line_segments.h" @@ -265,43 +265,10 @@ namespace embree } } return true; - } + } - void LineSegments::interpolate(const RTCInterpolateArguments* const args) - { - unsigned int primID = args->primID; - float u = args->u; - RTCBufferType bufferType = args->bufferType; - unsigned int bufferSlot = args->bufferSlot; - float* P = args->P; - float* dPdu = args->dPdu; - float* ddPdudu = args->ddPdudu; - unsigned int valueCount = args->valueCount; - - /* calculate base pointer and stride */ - assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || - (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); - const char* src = nullptr; - size_t stride = 0; - if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { - src = vertexAttribs[bufferSlot].getPtr(); - stride = vertexAttribs[bufferSlot].getStride(); - } else { - src = vertices[bufferSlot].getPtr(); - stride = vertices[bufferSlot].getStride(); - } - - for (unsigned int i=0; i(args); } #endif diff --git a/kernels/common/scene_line_segments.h b/kernels/common/scene_line_segments.h index c0f9ee8f77..3c9fdb39db 100644 --- a/kernels/common/scene_line_segments.h +++ b/kernels/common/scene_line_segments.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -34,6 +34,44 @@ namespace embree void setMaxRadiusScale(float s); void addElementsToCount (GeometryCounts & counts) const; + template + void interpolate_impl(const RTCInterpolateArguments* const args) + { + unsigned int primID = args->primID; + float u = args->u; + RTCBufferType bufferType = args->bufferType; + unsigned int bufferSlot = args->bufferSlot; + float* P = args->P; + float* dPdu = args->dPdu; + float* ddPdudu = args->ddPdudu; + unsigned int valueCount = args->valueCount; + + /* calculate base pointer and stride */ + assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || + (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); + const char* src = nullptr; + size_t stride = 0; + if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { + src = vertexAttribs[bufferSlot].getPtr(); + stride = vertexAttribs[bufferSlot].getStride(); + } else { + src = vertices[bufferSlot].getPtr(); + stride = vertices[bufferSlot].getStride(); + } + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint(int(valueCount)); + const vfloat p0 = mem>::loadu(valid,(float*)&src[(segment+0)*stride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&src[(segment+1)*stride+ofs]); + if (P ) mem>::storeu(valid,P+i,lerp(p0,p1,u)); + if (dPdu ) mem>::storeu(valid,dPdu+i,p1-p0); + if (ddPdudu) mem>::storeu(valid,dPdu+i,vfloat(zero)); + } + } + public: /*! returns the number of vertices */ diff --git a/kernels/common/scene_points.cpp b/kernels/common/scene_points.cpp index b0bb2d90c7..8d4c63f4d6 100644 --- a/kernels/common/scene_points.cpp +++ b/kernels/common/scene_points.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_points.h" diff --git a/kernels/common/scene_points.h b/kernels/common/scene_points.h index e1da12bc81..017e098a51 100644 --- a/kernels/common/scene_points.h +++ b/kernels/common/scene_points.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -164,22 +164,19 @@ namespace embree } /*! calculates the linear bounds of the i'th primitive for the specified time range */ - __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& time_range) const - { - return LBBox3fa([&](size_t itime) { return bounds(primID, itime); }, time_range, fnumTimeSegments); + __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const { + return LBBox3fa([&](size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments); } /*! calculates the linear bounds of the i'th primitive for the specified time range */ - __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const - { - return LBBox3fa([&](size_t itime) { return bounds(space, primID, itime); }, time_range, fnumTimeSegments); + __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const { + return LBBox3fa([&](size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments); } /*! calculates the linear bounds of the i'th primitive for the specified time range */ __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const { - if (!valid(i, getTimeSegmentRange(time_range, fnumTimeSegments))) - return false; + if (!valid(i, timeSegmentRange(time_range))) return false; bbox = linearBounds(i, time_range); return true; } @@ -250,14 +247,9 @@ namespace embree { PrimInfoMB pinfo(empty); for (size_t j = r.begin(); j < r.end(); j++) { - if (!valid(j, getTimeSegmentRange(t0t1, fnumTimeSegments))) + if (!valid(j, timeSegmentRange(t0t1))) continue; - const PrimRefMB prim(linearBounds(j, t0t1), - this->numTimeSegments(), - this->time_range, - this->numTimeSegments(), - geomID, - unsigned(j)); + const PrimRefMB prim(linearBounds(j, t0t1), this->numTimeSegments(), this->time_range, this->numTimeSegments(), geomID, unsigned(j)); pinfo.add_primref(prim); prims[k++] = prim; } diff --git a/kernels/common/scene_quad_mesh.cpp b/kernels/common/scene_quad_mesh.cpp index c0ae1dd9de..ccab1a0732 100644 --- a/kernels/common/scene_quad_mesh.cpp +++ b/kernels/common/scene_quad_mesh.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_quad_mesh.h" @@ -175,63 +175,8 @@ namespace embree return true; } - void QuadMesh::interpolate(const RTCInterpolateArguments* const args) - { - unsigned int primID = args->primID; - float u = args->u; - float v = args->v; - RTCBufferType bufferType = args->bufferType; - unsigned int bufferSlot = args->bufferSlot; - float* P = args->P; - float* dPdu = args->dPdu; - float* dPdv = args->dPdv; - float* ddPdudu = args->ddPdudu; - float* ddPdvdv = args->ddPdvdv; - float* ddPdudv = args->ddPdudv; - unsigned int valueCount = args->valueCount; - - /* calculate base pointer and stride */ - assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || - (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); - const char* src = nullptr; - size_t stride = 0; - if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { - src = vertexAttribs[bufferSlot].getPtr(); - stride = vertexAttribs[bufferSlot].getStride(); - } else { - src = vertices[bufferSlot].getPtr(); - stride = vertices[bufferSlot].getStride(); - } - - for (unsigned int i=0; i(args); } #endif diff --git a/kernels/common/scene_quad_mesh.h b/kernels/common/scene_quad_mesh.h index d5bb054b14..bd8eeaaeb7 100644 --- a/kernels/common/scene_quad_mesh.h +++ b/kernels/common/scene_quad_mesh.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -43,6 +43,66 @@ namespace embree void interpolate(const RTCInterpolateArguments* const args); void addElementsToCount (GeometryCounts & counts) const; + template + void interpolate_impl(const RTCInterpolateArguments* const args) + { + unsigned int primID = args->primID; + float u = args->u; + float v = args->v; + RTCBufferType bufferType = args->bufferType; + unsigned int bufferSlot = args->bufferSlot; + float* P = args->P; + float* dPdu = args->dPdu; + float* dPdv = args->dPdv; + float* ddPdudu = args->ddPdudu; + float* ddPdvdv = args->ddPdvdv; + float* ddPdudv = args->ddPdudv; + unsigned int valueCount = args->valueCount; + + /* calculate base pointer and stride */ + assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || + (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); + const char* src = nullptr; + size_t stride = 0; + if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { + src = vertexAttribs[bufferSlot].getPtr(); + stride = vertexAttribs[bufferSlot].getStride(); + } else { + src = vertices[bufferSlot].getPtr(); + stride = vertices[bufferSlot].getStride(); + } + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint(int(valueCount)); + const size_t ofs = i*sizeof(float); + const Quad& tri = quad(primID); + const vfloat p0 = mem>::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]); + const vfloat p2 = mem>::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]); + const vfloat p3 = mem>::loadu(valid,(float*)&src[tri.v[3]*stride+ofs]); + const vbool left = u+v <= 1.0f; + const vfloat Q0 = select(left,p0,p2); + const vfloat Q1 = select(left,p1,p3); + const vfloat Q2 = select(left,p3,p1); + const vfloat U = select(left,u,vfloat(1.0f)-u); + const vfloat V = select(left,v,vfloat(1.0f)-v); + const vfloat W = 1.0f-U-V; + if (P) { + mem>::storeu(valid,P+i,madd(W,Q0,madd(U,Q1,V*Q2))); + } + if (dPdu) { + assert(dPdu); mem>::storeu(valid,dPdu+i,select(left,Q1-Q0,Q0-Q1)); + assert(dPdv); mem>::storeu(valid,dPdv+i,select(left,Q2-Q0,Q0-Q2)); + } + if (ddPdudu) { + assert(ddPdudu); mem>::storeu(valid,ddPdudu+i,vfloat(zero)); + assert(ddPdvdv); mem>::storeu(valid,ddPdvdv+i,vfloat(zero)); + assert(ddPdudv); mem>::storeu(valid,ddPdudv+i,vfloat(zero)); + } + } + } + public: /*! returns number of vertices */ diff --git a/kernels/common/scene_subdiv_mesh.cpp b/kernels/common/scene_subdiv_mesh.cpp index 9d2679755b..8cc09014b7 100644 --- a/kernels/common/scene_subdiv_mesh.cpp +++ b/kernels/common/scene_subdiv_mesh.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_subdiv_mesh.h" diff --git a/kernels/common/scene_subdiv_mesh.h b/kernels/common/scene_subdiv_mesh.h index 25ee8e8efa..1db170196d 100644 --- a/kernels/common/scene_subdiv_mesh.h +++ b/kernels/common/scene_subdiv_mesh.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/scene_triangle_mesh.cpp b/kernels/common/scene_triangle_mesh.cpp index d1c2750f14..3bbd7e51ae 100644 --- a/kernels/common/scene_triangle_mesh.cpp +++ b/kernels/common/scene_triangle_mesh.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_triangle_mesh.h" @@ -178,62 +178,13 @@ namespace embree return true; } - - void TriangleMesh::interpolate(const RTCInterpolateArguments* const args) - { - unsigned int primID = args->primID; - float u = args->u; - float v = args->v; - RTCBufferType bufferType = args->bufferType; - unsigned int bufferSlot = args->bufferSlot; - float* P = args->P; - float* dPdu = args->dPdu; - float* dPdv = args->dPdv; - float* ddPdudu = args->ddPdudu; - float* ddPdvdv = args->ddPdvdv; - float* ddPdudv = args->ddPdudv; - unsigned int valueCount = args->valueCount; - - /* calculate base pointer and stride */ - assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || - (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); - const char* src = nullptr; - size_t stride = 0; - if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { - src = vertexAttribs[bufferSlot].getPtr(); - stride = vertexAttribs[bufferSlot].getStride(); - } else { - src = vertices[bufferSlot].getPtr(); - stride = vertices[bufferSlot].getStride(); - } - - for (unsigned int i=0; i(args); } - + #endif - + namespace isa { TriangleMesh* createTriangleMesh(Device* device) { diff --git a/kernels/common/scene_triangle_mesh.h b/kernels/common/scene_triangle_mesh.h index 28bd744d16..ad3f602fde 100644 --- a/kernels/common/scene_triangle_mesh.h +++ b/kernels/common/scene_triangle_mesh.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -43,8 +43,62 @@ namespace embree void interpolate(const RTCInterpolateArguments* const args); void addElementsToCount (GeometryCounts & counts) const; + template + void interpolate_impl(const RTCInterpolateArguments* const args) + { + unsigned int primID = args->primID; + float u = args->u; + float v = args->v; + RTCBufferType bufferType = args->bufferType; + unsigned int bufferSlot = args->bufferSlot; + float* P = args->P; + float* dPdu = args->dPdu; + float* dPdv = args->dPdv; + float* ddPdudu = args->ddPdudu; + float* ddPdvdv = args->ddPdvdv; + float* ddPdudv = args->ddPdudv; + unsigned int valueCount = args->valueCount; + + /* calculate base pointer and stride */ + assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) || + (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size())); + const char* src = nullptr; + size_t stride = 0; + if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) { + src = vertexAttribs[bufferSlot].getPtr(); + stride = vertexAttribs[bufferSlot].getStride(); + } else { + src = vertices[bufferSlot].getPtr(); + stride = vertices[bufferSlot].getStride(); + } + + for (unsigned int i=0; i valid = vint((int)i)+vint(step) < vint(int(valueCount)); + const vfloat p0 = mem>::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]); + const vfloat p1 = mem>::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]); + const vfloat p2 = mem>::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]); + + if (P) { + mem>::storeu(valid,P+i,madd(w,p0,madd(u,p1,v*p2))); + } + if (dPdu) { + assert(dPdu); mem>::storeu(valid,dPdu+i,p1-p0); + assert(dPdv); mem>::storeu(valid,dPdv+i,p2-p0); + } + if (ddPdudu) { + assert(ddPdudu); mem>::storeu(valid,ddPdudu+i,vfloat(zero)); + assert(ddPdvdv); mem>::storeu(valid,ddPdvdv+i,vfloat(zero)); + assert(ddPdudv); mem>::storeu(valid,ddPdudv+i,vfloat(zero)); + } + } + } + public: - + /*! returns number of vertices */ __forceinline size_t numVertices() const { return vertices[0].size(); @@ -95,15 +149,6 @@ namespace embree return BBox3fa(min(v0,v1,v2),max(v0,v1,v2)); } - /*! calculates the interpolated bounds of the i'th triangle at the specified time */ - __forceinline BBox3fa bounds(size_t i, float time) const - { - float ftime; size_t itime = getTimeSegment(time, fnumTimeSegments, ftime); - const BBox3fa b0 = bounds(i, itime+0); - const BBox3fa b1 = bounds(i, itime+1); - return lerp(b0, b1, ftime); - } - /*! check if the i'th primitive is valid at the itime'th timestep */ __forceinline bool valid(size_t i, size_t itime) const { return valid(i, make_range(itime, itime)); diff --git a/kernels/common/scene_user_geometry.cpp b/kernels/common/scene_user_geometry.cpp index e80bb8718d..db19db585e 100644 --- a/kernels/common/scene_user_geometry.cpp +++ b/kernels/common/scene_user_geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_user_geometry.h" diff --git a/kernels/common/scene_user_geometry.h b/kernels/common/scene_user_geometry.h index 8d11ed6986..2867b18b79 100644 --- a/kernels/common/scene_user_geometry.h +++ b/kernels/common/scene_user_geometry.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/stack_item.h b/kernels/common/stack_item.h index 533c385365..c31c64e862 100644 --- a/kernels/common/stack_item.h +++ b/kernels/common/stack_item.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/stat.cpp b/kernels/common/stat.cpp index b73c3a8c76..ebb77cd534 100644 --- a/kernels/common/stat.cpp +++ b/kernels/common/stat.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stat.h" diff --git a/kernels/common/stat.h b/kernels/common/stat.h index 3cda2bd014..02fc07e67f 100644 --- a/kernels/common/stat.h +++ b/kernels/common/stat.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/common/state.cpp b/kernels/common/state.cpp index 6582470097..db6b803041 100644 --- a/kernels/common/state.cpp +++ b/kernels/common/state.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "state.h" @@ -100,7 +100,6 @@ namespace embree instancing_open_max_depth = 32; instancing_open_max = 50000000; - ignore_config_files = false; float_exceptions = false; quality_flags = -1; scene_flags = -1; @@ -115,8 +114,6 @@ namespace embree #else set_affinity = false; #endif - /* per default enable affinity on KNL */ - if (hasISA(AVX512KNL)) set_affinity = true; start_threads = false; enable_selockmemoryprivilege = false; @@ -146,6 +143,23 @@ namespace embree return (enabled_cpu_features & isa) == isa; } + bool State::checkISASupport() { +#if defined(__ARM_NEON) + /* + * NEON CPU type is a mixture of NEON and SSE2 + */ + + bool hasSSE2 = (getCPUFeatures() & enabled_cpu_features) & CPU_FEATURE_SSE2; + + /* this will be true when explicitly initialize Device with `isa=neon` config */ + bool hasNEON = (getCPUFeatures() & enabled_cpu_features) & CPU_FEATURE_NEON; + + return hasSSE2 || hasNEON; +#else + return (getCPUFeatures() & enabled_cpu_features) == enabled_cpu_features; +#endif + } + void State::verify() { /* verify that calculations stay in range */ @@ -156,8 +170,10 @@ namespace embree * functions */ #if defined(DEBUG) #if defined(EMBREE_TARGET_SSE2) +#if !defined(__ARM_NEON) assert(sse2::getISA() <= SSE2); #endif +#endif #if defined(EMBREE_TARGET_SSE42) assert(sse42::getISA() <= SSE42); #endif @@ -167,18 +183,15 @@ namespace embree #if defined(EMBREE_TARGET_AVX2) assert(avx2::getISA() <= AVX2); #endif -#if defined (EMBREE_TARGET_AVX512KNL) - assert(avx512knl::getISA() <= AVX512KNL); -#endif -#if defined (EMBREE_TARGET_AVX512SKX) - assert(avx512skx::getISA() <= AVX512SKX); +#if defined (EMBREE_TARGET_AVX512) + assert(avx512::getISA() <= AVX512); #endif #endif } const char* symbols[3] = { "=", ",", "|" }; - bool State::parseFile(const FileName& fileName) + bool State::parseFile(const FileName& fileName) { FILE* f = fopen(fileName.c_str(),"r"); if (!f) return false; @@ -222,8 +235,7 @@ namespace embree else if (isa == "avx") return AVX; else if (isa == "avxi") return AVXI; else if (isa == "avx2") return AVX2; - else if (isa == "avx512knl") return AVX512KNL; - else if (isa == "avx512skx") return AVX512SKX; + else if (isa == "avx512") return AVX512; else return SSE2; } @@ -250,20 +262,20 @@ namespace embree start_threads = cin->get().Int(); else if (tok == Token::Id("isa") && cin->trySymbol("=")) { - std::string isa = toLowerCase(cin->get().Identifier()); - enabled_cpu_features = string_to_cpufeatures(isa); + std::string isa_str = toLowerCase(cin->get().Identifier()); + enabled_cpu_features = string_to_cpufeatures(isa_str); enabled_builder_cpu_features = enabled_cpu_features; } else if (tok == Token::Id("max_isa") && cin->trySymbol("=")) { - std::string isa = toLowerCase(cin->get().Identifier()); - enabled_cpu_features &= string_to_cpufeatures(isa); + std::string isa_str = toLowerCase(cin->get().Identifier()); + enabled_cpu_features &= string_to_cpufeatures(isa_str); enabled_builder_cpu_features &= enabled_cpu_features; } else if (tok == Token::Id("max_builder_isa") && cin->trySymbol("=")) { - std::string isa = toLowerCase(cin->get().Identifier()); - enabled_builder_cpu_features &= string_to_cpufeatures(isa); + std::string isa_str = toLowerCase(cin->get().Identifier()); + enabled_builder_cpu_features &= string_to_cpufeatures(isa_str); } else if (tok == Token::Id("frequency_level") && cin->trySymbol("=")) { @@ -280,8 +292,6 @@ namespace embree hugepages = cin->get().Int(); } - else if (tok == Token::Id("ignore_config_files") && cin->trySymbol("=")) - ignore_config_files = cin->get().Int(); else if (tok == Token::Id("float_exceptions") && cin->trySymbol("=")) float_exceptions = cin->get().Int(); diff --git a/kernels/common/state.h b/kernels/common/state.h index 935d70d7df..33bcc843b2 100644 --- a/kernels/common/state.h +++ b/kernels/common/state.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -40,6 +40,9 @@ namespace embree /*! checks if some particular ISA is enabled */ bool hasISA(const int isa); + /*! check whether selected ISA is supported by the HW */ + bool checkISASupport(); + public: std::string tri_accel; //!< acceleration structure to use for triangles std::string tri_builder; //!< builder to use for triangles @@ -115,7 +118,6 @@ namespace embree size_t instancing_open_max; //!< instancing opens tree to maximally that number of subtrees public: - bool ignore_config_files; //!< if true no more config files get parse bool float_exceptions; //!< enable floating point exceptions int quality_flags; int scene_flags; diff --git a/kernels/common/vector.h b/kernels/common/vector.h index b478762240..4b08275f3b 100644 --- a/kernels/common/vector.h +++ b/kernels/common/vector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "default.h" diff --git a/kernels/config.h.in b/kernels/config.h.in index c1c38e8457..a0425fc4f6 100644 --- a/kernels/config.h.in +++ b/kernels/config.h.in @@ -1,9 +1,10 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #cmakedefine EMBREE_RAY_MASK #cmakedefine EMBREE_STAT_COUNTERS #cmakedefine EMBREE_BACKFACE_CULLING +#cmakedefine EMBREE_BACKFACE_CULLING_CURVES #cmakedefine EMBREE_FILTER_FUNCTION #cmakedefine EMBREE_IGNORE_INVALID_RAYS #cmakedefine EMBREE_GEOMETRY_TRIANGLE diff --git a/kernels/embree.rc b/kernels/embree.rc index 2b5041d45a..1a3a3e319f 100644 --- a/kernels/embree.rc +++ b/kernels/embree.rc @@ -1,18 +1,5 @@ -// ======================================================================== // -// Copyright 2009-2020 Intel Corporation // -// // -// Licensed under the Apache License, Version 2.0 (the "License"); // -// you may not use this file except in compliance with the License. // -// You may obtain a copy of the License at // -// // -// http://www.apache.org/licenses/LICENSE-2.0 // -// // -// Unless required by applicable law or agreed to in writing, software // -// distributed under the License is distributed on an "AS IS" BASIS, // -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // -// See the License for the specific language governing permissions and // -// limitations under the License. // -// ======================================================================== // +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 #include "../include/embree3/rtcore_config.h" @@ -37,7 +24,7 @@ BEGIN VALUE "FileDescription", "Embree Ray Tracing Kernels" VALUE "FileVersion", RTC_VERSION_STRING VALUE "ProductVersion", RTC_VERSION_STRING - VALUE "LegalCopyright", "© 2009-2020 Intel Corporation" + VALUE "LegalCopyright", "© 2009-2021 Intel Corporation" VALUE "InternalName", "Embree" VALUE "ProductName", "Intel® Embree" END diff --git a/kernels/export.linux.map b/kernels/export.linux.map deleted file mode 100644 index 818c4b415d..0000000000 --- a/kernels/export.linux.map +++ /dev/null @@ -1,18 +0,0 @@ -{ -global: - rtc*; - _ZN?rtc*; - _ZN??rtc*; - _ZN???rtc*; - _ZN????rtc*; - _ZN?????rtc*; - _ZN??rtc*; - _ZN???rtc*; - _ZN????rtc*; - _ZN?????rtc*; - _ZN??????rtc*; - _ZN6embree13TaskScheduler*; - _ZN6embree713TaskScheduler*; -local: - *; -}; diff --git a/kernels/export.linux.map.in b/kernels/export.linux.map.in index e06745c833..b3e511cbd7 100644 --- a/kernels/export.linux.map.in +++ b/kernels/export.linux.map.in @@ -5,12 +5,14 @@ global: _ZN?@EMBREE_API_NAMESPACE@?rtc*; _ZN?@EMBREE_API_NAMESPACE@??rtc*; _ZN?@EMBREE_API_NAMESPACE@???rtc*; - _ZN?@EMBREE_API_NAMESPACE@????rtc*; _ZN??@EMBREE_API_NAMESPACE@rtc*; _ZN??@EMBREE_API_NAMESPACE@?rtc*; _ZN??@EMBREE_API_NAMESPACE@??rtc*; _ZN??@EMBREE_API_NAMESPACE@???rtc*; - _ZN??@EMBREE_API_NAMESPACE@????rtc*; + _ZN???@EMBREE_API_NAMESPACE@rtc*; + _ZN???@EMBREE_API_NAMESPACE@?rtc*; + _ZN???@EMBREE_API_NAMESPACE@??rtc*; + _ZN???@EMBREE_API_NAMESPACE@???rtc*; _ZN6embree13TaskScheduler*; _ZN6embree7@EMBREE_API_NAMESPACE@13TaskScheduler*; local: diff --git a/kernels/export.macosx.map b/kernels/export.macosx.map deleted file mode 100644 index aabe11a083..0000000000 --- a/kernels/export.macosx.map +++ /dev/null @@ -1,8 +0,0 @@ -_rtc* -__ZN?rtc* -__ZN??rtc* -__ZN???rtc* -__ZN????rtc* -__ZN?????rtc* -__ZN6embree13TaskScheduler* -__ZN6embree713TaskScheduler* diff --git a/kernels/export.macosx.map.in b/kernels/export.macosx.map.in index e55cd65ef6..60c90b9966 100644 --- a/kernels/export.macosx.map.in +++ b/kernels/export.macosx.map.in @@ -3,6 +3,13 @@ __ZN?@EMBREE_API_NAMESPACE@rtc* __ZN?@EMBREE_API_NAMESPACE@?rtc* __ZN?@EMBREE_API_NAMESPACE@??rtc* __ZN?@EMBREE_API_NAMESPACE@???rtc* -__ZN?@EMBREE_API_NAMESPACE@????rtc* -__ZN6embree13TaskScheduler* -__ZN6embree7@EMBREE_API_NAMESPACE@13TaskScheduler* +__ZN??@EMBREE_API_NAMESPACE@rtc* +__ZN??@EMBREE_API_NAMESPACE@?rtc* +__ZN??@EMBREE_API_NAMESPACE@??rtc* +__ZN??@EMBREE_API_NAMESPACE@???rtc* +__ZN???@EMBREE_API_NAMESPACE@rtc* +__ZN???@EMBREE_API_NAMESPACE@?rtc* +__ZN???@EMBREE_API_NAMESPACE@??rtc* +__ZN???@EMBREE_API_NAMESPACE@???rtc* +# __ZN6embree13TaskScheduler* +# __ZN6embree7@EMBREE_API_NAMESPACE@13TaskScheduler* diff --git a/kernels/geometry/cone.h b/kernels/geometry/cone.h index 961ef86160..17429bab32 100644 --- a/kernels/geometry/cone.h +++ b/kernels/geometry/cone.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/coneline_intersector.h b/kernels/geometry/coneline_intersector.h new file mode 100644 index 0000000000..90f3792eff --- /dev/null +++ b/kernels/geometry/coneline_intersector.h @@ -0,0 +1,209 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "../common/ray.h" +#include "curve_intersector_precalculations.h" + +namespace embree +{ + namespace isa + { + namespace __coneline_internal + { + template + static __forceinline bool intersectCone(const vbool& valid_i, + const Vec3vf& ray_org_in, const Vec3vf& ray_dir, + const vfloat& ray_tnear, const ray_tfar_func& ray_tfar, + const Vec4vf& v0, const Vec4vf& v1, + const vbool& cL, const vbool& cR, + const Epilog& epilog) + { + vbool valid = valid_i; + + /* move ray origin closer to make calculations numerically stable */ + const vfloat dOdO = sqr(ray_dir); + const vfloat rcp_dOdO = rcp(dOdO); + const Vec3vf center = vfloat(0.5f)*(v0.xyz()+v1.xyz()); + const vfloat dt = dot(center-ray_org_in,ray_dir)*rcp_dOdO; + const Vec3vf ray_org = ray_org_in + dt*ray_dir; + + const Vec3vf dP = v1.xyz() - v0.xyz(); + const Vec3vf p0 = ray_org - v0.xyz(); + const Vec3vf p1 = ray_org - v1.xyz(); + + const vfloat dPdP = sqr(dP); + const vfloat dP0 = dot(p0,dP); + const vfloat dP1 = dot(p1,dP); + const vfloat dOdP = dot(ray_dir,dP); + + // intersect cone body + const vfloat dr = v0.w - v1.w; + const vfloat hy = dPdP + sqr(dr); + const vfloat dO0 = dot(ray_dir,p0); + const vfloat OO = sqr(p0); + const vfloat dPdP2 = sqr(dPdP); + const vfloat dPdPr0 = dPdP*v0.w; + + const vfloat A = dPdP2 - sqr(dOdP)*hy; + const vfloat B = dPdP2*dO0 - dP0*dOdP*hy + dPdPr0*(dr*dOdP); + const vfloat C = dPdP2*OO - sqr(dP0)*hy + dPdPr0*(2.0f*dr*dP0 - dPdPr0); + + const vfloat D = B*B - A*C; + valid &= D >= 0.0f; + if (unlikely(none(valid))) { + return false; + } + + /* standard case for "non-parallel" rays */ + const vfloat Q = sqrt(D); + const vfloat rcp_A = rcp(A); + /* special case for rays that are "parallel" to the cone - assume miss */ + const vbool isParallel = abs(A) <= min_rcp_input; + + vfloat t_cone_lower = select (isParallel, neg_inf, (-B-Q)*rcp_A); + vfloat t_cone_upper = select (isParallel, pos_inf, (-B+Q)*rcp_A); + const vfloat y_lower = dP0 + t_cone_lower*dOdP; + const vfloat y_upper = dP0 + t_cone_upper*dOdP; + t_cone_lower = select(valid & y_lower > 0.0f & y_lower < dPdP, t_cone_lower, pos_inf); + t_cone_upper = select(valid & y_upper > 0.0f & y_upper < dPdP, t_cone_upper, neg_inf); + + const vbool hitDisk0 = valid & cL; + const vbool hitDisk1 = valid & cR; + const vfloat rcp_dOdP = rcp(dOdP); + const vfloat t_disk0 = select (hitDisk0, select (sqr(p0*dOdP-ray_dir*dP0)<(sqr(v0.w)*sqr(dOdP)), -dP0*rcp_dOdP, pos_inf), pos_inf); + const vfloat t_disk1 = select (hitDisk1, select (sqr(p1*dOdP-ray_dir*dP1)<(sqr(v1.w)*sqr(dOdP)), -dP1*rcp_dOdP, pos_inf), pos_inf); + const vfloat t_disk_lower = min(t_disk0, t_disk1); + const vfloat t_disk_upper = max(t_disk0, t_disk1); + + const vfloat t_lower = min(t_cone_lower, t_disk_lower); + const vfloat t_upper = max(t_cone_upper, select(t_lower==t_disk_lower, + select(t_disk_upper==vfloat(pos_inf),neg_inf,t_disk_upper), + select(t_disk_lower==vfloat(pos_inf),neg_inf,t_disk_lower))); + + const vbool valid_lower = valid & ray_tnear <= dt+t_lower & dt+t_lower <= ray_tfar() & t_lower != vfloat(pos_inf); + const vbool valid_upper = valid & ray_tnear <= dt+t_upper & dt+t_upper <= ray_tfar() & t_upper != vfloat(neg_inf); + + const vbool valid_first = valid_lower | valid_upper; + if (unlikely(none(valid_first))) + return false; + + const vfloat t_first = select(valid_lower, t_lower, t_upper); + const vfloat y_first = select(valid_lower, y_lower, y_upper); + + const vfloat rcp_dPdP = rcp(dPdP); + const Vec3vf dP2drr0dP = dPdP*dr*v0.w*dP; + const Vec3vf dPhy = dP*hy; + const vbool cone_hit_first = valid & (t_first == t_cone_lower | t_first == t_cone_upper); + const vbool disk0_hit_first = valid & (t_first == t_disk0); + const Vec3vf Ng_first = select(cone_hit_first, dPdP2*(p0+t_first*ray_dir)+dP2drr0dP-dPhy*y_first, select(disk0_hit_first, -dP, dP)); + const vfloat u_first = select(cone_hit_first, y_first*rcp_dPdP, select(disk0_hit_first, vfloat(zero), vfloat(one))); + + /* invoke intersection filter for first hit */ + RoundLineIntersectorHitM hit(u_first,zero,dt+t_first,Ng_first); + const bool is_hit_first = epilog(valid_first, hit); + + /* check for possible second hits before potentially accepted hit */ + const vfloat t_second = t_upper; + const vfloat y_second = y_upper; + const vbool valid_second = valid_lower & valid_upper & (dt+t_upper <= ray_tfar()); + if (unlikely(none(valid_second))) + return is_hit_first; + + /* invoke intersection filter for second hit */ + const vbool cone_hit_second = t_second == t_cone_lower | t_second == t_cone_upper; + const vbool disk0_hit_second = t_second == t_disk0; + const Vec3vf Ng_second = select(cone_hit_second, dPdP2*(p0+t_second*ray_dir)+dP2drr0dP-dPhy*y_second, select(disk0_hit_second, -dP, dP)); + const vfloat u_second = select(cone_hit_second, y_second*rcp_dPdP, select(disk0_hit_first, vfloat(zero), vfloat(one))); + + hit = RoundLineIntersectorHitM(u_second,zero,dt+t_second,Ng_second); + const bool is_hit_second = epilog(valid_second, hit); + + return is_hit_first | is_hit_second; + } + } + + template + struct ConeLineIntersectorHitM + { + __forceinline ConeLineIntersectorHitM() {} + + __forceinline ConeLineIntersectorHitM(const vfloat& u, const vfloat& v, const vfloat& t, const Vec3vf& Ng) + : vu(u), vv(v), vt(t), vNg(Ng) {} + + __forceinline void finalize() {} + + __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } + __forceinline float t (const size_t i) const { return vt[i]; } + __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } + + public: + vfloat vu; + vfloat vv; + vfloat vt; + Vec3vf vNg; + }; + + template + struct ConeCurveIntersector1 + { + typedef CurvePrecalculations1 Precalculations; + + struct ray_tfar { + Ray& ray; + __forceinline ray_tfar(Ray& ray) : ray(ray) {} + __forceinline vfloat operator() () const { return ray.tfar; }; + }; + + template + static __forceinline bool intersect(const vbool& valid_i, + Ray& ray, + IntersectContext* context, + const LineSegments* geom, + const Precalculations& pre, + const Vec4vf& v0i, const Vec4vf& v1i, + const vbool& cL, const vbool& cR, + const Epilog& epilog) + { + const Vec3vf ray_org(ray.org.x, ray.org.y, ray.org.z); + const Vec3vf ray_dir(ray.dir.x, ray.dir.y, ray.dir.z); + const vfloat ray_tnear(ray.tnear()); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); + return __coneline_internal::intersectCone(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray),v0,v1,cL,cR,epilog); + } + }; + + template + struct ConeCurveIntersectorK + { + typedef CurvePrecalculationsK Precalculations; + + struct ray_tfar { + RayK& ray; + size_t k; + __forceinline ray_tfar(RayK& ray, size_t k) : ray(ray), k(k) {} + __forceinline vfloat operator() () const { return ray.tfar[k]; }; + }; + + template + static __forceinline bool intersect(const vbool& valid_i, + RayK& ray, size_t k, + IntersectContext* context, + const LineSegments* geom, + const Precalculations& pre, + const Vec4vf& v0i, const Vec4vf& v1i, + const vbool& cL, const vbool& cR, + const Epilog& epilog) + { + const Vec3vf ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); + const Vec3vf ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]); + const vfloat ray_tnear = ray.tnear()[k]; + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); + return __coneline_internal::intersectCone(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,cL,cR,epilog); + } + }; + } +} diff --git a/kernels/geometry/conelinei_intersector.h b/kernels/geometry/conelinei_intersector.h new file mode 100644 index 0000000000..6a985ebcad --- /dev/null +++ b/kernels/geometry/conelinei_intersector.h @@ -0,0 +1,141 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "coneline_intersector.h" +#include "intersector_epilog.h" + +namespace embree +{ + namespace isa + { + template + struct ConeCurveMiIntersector1 + { + typedef LineMi Primitive; + typedef CurvePrecalculations1 Precalculations; + + static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line) + { + STAT3(normal.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom); + const vbool valid = line.valid(); + ConeCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); + } + + static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line) + { + STAT3(shadow.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom); + const vbool valid = line.valid(); + return ConeCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); + return false; + } + + static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line) + { + return PrimitivePointQuery1::pointQuery(query, context, line); + } + }; + + template + struct ConeCurveMiMBIntersector1 + { + typedef LineMi Primitive; + typedef CurvePrecalculations1 Precalculations; + + static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& line) + { + STAT3(normal.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom,ray.time()); + const vbool valid = line.valid(); + ConeCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); + } + + static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line) + { + STAT3(shadow.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom,ray.time()); + const vbool valid = line.valid(); + return ConeCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,cL,cR,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); + return false; + } + + static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line) + { + return PrimitivePointQuery1::pointQuery(query, context, line); + } + }; + + template + struct ConeCurveMiIntersectorK + { + typedef LineMi Primitive; + typedef CurvePrecalculationsK Precalculations; + + static __forceinline void intersect(const Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive& line) + { + STAT3(normal.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom); + const vbool valid = line.valid(); + ConeCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); + } + + static __forceinline bool occluded(const Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& line) + { + STAT3(shadow.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom); + const vbool valid = line.valid(); + return ConeCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); + } + }; + + template + struct ConeCurveMiMBIntersectorK + { + typedef LineMi Primitive; + typedef CurvePrecalculationsK Precalculations; + + static __forceinline void intersect(const Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive& line) + { + STAT3(normal.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom,ray.time()[k]); + const vbool valid = line.valid(); + ConeCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); + } + + static __forceinline bool occluded(const Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& line) + { + STAT3(shadow.trav_prims,1,1,1); + const LineSegments* geom = context->scene->get(line.geomID()); + Vec4vf v0,v1; + vbool cL,cR; + line.gather(v0,v1,cL,cR,geom,ray.time()[k]); + const vbool valid = line.valid(); + return ConeCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,cL,cR,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); + } + }; + } +} diff --git a/kernels/geometry/curveNi.h b/kernels/geometry/curveNi.h index 00ca9b8b65..6366a6fb9c 100644 --- a/kernels/geometry/curveNi.h +++ b/kernels/geometry/curveNi.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curveNi_intersector.h b/kernels/geometry/curveNi_intersector.h index 0f9038c9fc..c0b66515c1 100644 --- a/kernels/geometry/curveNi_intersector.h +++ b/kernels/geometry/curveNi_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curveNi_mb.h b/kernels/geometry/curveNi_mb.h index d2e1926220..5d972b43a0 100644 --- a/kernels/geometry/curveNi_mb.h +++ b/kernels/geometry/curveNi_mb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curveNi_mb_intersector.h b/kernels/geometry/curveNi_mb_intersector.h index 0cbc764668..bab796b33b 100644 --- a/kernels/geometry/curveNi_mb_intersector.h +++ b/kernels/geometry/curveNi_mb_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curveNv.h b/kernels/geometry/curveNv.h index 6eb5e30b39..e41a381706 100644 --- a/kernels/geometry/curveNv.h +++ b/kernels/geometry/curveNv.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curveNv_intersector.h b/kernels/geometry/curveNv_intersector.h index e20da2882e..2742725aec 100644 --- a/kernels/geometry/curveNv_intersector.h +++ b/kernels/geometry/curveNv_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curve_intersector.h b/kernels/geometry/curve_intersector.h index 204958f7cc..1e8ac26125 100644 --- a/kernels/geometry/curve_intersector.h +++ b/kernels/geometry/curve_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -23,8 +23,8 @@ namespace embree typedef unsigned char Primitive; typedef CurvePrecalculations1 Precalculations; - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { assert(num == 1); RTCGeometryType ty = (RTCGeometryType)(*prim); @@ -33,8 +33,8 @@ namespace embree leafIntersector.intersect<1>(&pre,&ray,context,prim); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { assert(num == 1); RTCGeometryType ty = (RTCGeometryType)(*prim); diff --git a/kernels/geometry/curve_intersector_distance.h b/kernels/geometry/curve_intersector_distance.h index 343cc8ff28..748a9511a5 100644 --- a/kernels/geometry/curve_intersector_distance.h +++ b/kernels/geometry/curve_intersector_distance.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curve_intersector_oriented.h b/kernels/geometry/curve_intersector_oriented.h index 47531027fc..75532f5ae0 100644 --- a/kernels/geometry/curve_intersector_oriented.h +++ b/kernels/geometry/curve_intersector_oriented.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -225,7 +225,7 @@ namespace embree /* exit if convergence cannot get proven, but terminate if we are very small */ if (unlikely(!subset(K,x) && !very_small)) return false; - /* solve using newton raphson iteration of convergence is guarenteed */ + /* solve using newton raphson iteration of convergence is guaranteed */ solve_newton_raphson_loop(cu,cv,c1,dfdu,dfdv,rcp_J); return true; } diff --git a/kernels/geometry/curve_intersector_precalculations.h b/kernels/geometry/curve_intersector_precalculations.h index 6e9fc91925..de6b70be1b 100644 --- a/kernels/geometry/curve_intersector_precalculations.h +++ b/kernels/geometry/curve_intersector_precalculations.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/curve_intersector_ribbon.h b/kernels/geometry/curve_intersector_ribbon.h index a99cf99d56..c3272e99fd 100644 --- a/kernels/geometry/curve_intersector_ribbon.h +++ b/kernels/geometry/curve_intersector_ribbon.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -32,9 +32,11 @@ namespace embree __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } __forceinline float t (const size_t i) const { return vt[i]; } - __forceinline Vec3fa Ng(const size_t i) const { - return curve3D.eval_du(vu[i]); - } + __forceinline Vec3fa Ng(const size_t i) const { return curve3D.eval_du(vu[i]); } + + __forceinline Vec2vf uv() const { return Vec2vf(vu,vv); } + __forceinline vfloat t () const { return vt; } + __forceinline Vec3vf Ng() const { return (Vec3vf) curve3D.template veval_du(vu); } public: vfloat U; @@ -98,7 +100,7 @@ namespace embree const Vec3vfx up1 = nmadd(p1.w,nn1,Vec3vfx(p1)); vfloatx vu,vv,vt; - vboolx valid0 = intersect_quad_backface_culling(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt); + vboolx valid0 = intersect_quad_backface_culling(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt); if (any(valid0)) { @@ -143,7 +145,7 @@ namespace embree const Vec3vfx up1 = nmadd(p1.w,nn1,Vec3vfx(p1)); vfloatx vu,vv,vt; - vboolx valid0 = intersect_quad_backface_culling(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt); + vboolx valid0 = intersect_quad_backface_culling(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt); if (any(valid0)) { diff --git a/kernels/geometry/curve_intersector_sweep.h b/kernels/geometry/curve_intersector_sweep.h index 883cedc3d2..dba097cf30 100644 --- a/kernels/geometry/curve_intersector_sweep.h +++ b/kernels/geometry/curve_intersector_sweep.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -60,7 +60,7 @@ namespace embree const Vec3fa dir = ray.dir; const float length_ray_dir = length(dir); - /* error of curve evaluations is propertional to largest coordinate */ + /* error of curve evaluations is proportional to largest coordinate */ const BBox3ff box = curve.bounds(); const float P_err = 16.0f*float(ulp)*reduce_max(max(abs(box.lower),abs(box.upper))); @@ -137,10 +137,12 @@ namespace embree float u0, float u1, unsigned int depth, const Epilog& epilog) { #if defined(__AVX__) + enum { VSIZEX_ = 8 }; typedef vbool8 vboolx; // maximally 8-wide to work around KNL issues typedef vint8 vintx; typedef vfloat8 vfloatx; #else + enum { VSIZEX_ = 4 }; typedef vbool4 vboolx; typedef vint4 vintx; typedef vfloat4 vfloatx; @@ -192,7 +194,7 @@ namespace embree /* subdivide curve */ const float dscale = (u1-u0)*(1.0f/(3.0f*(vfloatx::size-1))); const vfloatx vu0 = lerp(u0,u1,vfloatx(step)*(1.0f/(vfloatx::size-1))); - Vec4vfx P0, dP0du; curve.veval(vu0,P0,dP0du); dP0du = dP0du * Vec4vfx(dscale); + Vec4vfx P0, dP0du; curve.template veval(vu0,P0,dP0du); dP0du = dP0du * Vec4vfx(dscale); const Vec4vfx P3 = shift_right_1(P0); const Vec4vfx dP3du = shift_right_1(dP0du); const Vec4vfx P1 = P0 + dP0du; @@ -229,9 +231,11 @@ namespace embree /* clamp and correct u parameter */ u_outer0 = clamp(u_outer0,vfloatx(0.0f),vfloatx(1.0f)); - u_outer1 = clamp(u_outer1,vfloatx(0.0f),vfloatx(1.0f)); u_outer0 = lerp(u0,u1,(vfloatx(step)+u_outer0)*(1.0f/float(vfloatx::size))); +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) + u_outer1 = clamp(u_outer1,vfloatx(0.0f),vfloatx(1.0f)); u_outer1 = lerp(u0,u1,(vfloatx(step)+u_outer1)*(1.0f/float(vfloatx::size))); +#endif /* intersect with inner cylinder */ BBox tc_inner; @@ -240,8 +244,10 @@ namespace embree /* at the unstable area we subdivide deeper */ const vboolx unstable0 = (!valid_inner) | (abs(dot(Vec3vfx(Vec3fa(ray.dir)),Ng_inner0)) < 0.3f); +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) const vboolx unstable1 = (!valid_inner) | (abs(dot(Vec3vfx(Vec3fa(ray.dir)),Ng_inner1)) < 0.3f); - +#endif + /* subtract the inner interval from the current hit interval */ BBox tp0, tp1; subtract(tp,tc_inner,tp0,tp1); @@ -263,6 +269,7 @@ namespace embree } valid1 &= tp1.lower+dt <= ray.tfar; +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) /* iterate over all second hits front to back */ const vintx termDepth1 = select(unstable1,vintx(maxDepth+1),vintx(maxDepth)); vboolx recursion_valid1 = valid1 & (depth < termDepth1); @@ -274,11 +281,16 @@ namespace embree //found = found | intersect_bezier_iterative_debug (ray,dt,curve,i,u_outer1,tp1,h0,h1,Ng_outer1,dP0du,dP3du,epilog); valid1 &= tp1.lower+dt <= ray.tfar; } +#endif /* push valid segments to stack */ recursion_valid0 &= tp0.lower+dt <= ray.tfar; +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) recursion_valid1 &= tp1.lower+dt <= ray.tfar; const vboolx recursion_valid = recursion_valid0 | recursion_valid1; +#else + const vboolx recursion_valid = recursion_valid0; +#endif if (any(recursion_valid)) { assert(sptr < stack_size); diff --git a/kernels/geometry/curve_intersector_virtual.cpp b/kernels/geometry/curve_intersector_virtual.cpp deleted file mode 100644 index c00377bf00..0000000000 --- a/kernels/geometry/curve_intersector_virtual.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "curve_intersector_virtual.h" - -namespace embree -{ - namespace isa - { - VirtualCurveIntersector* VirtualCurveIntersector4i() - { - static VirtualCurveIntersector function_local_static_prim; - function_local_static_prim.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearConeNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); - return &function_local_static_prim; - } - - VirtualCurveIntersector* VirtualCurveIntersector4v() - { - static VirtualCurveIntersector function_local_static_prim; - function_local_static_prim.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearConeNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNvIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNvIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNvIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNvIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); - return &function_local_static_prim; - } - - VirtualCurveIntersector* VirtualCurveIntersector4iMB() - { - static VirtualCurveIntersector function_local_static_prim; - function_local_static_prim.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiMBIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_DISC_POINT] = DiscNiMBIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiMBIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearConeNiMBIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiMBIntersectors<4>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiMBIntersectors(); - return &function_local_static_prim; - } - } -} diff --git a/kernels/geometry/curve_intersector_virtual.h b/kernels/geometry/curve_intersector_virtual.h index 3e841c268f..cffa8e46ad 100644 --- a/kernels/geometry/curve_intersector_virtual.h +++ b/kernels/geometry/curve_intersector_virtual.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -22,6 +22,7 @@ #include "linei_intersector.h" #include "roundlinei_intersector.h" +#include "conelinei_intersector.h" #include "curveNi_intersector.h" #include "curveNv_intersector.h" @@ -96,8 +97,8 @@ namespace embree typedef unsigned char Primitive; typedef CurvePrecalculations1 Precalculations; - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { assert(num == 1); RTCGeometryType ty = (RTCGeometryType)(*prim); @@ -106,8 +107,8 @@ namespace embree leafIntersector.intersect<1>(&pre,&ray,context,prim); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { assert(num == 1); RTCGeometryType ty = (RTCGeometryType)(*prim); @@ -151,8 +152,8 @@ namespace embree return valid_o; } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { assert(num == 1); RTCGeometryType ty = (RTCGeometryType)(*prim); @@ -161,8 +162,8 @@ namespace embree leafIntersector.intersect(&pre,&ray,k,context,prim); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { assert(num == 1); RTCGeometryType ty = (RTCGeometryType)(*prim); @@ -172,21 +173,59 @@ namespace embree } }; + template + static VirtualCurveIntersector::Intersectors LinearRoundConeNiIntersectors() + { + VirtualCurveIntersector::Intersectors intersectors; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiIntersectorK::occluded; +#if defined(__AVX__) + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiIntersectorK::occluded; +#endif +#if defined(__AVX512F__) + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiIntersectorK::occluded; +#endif + return intersectors; + } + template static VirtualCurveIntersector::Intersectors LinearConeNiIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &ConeCurveMiIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &ConeCurveMiIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &ConeCurveMiIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &ConeCurveMiIntersectorK::occluded; +#if defined(__AVX__) + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&ConeCurveMiIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &ConeCurveMiIntersectorK::occluded; +#endif +#if defined(__AVX512F__) + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&ConeCurveMiIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &ConeCurveMiIntersectorK::occluded; +#endif + return intersectors; + } + + template + static VirtualCurveIntersector::Intersectors LinearRoundConeNiMBIntersectors() + { + VirtualCurveIntersector::Intersectors intersectors; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiMBIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiMBIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiMBIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiMBIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiMBIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiMBIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiMBIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiMBIntersectorK::occluded; #endif return intersectors; } @@ -195,17 +234,17 @@ namespace embree static VirtualCurveIntersector::Intersectors LinearConeNiMBIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &RoundLinearCurveMiMBIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &RoundLinearCurveMiMBIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &RoundLinearCurveMiMBIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &RoundLinearCurveMiMBIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &ConeCurveMiMBIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &ConeCurveMiMBIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &ConeCurveMiMBIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &ConeCurveMiMBIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&RoundLinearCurveMiMBIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &RoundLinearCurveMiMBIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&ConeCurveMiMBIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &ConeCurveMiMBIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&RoundLinearCurveMiMBIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &RoundLinearCurveMiMBIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&ConeCurveMiMBIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &ConeCurveMiMBIntersectorK::occluded; #endif return intersectors; } @@ -215,17 +254,17 @@ namespace embree static VirtualCurveIntersector::Intersectors LinearRibbonNiIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiIntersectorK::occluded; #endif return intersectors; } @@ -234,17 +273,17 @@ namespace embree static VirtualCurveIntersector::Intersectors LinearRibbonNiMBIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiMBIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiMBIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiMBIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiMBIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &FlatLinearCurveMiMBIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &FlatLinearCurveMiMBIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &FlatLinearCurveMiMBIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &FlatLinearCurveMiMBIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiMBIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiMBIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&FlatLinearCurveMiMBIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &FlatLinearCurveMiMBIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiMBIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiMBIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&FlatLinearCurveMiMBIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &FlatLinearCurveMiMBIntersectorK::occluded; #endif return intersectors; } @@ -253,17 +292,17 @@ namespace embree static VirtualCurveIntersector::Intersectors SphereNiIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiIntersectorK::occluded; #endif return intersectors; } @@ -272,17 +311,17 @@ namespace embree static VirtualCurveIntersector::Intersectors SphereNiMBIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiMBIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiMBIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiMBIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiMBIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &SphereMiMBIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &SphereMiMBIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &SphereMiMBIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &SphereMiMBIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiMBIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiMBIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&SphereMiMBIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &SphereMiMBIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiMBIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiMBIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&SphereMiMBIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &SphereMiMBIntersectorK::occluded; #endif return intersectors; } @@ -291,17 +330,17 @@ namespace embree static VirtualCurveIntersector::Intersectors DiscNiIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiIntersectorK::occluded; #endif return intersectors; } @@ -310,17 +349,17 @@ namespace embree static VirtualCurveIntersector::Intersectors DiscNiMBIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiMBIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiMBIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiMBIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiMBIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &DiscMiMBIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &DiscMiMBIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &DiscMiMBIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &DiscMiMBIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiMBIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiMBIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&DiscMiMBIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &DiscMiMBIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiMBIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiMBIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&DiscMiMBIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &DiscMiMBIntersectorK::occluded; #endif return intersectors; } @@ -329,17 +368,17 @@ namespace embree static VirtualCurveIntersector::Intersectors OrientedDiscNiIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiIntersectorK::occluded; #endif return intersectors; } @@ -348,17 +387,17 @@ namespace embree static VirtualCurveIntersector::Intersectors OrientedDiscNiMBIntersectors() { VirtualCurveIntersector::Intersectors intersectors; - intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiMBIntersector1::intersect; - intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiMBIntersector1::occluded; - intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiMBIntersectorK::intersect; - intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiMBIntersectorK::occluded; + intersectors.intersect1 = (VirtualCurveIntersector::Intersect1Ty) &OrientedDiscMiMBIntersector1::intersect; + intersectors.occluded1 = (VirtualCurveIntersector::Occluded1Ty) &OrientedDiscMiMBIntersector1::occluded; + intersectors.intersect4 = (VirtualCurveIntersector::Intersect4Ty) &OrientedDiscMiMBIntersectorK::intersect; + intersectors.occluded4 = (VirtualCurveIntersector::Occluded4Ty) &OrientedDiscMiMBIntersectorK::occluded; #if defined(__AVX__) - intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiMBIntersectorK::intersect; - intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiMBIntersectorK::occluded; + intersectors.intersect8 = (VirtualCurveIntersector::Intersect8Ty)&OrientedDiscMiMBIntersectorK::intersect; + intersectors.occluded8 = (VirtualCurveIntersector::Occluded8Ty) &OrientedDiscMiMBIntersectorK::occluded; #endif #if defined(__AVX512F__) - intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiMBIntersectorK::intersect; - intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiMBIntersectorK::occluded; + intersectors.intersect16 = (VirtualCurveIntersector::Intersect16Ty)&OrientedDiscMiMBIntersectorK::intersect; + intersectors.occluded16 = (VirtualCurveIntersector::Occluded16Ty) &OrientedDiscMiMBIntersectorK::occluded; #endif return intersectors; } diff --git a/kernels/geometry/curve_intersector_virtual2.cpp b/kernels/geometry/curve_intersector_virtual2.cpp deleted file mode 100644 index 01914a2ddb..0000000000 --- a/kernels/geometry/curve_intersector_virtual2.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "curve_intersector_virtual.h" -#include "intersector_epilog.h" - -#include "../subdiv/bezier_curve.h" -#include "../subdiv/bspline_curve.h" -#include "../subdiv/hermite_curve.h" -#include "../subdiv/catmullrom_curve.h" - -#include "spherei_intersector.h" -#include "disci_intersector.h" - -#include "linei_intersector.h" - -#include "curveNi_intersector.h" -#include "curveNv_intersector.h" -#include "curveNi_mb_intersector.h" - -#include "curve_intersector_distance.h" -#include "curve_intersector_ribbon.h" -#include "curve_intersector_oriented.h" -#include "curve_intersector_sweep.h" - -namespace embree -{ - namespace isa - { -#if defined (__AVX__) - - VirtualCurveIntersector* VirtualCurveIntersector8i() - { - static VirtualCurveIntersector function_local_static_prim; - function_local_static_prim.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearConeNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); - return &function_local_static_prim; - } - - VirtualCurveIntersector* VirtualCurveIntersector8v() - { - static VirtualCurveIntersector function_local_static_prim; - function_local_static_prim.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearConeNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNvIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNvIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNvIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNvIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); - return &function_local_static_prim; - } - - VirtualCurveIntersector* VirtualCurveIntersector8iMB() - { - static VirtualCurveIntersector function_local_static_prim; - function_local_static_prim.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiMBIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_DISC_POINT] = DiscNiMBIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiMBIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearConeNiMBIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiMBIntersectors<8>(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiMBIntersectors (); - function_local_static_prim.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiMBIntersectors(); - function_local_static_prim.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiMBIntersectors(); - return &function_local_static_prim; - } - -#endif - } -} diff --git a/kernels/geometry/curve_intersector_virtual_4i.cpp b/kernels/geometry/curve_intersector_virtual_4i.cpp new file mode 100644 index 0000000000..02cda4e3ea --- /dev/null +++ b/kernels/geometry/curve_intersector_virtual_4i.cpp @@ -0,0 +1,38 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "curve_intersector_virtual.h" + +namespace embree +{ + namespace isa + { + VirtualCurveIntersector* VirtualCurveIntersector4i() + { + static VirtualCurveIntersector function_local_static_prim = []() + { + VirtualCurveIntersector intersector; + intersector.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_CONE_LINEAR_CURVE ] = LinearConeNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearRoundConeNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); + return intersector; + }(); + return &function_local_static_prim; + } + } +} diff --git a/kernels/geometry/curve_intersector_virtual_4i_mb.cpp b/kernels/geometry/curve_intersector_virtual_4i_mb.cpp new file mode 100644 index 0000000000..e65b744197 --- /dev/null +++ b/kernels/geometry/curve_intersector_virtual_4i_mb.cpp @@ -0,0 +1,38 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "curve_intersector_virtual.h" + +namespace embree +{ + namespace isa + { + VirtualCurveIntersector* VirtualCurveIntersector4iMB() + { + static VirtualCurveIntersector function_local_static_prim = []() + { + VirtualCurveIntersector intersector; + intersector.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiMBIntersectors<4>(); + intersector.vtbl[Geometry::GTY_DISC_POINT] = DiscNiMBIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiMBIntersectors<4>(); + intersector.vtbl[Geometry::GTY_CONE_LINEAR_CURVE ] = LinearConeNiMBIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearRoundConeNiMBIntersectors<4>(); + intersector.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiMBIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiMBIntersectors(); + return intersector; + }(); + return &function_local_static_prim; + } + } +} diff --git a/kernels/geometry/curve_intersector_virtual_4v.cpp b/kernels/geometry/curve_intersector_virtual_4v.cpp new file mode 100644 index 0000000000..0707711fa7 --- /dev/null +++ b/kernels/geometry/curve_intersector_virtual_4v.cpp @@ -0,0 +1,38 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "curve_intersector_virtual.h" + +namespace embree +{ + namespace isa + { + VirtualCurveIntersector* VirtualCurveIntersector4v() + { + static VirtualCurveIntersector function_local_static_prim = []() + { + VirtualCurveIntersector intersector; + intersector.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_CONE_LINEAR_CURVE ] = LinearConeNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearRoundConeNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<4>(); + intersector.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNvIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNvIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNvIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNvIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); + return intersector; + }(); + return &function_local_static_prim; + } + } +} diff --git a/kernels/geometry/curve_intersector_virtual_8i.cpp b/kernels/geometry/curve_intersector_virtual_8i.cpp new file mode 100644 index 0000000000..f8e5a8d986 --- /dev/null +++ b/kernels/geometry/curve_intersector_virtual_8i.cpp @@ -0,0 +1,62 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "curve_intersector_virtual.h" +#include "intersector_epilog.h" + +#include "../subdiv/bezier_curve.h" +#include "../subdiv/bspline_curve.h" +#include "../subdiv/hermite_curve.h" +#include "../subdiv/catmullrom_curve.h" + +#include "spherei_intersector.h" +#include "disci_intersector.h" + +#include "linei_intersector.h" + +#include "curveNi_intersector.h" +#include "curveNv_intersector.h" +#include "curveNi_mb_intersector.h" + +#include "curve_intersector_distance.h" +#include "curve_intersector_ribbon.h" +#include "curve_intersector_oriented.h" +#include "curve_intersector_sweep.h" + +namespace embree +{ + namespace isa + { +#if defined (__AVX__) + + VirtualCurveIntersector* VirtualCurveIntersector8i() + { + static VirtualCurveIntersector function_local_static_prim = []() + { + VirtualCurveIntersector intersector; + intersector.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_CONE_LINEAR_CURVE ] = LinearConeNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearRoundConeNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); + return intersector; + }(); + return &function_local_static_prim; + } + +#endif + } +} diff --git a/kernels/geometry/curve_intersector_virtual_8i_mb.cpp b/kernels/geometry/curve_intersector_virtual_8i_mb.cpp new file mode 100644 index 0000000000..b6d78b038f --- /dev/null +++ b/kernels/geometry/curve_intersector_virtual_8i_mb.cpp @@ -0,0 +1,62 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "curve_intersector_virtual.h" +#include "intersector_epilog.h" + +#include "../subdiv/bezier_curve.h" +#include "../subdiv/bspline_curve.h" +#include "../subdiv/hermite_curve.h" +#include "../subdiv/catmullrom_curve.h" + +#include "spherei_intersector.h" +#include "disci_intersector.h" + +#include "linei_intersector.h" + +#include "curveNi_intersector.h" +#include "curveNv_intersector.h" +#include "curveNi_mb_intersector.h" + +#include "curve_intersector_distance.h" +#include "curve_intersector_ribbon.h" +#include "curve_intersector_oriented.h" +#include "curve_intersector_sweep.h" + +namespace embree +{ + namespace isa + { +#if defined (__AVX__) + + VirtualCurveIntersector* VirtualCurveIntersector8iMB() + { + static VirtualCurveIntersector function_local_static_prim = []() + { + VirtualCurveIntersector intersector; + intersector.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiMBIntersectors<8>(); + intersector.vtbl[Geometry::GTY_DISC_POINT] = DiscNiMBIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiMBIntersectors<8>(); + intersector.vtbl[Geometry::GTY_CONE_LINEAR_CURVE ] = LinearConeNiMBIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearRoundConeNiMBIntersectors<8>(); + intersector.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiMBIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiMBIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiMBIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiMBIntersectors(); + return intersector; + }(); + return &function_local_static_prim; + } + +#endif + } +} diff --git a/kernels/geometry/curve_intersector_virtual_8v.cpp b/kernels/geometry/curve_intersector_virtual_8v.cpp new file mode 100644 index 0000000000..8e5f4894c5 --- /dev/null +++ b/kernels/geometry/curve_intersector_virtual_8v.cpp @@ -0,0 +1,62 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "curve_intersector_virtual.h" +#include "intersector_epilog.h" + +#include "../subdiv/bezier_curve.h" +#include "../subdiv/bspline_curve.h" +#include "../subdiv/hermite_curve.h" +#include "../subdiv/catmullrom_curve.h" + +#include "spherei_intersector.h" +#include "disci_intersector.h" + +#include "linei_intersector.h" + +#include "curveNi_intersector.h" +#include "curveNv_intersector.h" +#include "curveNi_mb_intersector.h" + +#include "curve_intersector_distance.h" +#include "curve_intersector_ribbon.h" +#include "curve_intersector_oriented.h" +#include "curve_intersector_sweep.h" + +namespace embree +{ + namespace isa + { +#if defined (__AVX__) + + VirtualCurveIntersector* VirtualCurveIntersector8v() + { + static VirtualCurveIntersector function_local_static_prim = []() + { + VirtualCurveIntersector intersector; + intersector.vtbl[Geometry::GTY_SPHERE_POINT] = SphereNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_DISC_POINT] = DiscNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ORIENTED_DISC_POINT] = OrientedDiscNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_CONE_LINEAR_CURVE ] = LinearConeNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ROUND_LINEAR_CURVE ] = LinearRoundConeNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_FLAT_LINEAR_CURVE ] = LinearRibbonNiIntersectors<8>(); + intersector.vtbl[Geometry::GTY_ROUND_BEZIER_CURVE] = CurveNvIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BEZIER_CURVE ] = RibbonNvIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BEZIER_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_BSPLINE_CURVE] = CurveNvIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_BSPLINE_CURVE ] = RibbonNvIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_BSPLINE_CURVE] = OrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_HERMITE_CURVE] = HermiteCurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_HERMITE_CURVE ] = HermiteRibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_HERMITE_CURVE] = HermiteOrientedCurveNiIntersectors(); + intersector.vtbl[Geometry::GTY_ROUND_CATMULL_ROM_CURVE] = CurveNiIntersectors (); + intersector.vtbl[Geometry::GTY_FLAT_CATMULL_ROM_CURVE ] = RibbonNiIntersectors(); + intersector.vtbl[Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE] = OrientedCurveNiIntersectors(); + return intersector; + }(); + return &function_local_static_prim; + } + +#endif + } +} diff --git a/kernels/geometry/cylinder.h b/kernels/geometry/cylinder.h index 39a582864c..dab02989ce 100644 --- a/kernels/geometry/cylinder.h +++ b/kernels/geometry/cylinder.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/disc_intersector.h b/kernels/geometry/disc_intersector.h index e8305780e5..816c066899 100644 --- a/kernels/geometry/disc_intersector.h +++ b/kernels/geometry/disc_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -64,7 +64,7 @@ namespace embree const Vec3vf ray_dir(ray.dir.x, ray.dir.y, ray.dir.z); const vfloat rd2 = rcp(dot(ray_dir, ray_dir)); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); const Vec3vf center = v0.xyz(); const vfloat radius = v0.w; @@ -101,7 +101,7 @@ namespace embree vbool valid = valid_i; const Vec3vf ray_org(ray.org.x, ray.org.y, ray.org.z); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); const Vec3vf center = v0.xyz(); const vfloat radius = v0.w; @@ -148,7 +148,7 @@ namespace embree const Vec3vf ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]); const vfloat rd2 = rcp(dot(ray_dir, ray_dir)); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); const Vec3vf center = v0.xyz(); const vfloat radius = v0.w; @@ -187,7 +187,7 @@ namespace embree const Vec3vf ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); const Vec3vf ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); const Vec3vf center = v0.xyz(); const vfloat radius = v0.w; diff --git a/kernels/geometry/disci_intersector.h b/kernels/geometry/disci_intersector.h index e1dc3aa98e..bb9d396f6e 100644 --- a/kernels/geometry/disci_intersector.h +++ b/kernels/geometry/disci_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,7 +11,7 @@ namespace embree { namespace isa { - template + template struct DiscMiIntersector1 { typedef PointMi Primitive; @@ -25,9 +25,9 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom); - const vbool valid = Disc.template valid(); - DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded(const Precalculations& pre, @@ -38,13 +38,13 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom); - const vbool valid = Disc.template valid(); - return DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + return DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } }; - template + template struct DiscMiMBIntersector1 { typedef PointMi Primitive; @@ -58,9 +58,9 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom, ray.time()); - const vbool valid = Disc.template valid(); - DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded(const Precalculations& pre, @@ -71,13 +71,13 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom, ray.time()); - const vbool valid = Disc.template valid(); - return DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + return DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } }; - template + template struct DiscMiIntersectorK { typedef PointMi Primitive; @@ -89,10 +89,10 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom); - const vbool valid = Disc.template valid(); - DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded( @@ -101,14 +101,14 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom); - const vbool valid = Disc.template valid(); - return DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + return DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } }; - template + template struct DiscMiMBIntersectorK { typedef PointMi Primitive; @@ -120,10 +120,10 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom, ray.time()[k]); - const vbool valid = Disc.template valid(); - DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded( @@ -132,13 +132,13 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Disc.gather(v0, geom, ray.time()[k]); - const vbool valid = Disc.template valid(); - return DiscIntersectorK::intersect( - valid, ray, k, context, geom, pre, v0, Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + return DiscIntersectorK::intersect( + valid, ray, k, context, geom, pre, v0, Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } }; - template + template struct OrientedDiscMiIntersector1 { typedef PointMi Primitive; @@ -153,9 +153,9 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom); - const vbool valid = Disc.template valid(); - DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded(const Precalculations& pre, @@ -167,13 +167,13 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom); - const vbool valid = Disc.template valid(); - return DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + return DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } }; - template + template struct OrientedDiscMiMBIntersector1 { typedef PointMi Primitive; @@ -188,9 +188,9 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom, ray.time()); - const vbool valid = Disc.template valid(); - DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, n0, Intersect1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded(const Precalculations& pre, @@ -202,13 +202,13 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom, ray.time()); - const vbool valid = Disc.template valid(); - return DiscIntersector1::intersect( - valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); + const vbool valid = Disc.valid(); + return DiscIntersector1::intersect( + valid, ray, context, geom, pre, v0, n0, Occluded1EpilogM(ray, context, Disc.geomID(), Disc.primID())); } }; - template + template struct OrientedDiscMiIntersectorK { typedef PointMi Primitive; @@ -221,10 +221,10 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom); - const vbool valid = Disc.template valid(); - DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, n0, - Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded( @@ -234,14 +234,14 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom); - const vbool valid = Disc.template valid(); - return DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + return DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, n0, - Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } }; - template + template struct OrientedDiscMiMBIntersectorK { typedef PointMi Primitive; @@ -254,10 +254,10 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom, ray.time()[k]); - const vbool valid = Disc.template valid(); - DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, n0, - Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Intersect1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } static __forceinline bool occluded( @@ -267,10 +267,10 @@ namespace embree const Points* geom = context->scene->get(Disc.geomID()); Vec4vf v0; Vec3vf n0; Disc.gather(v0, n0, geom, ray.time()[k]); - const vbool valid = Disc.template valid(); - return DiscIntersectorK::intersect( + const vbool valid = Disc.valid(); + return DiscIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, n0, - Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); + Occluded1KEpilogM(ray, k, context, Disc.geomID(), Disc.primID())); } }; } // namespace isa diff --git a/kernels/geometry/filter.h b/kernels/geometry/filter.h index 4cdf7a395a..d64320bf78 100644 --- a/kernels/geometry/filter.h +++ b/kernels/geometry/filter.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -51,20 +51,11 @@ namespace embree __forceinline void reportIntersection1(IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args) { #if defined(EMBREE_FILTER_FUNCTION) - IntersectContext* MAYBE_UNUSED context = args->internal_context; - const Geometry* const geometry = args->geometry; - if (geometry->intersectionFilterN) { - assert(context->scene->hasGeometryFilterFunction()); - geometry->intersectionFilterN(filter_args); - } + if (args->geometry->intersectionFilterN) + args->geometry->intersectionFilterN(filter_args); - //if (args->valid[0] == 0) - // return; - - if (context->user->filter) { - assert(context->scene->hasContextFilterFunction()); - context->user->filter(filter_args); - } + if (args->context->filter) + args->context->filter(filter_args); #endif } @@ -105,20 +96,11 @@ namespace embree __forceinline void reportOcclusion1(OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args) { #if defined(EMBREE_FILTER_FUNCTION) - IntersectContext* MAYBE_UNUSED context = args->internal_context; - const Geometry* const geometry = args->geometry; - if (geometry->occlusionFilterN) { - assert(context->scene->hasGeometryFilterFunction()); - geometry->occlusionFilterN(filter_args); - } - - //if (args->valid[0] == 0) - // return false; + if (args->geometry->occlusionFilterN) + args->geometry->occlusionFilterN(filter_args); - if (context->user->filter) { - assert(context->scene->hasContextFilterFunction()); - context->user->filter(filter_args); - } + if (args->context->filter) + args->context->filter(filter_args); #endif } diff --git a/kernels/geometry/grid_intersector.h b/kernels/geometry/grid_intersector.h index 46a0af0827..9c59cef119 100644 --- a/kernels/geometry/grid_intersector.h +++ b/kernels/geometry/grid_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/grid_soa.cpp b/kernels/geometry/grid_soa.cpp index c590dfa34f..615070be9d 100644 --- a/kernels/geometry/grid_soa.cpp +++ b/kernels/geometry/grid_soa.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "grid_soa.h" diff --git a/kernels/geometry/grid_soa.h b/kernels/geometry/grid_soa.h index 02edbbed5e..cea90aedf6 100644 --- a/kernels/geometry/grid_soa.h +++ b/kernels/geometry/grid_soa.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -41,7 +41,7 @@ namespace embree } const size_t gridBytes = 4*size_t(width)*size_t(height)*sizeof(float); size_t rootBytes = time_steps*sizeof(BVH4::NodeRef); -#if !defined(__X86_64__) +#if !defined(__64BIT__) rootBytes += 4; // We read 2 elements behind the grid. As we store at least 8 root bytes after the grid we are fine in 64 bit mode. But in 32 bit mode we have to do additional padding. #endif void* data = alloc(offsetof(GridSOA,data)+bvhBytes+time_steps*gridBytes+rootBytes); @@ -132,7 +132,7 @@ namespace embree __forceinline MapUV(const float* const grid_uv, size_t line_offset, const size_t lines) : grid_uv(grid_uv), line_offset(line_offset), lines(lines) {} - __forceinline void operator() (vfloat& u, vfloat& v) const { + __forceinline void operator() (vfloat& u, vfloat& v, Vec3& Ng) const { const Vec3 tri_v012_uv = Loader::gather(grid_uv,line_offset,lines); const Vec2 uv0 = GridSOA::decodeUV(tri_v012_uv[0]); const Vec2 uv1 = GridSOA::decodeUV(tri_v012_uv[1]); @@ -253,7 +253,7 @@ namespace embree public: BVH4::NodeRef troot; -#if !defined(__X86_64__) +#if !defined(__64BIT__) unsigned align1; #endif unsigned time_steps; diff --git a/kernels/geometry/grid_soa_intersector1.h b/kernels/geometry/grid_soa_intersector1.h index 2ed922a5ae..8fbf0d4bdf 100644 --- a/kernels/geometry/grid_soa_intersector1.h +++ b/kernels/geometry/grid_soa_intersector1.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/grid_soa_intersector_packet.h b/kernels/geometry/grid_soa_intersector_packet.h index 41d66e1e28..14cacab5fe 100644 --- a/kernels/geometry/grid_soa_intersector_packet.h +++ b/kernels/geometry/grid_soa_intersector_packet.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -20,7 +20,7 @@ namespace embree __forceinline MapUV0(const float* const grid_uv, size_t ofs00, size_t ofs01, size_t ofs10, size_t ofs11) : grid_uv(grid_uv), ofs00(ofs00), ofs01(ofs01), ofs10(ofs10), ofs11(ofs11) {} - __forceinline void operator() (vfloat& u, vfloat& v) const { + __forceinline void operator() (vfloat& u, vfloat& v, Vec3vf& Ng) const { const vfloat uv00(grid_uv[ofs00]); const vfloat uv01(grid_uv[ofs01]); const vfloat uv10(grid_uv[ofs10]); @@ -42,7 +42,7 @@ namespace embree __forceinline MapUV1(const float* const grid_uv, size_t ofs00, size_t ofs01, size_t ofs10, size_t ofs11) : grid_uv(grid_uv), ofs00(ofs00), ofs01(ofs01), ofs10(ofs10), ofs11(ofs11) {} - __forceinline void operator() (vfloat& u, vfloat& v) const { + __forceinline void operator() (vfloat& u, vfloat& v, Vec3vf& Ng) const { const vfloat uv00(grid_uv[ofs00]); const vfloat uv01(grid_uv[ofs01]); const vfloat uv10(grid_uv[ofs10]); @@ -222,7 +222,7 @@ namespace embree static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node) { vfloat vftime; - vint vitime = getTimeSegment(ray.time(), vfloat((float)(pre.grid->time_steps-1)), vftime); + vint vitime = getTimeSegment(ray.time(), vfloat((float)(pre.grid->time_steps-1)), vftime); vbool valid1 = valid_i; while (any(valid1)) { @@ -282,7 +282,7 @@ namespace embree static __forceinline vbool occluded(const vbool& valid_i, Precalculations& pre, RayK& ray, IntersectContext* context, const Primitive* prim, size_t& lazy_node) { vfloat vftime; - vint vitime = getTimeSegment(ray.time(), vfloat((float)(pre.grid->time_steps-1)), vftime); + vint vitime = getTimeSegment(ray.time(), vfloat((float)(pre.grid->time_steps-1)), vftime); vbool valid_o = valid_i; vbool valid1 = valid_i; diff --git a/kernels/geometry/instance.h b/kernels/geometry/instance.h index 883d1d7f63..7c0e7e0f49 100644 --- a/kernels/geometry/instance.h +++ b/kernels/geometry/instance.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -66,6 +66,11 @@ namespace embree return instance->linearBounds(0,time_range); } + /* Updates the primitive */ + __forceinline BBox3fa update(Instance* instance) { + return instance->bounds(0); + } + public: const Instance* instance; const unsigned int instID_ = std::numeric_limits::max (); diff --git a/kernels/geometry/instance_intersector.cpp b/kernels/geometry/instance_intersector.cpp index ad1ff440eb..0534d09fa6 100644 --- a/kernels/geometry/instance_intersector.cpp +++ b/kernels/geometry/instance_intersector.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "instance_intersector.h" @@ -340,7 +340,7 @@ namespace embree return occluded; } -#if defined(__SSE__) +#if defined(__SSE__) || defined(__ARM_NEON) template struct InstanceIntersectorK<4>; template struct InstanceIntersectorKMB<4>; #endif diff --git a/kernels/geometry/instance_intersector.h b/kernels/geometry/instance_intersector.h index 91731a39c5..28a7b728e5 100644 --- a/kernels/geometry/instance_intersector.h +++ b/kernels/geometry/instance_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/intersector_epilog.h b/kernels/geometry/intersector_epilog.h index 0df49dd6e9..7bf134cc54 100644 --- a/kernels/geometry/intersector_epilog.h +++ b/kernels/geometry/intersector_epilog.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -13,7 +13,7 @@ namespace embree { template struct UVIdentity { - __forceinline void operator() (vfloat& u, vfloat& v) const {} + __forceinline void operator() (vfloat& u, vfloat& v, Vec3vf& Ng) const {} }; @@ -63,7 +63,7 @@ namespace embree ray.v = hit.v; ray.primID = primID; ray.geomID = geomID; - instance_id_stack::copy(context->user->instID, ray.instID); + instance_id_stack::copy_UU(context->user->instID, ray.instID); return true; } }; @@ -162,7 +162,7 @@ namespace embree ray.v[k] = hit.v; ray.primID[k] = primID; ray.geomID[k] = geomID; - instance_id_stack::copy*, const size_t&>(context->user->instID, ray.instID, k); + instance_id_stack::copy_UV(context->user->instID, ray.instID, k); return true; } }; @@ -211,7 +211,7 @@ namespace embree } }; - template + template struct Intersect1EpilogM { RayHit& ray; @@ -226,11 +226,10 @@ namespace embree : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {} template - __forceinline bool operator() (const vbool& valid_i, Hit& hit) const + __forceinline bool operator() (const vbool& valid_i, Hit& hit) const { Scene* scene MAYBE_UNUSED = context->scene; - vbool valid = valid_i; - if (Mx > M) valid &= (1< valid = valid_i; hit.finalize(); size_t i = select_min(valid,hit.vt); unsigned int geomID = geomIDs[i]; @@ -287,94 +286,13 @@ namespace embree ray.v = uv.y; ray.primID = primIDs[i]; ray.geomID = geomID; - instance_id_stack::copy(context->user->instID, ray.instID); + instance_id_stack::copy_UU(context->user->instID, ray.instID); return true; } }; -#if 0 && defined(__AVX512F__) // do not enable, this reduced frequency for BVH4 template - struct Intersect1EpilogM - { - static const size_t Mx = 16; - RayHit& ray; - IntersectContext* context; - const vuint& geomIDs; - const vuint& primIDs; - - __forceinline Intersect1EpilogM(RayHit& ray, - IntersectContext* context, - const vuint& geomIDs, - const vuint& primIDs) - : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {} - - template - __forceinline bool operator() (const vbool& valid_i, Hit& hit) const - { - Scene* MAYBE_UNUSED scene = context->scene; - vbool valid = valid_i; - if (Mx > M) valid &= (1<get(geomID); - -#if defined(EMBREE_RAY_MASK) - /* goto next hit if mask test fails */ - if ((geometry->mask & ray.mask) == 0) { - clear(valid,i); - continue; - } -#endif - -#if defined(EMBREE_FILTER_FUNCTION) - /* call intersection filter function */ - if (filter) { - if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) { - const Vec2f uv = hit.uv(i); - HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i)); - const float old_t = ray.tfar; - ray.tfar = hit.t(i); - const bool found = runIntersectionFilter1(geometry,ray,context,h); - if (!found) ray.tfar = old_t; - foundhit |= found; - clear(valid,i); - valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value - continue; - } - } -#endif - break; - } -#endif - - vbool finalMask(((unsigned int)1 << i)); - ray.update(finalMask,hit.vt,hit.vu,hit.vv,hit.vNg.x,hit.vNg.y,hit.vNg.z,geomID,primIDs); - instance_id_stack::foreach([&](unsigned level) - { - ray.instID[level] = context->user->instID[level]; - return (context->user->instID[level] != RTC_INVALID_GEOMETRY_ID); - }); - return true; - - } - }; -#endif - - template struct Occluded1EpilogM { Ray& ray; @@ -389,7 +307,7 @@ namespace embree : ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {} template - __forceinline bool operator() (const vbool& valid_i, Hit& hit) const + __forceinline bool operator() (const vbool& valid_i, Hit& hit) const { Scene* scene MAYBE_UNUSED = context->scene; /* intersection filter test */ @@ -397,8 +315,7 @@ namespace embree if (unlikely(filter)) hit.finalize(); /* called only once */ - vbool valid = valid_i; - if (Mx > M) valid &= (1< valid = valid_i; size_t m=movemask(valid); goto entry; while (true) @@ -506,7 +423,7 @@ namespace embree ray.v = uv.y; ray.primID = primID; ray.geomID = geomID; - instance_id_stack::copy(context->user->instID, ray.instID); + instance_id_stack::copy_UU(context->user->instID, ray.instID); return true; } }; @@ -616,7 +533,7 @@ namespace embree vfloat::store(valid,&ray.v,v); vuint::store(valid,&ray.primID,primID); vuint::store(valid,&ray.geomID,geomID); - instance_id_stack::copy*, const vbool&>(context->user->instID, ray.instID, valid); + instance_id_stack::copy_UV(context->user->instID, ray.instID, valid); return valid; } }; @@ -646,8 +563,8 @@ namespace embree /* ray masking test */ Scene* scene MAYBE_UNUSED = context->scene; - const unsigned int geomID = geomIDs[i]; - const unsigned int primID = primIDs[i]; + const unsigned int geomID MAYBE_UNUSED = geomIDs[i]; + const unsigned int primID MAYBE_UNUSED = primIDs[i]; Geometry* geometry MAYBE_UNUSED = scene->get(geomID); #if defined(EMBREE_RAY_MASK) valid &= (geometry->mask & ray.mask) != 0; @@ -731,8 +648,7 @@ namespace embree vfloat::store(valid,&ray.v,v); vuint::store(valid,&ray.primID,primID); vuint::store(valid,&ray.geomID,geomID); - instance_id_stack::copy*, const vbool&>(context->user->instID, ray.instID, valid); - + instance_id_stack::copy_UV(context->user->instID, ray.instID, valid); return valid; } }; @@ -788,7 +704,7 @@ namespace embree } }; - template + template struct Intersect1KEpilogM { RayHitK& ray; @@ -804,12 +720,11 @@ namespace embree : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {} template - __forceinline bool operator() (const vbool& valid_i, Hit& hit) const + __forceinline bool operator() (const vbool& valid_i, Hit& hit) const { Scene* scene MAYBE_UNUSED = context->scene; - vbool valid = valid_i; + vbool valid = valid_i; hit.finalize(); - if (Mx > M) valid &= (1<(hit.vNg.x),vfloat(hit.vNg.y),vfloat(hit.vNg.z),geomID,vuint(primIDs)); -#else const Vec2f uv = hit.uv(i); ray.tfar[k] = hit.t(i); ray.Ng.x[k] = hit.vNg.x[i]; @@ -870,13 +782,12 @@ namespace embree ray.v[k] = uv.y; ray.primID[k] = primIDs[i]; ray.geomID[k] = geomID; - instance_id_stack::copy*, const size_t&>(context->user->instID, ray.instID, k); -#endif + instance_id_stack::copy_UV(context->user->instID, ray.instID, k); return true; } }; - template + template struct Occluded1KEpilogM { RayK& ray; @@ -892,7 +803,7 @@ namespace embree : ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {} template - __forceinline bool operator() (const vbool& valid_i, Hit& hit) const + __forceinline bool operator() (const vbool& valid_i, Hit& hit) const { Scene* scene MAYBE_UNUSED = context->scene; @@ -901,8 +812,7 @@ namespace embree if (unlikely(filter)) hit.finalize(); /* called only once */ - vbool valid = valid_i; - if (Mx > M) valid &= (1< valid = valid_i; size_t m=movemask(valid); goto entry; while (true) @@ -1002,10 +912,6 @@ namespace embree #endif /* update hit information */ -#if 0 && defined(__AVX512F__) // do not enable, this reduced frequency for BVH4 - const Vec3fa Ng = hit.Ng(i); - ray.updateK(i,k,hit.vt,hit.vu,hit.vv,vfloat(Ng.x),vfloat(Ng.y),vfloat(Ng.z),geomID,vuint(primID)); -#else const Vec2f uv = hit.uv(i); const Vec3fa Ng = hit.Ng(i); ray.tfar[k] = hit.t(i); @@ -1016,8 +922,7 @@ namespace embree ray.v[k] = uv.y; ray.primID[k] = primID; ray.geomID[k] = geomID; - instance_id_stack::copy*, const size_t&>(context->user->instID, ray.instID, k); -#endif + instance_id_stack::copy_UV(context->user->instID, ray.instID, k); return true; } }; diff --git a/kernels/geometry/intersector_iterators.h b/kernels/geometry/intersector_iterators.h index 5c1ba5cb61..9cac1cd25c 100644 --- a/kernels/geometry/intersector_iterators.h +++ b/kernels/geometry/intersector_iterators.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -19,15 +19,15 @@ namespace embree typedef typename Intersector::Primitive Primitive; typedef typename Intersector::Precalculations Precalculations; - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { for (size_t i=0; i - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { for (size_t i=0; i - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { for (size_t i=0; i - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { for (size_t i=0; i uv() const { return Vec2vf(vu,vv); } + __forceinline vfloat t () const { return vt; } + __forceinline Vec3vf Ng() const { return vNg; } public: vfloat vu; @@ -36,7 +40,7 @@ namespace embree { typedef CurvePrecalculations1 Precalculations; - template + template static __forceinline bool intersect(const vbool& valid_i, Ray& ray, IntersectContext* context, @@ -51,8 +55,8 @@ namespace embree LinearSpace3> ray_space = pre.ray_space; const Vec3vf ray_org ((Vec3fa)ray.org); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); - const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); Vec4vf p0(xfmVector(ray_space,v0.xyz()-ray_org), v0.w); Vec4vf p1(xfmVector(ray_space,v1.xyz()-ray_org), v1.w); @@ -105,8 +109,8 @@ namespace embree const Vec3vf ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]); const Vec3vf ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); - const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); Vec4vf p0(xfmVector(ray_space,v0.xyz()-ray_org), v0.w); Vec4vf p1(xfmVector(ray_space,v1.xyz()-ray_org), v1.w); diff --git a/kernels/geometry/linei.h b/kernels/geometry/linei.h index 2a571aacba..3ee70ac012 100644 --- a/kernels/geometry/linei.h +++ b/kernels/geometry/linei.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -40,8 +40,8 @@ namespace embree __forceinline LineMi() { } /* Construction from vertices and IDs */ - __forceinline LineMi(const vuint& v0, const vuint& geomIDs, const vuint& primIDs, Geometry::GType gtype) - : gtype((unsigned char)gtype), m((unsigned char)popcnt(vuint(primIDs) != vuint(-1))), sharedGeomID(geomIDs[0]), v0(v0), primIDs(primIDs) + __forceinline LineMi(const vuint& v0, unsigned short leftExists, unsigned short rightExists, const vuint& geomIDs, const vuint& primIDs, Geometry::GType gtype) + : gtype((unsigned char)gtype), m((unsigned char)popcnt(vuint(primIDs) != vuint(-1))), sharedGeomID(geomIDs[0]), leftExists (leftExists), rightExists(rightExists), v0(v0), primIDs(primIDs) { assert(all(vuint(geomID()) == geomIDs)); } @@ -49,10 +49,6 @@ namespace embree /* Returns a mask that tells which line segments are valid */ __forceinline vbool valid() const { return primIDs != vuint(-1); } - /* Returns a mask that tells which line segments are valid */ - template - __forceinline vbool valid() const { return vuint(primIDs) != vuint(-1); } - /* Returns if the specified line segment is valid */ __forceinline bool valid(const size_t i) const { assert(i& p0, + Vec4vf& p1, + vbool& cL, + vbool& cR, + const LineSegments* geom) const; + + __forceinline void gatheri(Vec4vf& p0, + Vec4vf& p1, + vbool& cL, + vbool& cR, + const LineSegments* geom, + const int itime) const; + + __forceinline void gather(Vec4vf& p0, + Vec4vf& p1, + vbool& cL, + vbool& cR, + const LineSegments* geom, + float time) const; + /* Calculate the bounds of the line segments */ __forceinline const BBox3fa bounds(const Scene* scene, size_t itime = 0) const { @@ -158,6 +174,8 @@ namespace embree Geometry::GType gty = scene->get(prims[begin].geomID())->getType(); vuint geomID, primID; vuint v0; + unsigned short leftExists = 0; + unsigned short rightExists = 0; const PrimRefT* prim = &prims[begin]; for (size_t i=0; igeomID(); primID[i] = prim->primID(); - v0[i] = geom->segment(prim->primID()); + v0[i] = geom->segment(prim->primID()); + leftExists |= geom->segmentLeftExists(primID[i]) << i; + rightExists |= geom->segmentRightExists(primID[i]) << i; begin++; } else { assert(i); @@ -178,7 +198,7 @@ namespace embree } if (begin @@ -247,6 +267,7 @@ namespace embree unsigned char gtype; unsigned char m; unsigned int sharedGeomID; + unsigned short leftExists, rightExists; vuint v0; // index of start vertex private: vuint primIDs; // primitive ID @@ -306,6 +327,52 @@ namespace embree p1 = lerp(a1,b1,vfloat4(ftime)); } + template<> + __forceinline void LineMi<4>::gather(Vec4vf4& p0, + Vec4vf4& p1, + vbool4& cL, + vbool4& cR, + const LineSegments* geom) const + { + gather(p0,p1,geom); + cL = !vbool4(leftExists); + cR = !vbool4(rightExists); + } + + template<> + __forceinline void LineMi<4>::gatheri(Vec4vf4& p0, + Vec4vf4& p1, + vbool4& cL, + vbool4& cR, + const LineSegments* geom, + const int itime) const + { + gatheri(p0,p1,geom,itime); + cL = !vbool4(leftExists); + cR = !vbool4(rightExists); + } + + template<> + __forceinline void LineMi<4>::gather(Vec4vf4& p0, + Vec4vf4& p1, + vbool4& cL, + vbool4& cR, + const LineSegments* geom, + float time) const + { + float ftime; + const int itime = geom->timeSegment(time, ftime); + + Vec4vf4 a0,a1; + gatheri(a0,a1,geom,itime); + Vec4vf4 b0,b1; + gatheri(b0,b1,geom,itime+1); + p0 = lerp(a0,b0,vfloat4(ftime)); + p1 = lerp(a1,b1,vfloat4(ftime)); + cL = !vbool4(leftExists); + cR = !vbool4(rightExists); + } + template<> __forceinline void LineMi<4>::gather(Vec4vf4& p0, Vec4vf4& p1, @@ -325,16 +392,16 @@ namespace embree const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1)); transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w); - const vfloat4 l0 = (primIDs[0] != -1 && geom->segmentLeftExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf); - const vfloat4 l1 = (primIDs[1] != -1 && geom->segmentLeftExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf); - const vfloat4 l2 = (primIDs[2] != -1 && geom->segmentLeftExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf); - const vfloat4 l3 = (primIDs[3] != -1 && geom->segmentLeftExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf); + const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf); + const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf); + const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf); + const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf); transpose(l0,l1,l2,l3,pL.x,pL.y,pL.z,pL.w); - const vfloat4 r0 = (primIDs[0] != -1 && geom->segmentRightExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf); - const vfloat4 r1 = (primIDs[1] != -1 && geom->segmentRightExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf); - const vfloat4 r2 = (primIDs[2] != -1 && geom->segmentRightExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf); - const vfloat4 r3 = (primIDs[3] != -1 && geom->segmentRightExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf); + const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf); + const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf); + const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf); + const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf); transpose(r0,r1,r2,r3,pR.x,pR.y,pR.z,pR.w); } @@ -358,16 +425,16 @@ namespace embree const vfloat4 b3 = vfloat4::loadu(geom->vertexPtr(v0[3]+1,itime)); transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z,p1.w); - const vfloat4 l0 = (primIDs[0] != -1 && geom->segmentLeftExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf); - const vfloat4 l1 = (primIDs[1] != -1 && geom->segmentLeftExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf); - const vfloat4 l2 = (primIDs[2] != -1 && geom->segmentLeftExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf); - const vfloat4 l3 = (primIDs[3] != -1 && geom->segmentLeftExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf); + const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf); + const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf); + const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf); + const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf); transpose(l0,l1,l2,l3,pL.x,pL.y,pL.z,pL.w); - const vfloat4 r0 = (primIDs[0] != -1 && geom->segmentRightExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf); - const vfloat4 r1 = (primIDs[1] != -1 && geom->segmentRightExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf); - const vfloat4 r2 = (primIDs[2] != -1 && geom->segmentRightExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf); - const vfloat4 r3 = (primIDs[3] != -1 && geom->segmentRightExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf); + const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf); + const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf); + const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf); + const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf); transpose(r0,r1,r2,r3,pR.x,pR.y,pR.z,pR.w); } @@ -491,24 +558,24 @@ namespace embree const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1)); transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w); - const vfloat4 l0 = (primIDs[0] != -1 && geom->segmentLeftExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf); - const vfloat4 l1 = (primIDs[1] != -1 && geom->segmentLeftExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf); - const vfloat4 l2 = (primIDs[2] != -1 && geom->segmentLeftExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf); - const vfloat4 l3 = (primIDs[3] != -1 && geom->segmentLeftExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf); - const vfloat4 l4 = (primIDs[4] != -1 && geom->segmentLeftExists(primIDs[4])) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1)) : vfloat4(inf); - const vfloat4 l5 = (primIDs[5] != -1 && geom->segmentLeftExists(primIDs[5])) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1)) : vfloat4(inf); - const vfloat4 l6 = (primIDs[6] != -1 && geom->segmentLeftExists(primIDs[6])) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1)) : vfloat4(inf); - const vfloat4 l7 = (primIDs[7] != -1 && geom->segmentLeftExists(primIDs[7])) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1)) : vfloat4(inf); + const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1)) : vfloat4(inf); + const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1)) : vfloat4(inf); + const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1)) : vfloat4(inf); + const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1)) : vfloat4(inf); + const vfloat4 l4 = (leftExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1)) : vfloat4(inf); + const vfloat4 l5 = (leftExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1)) : vfloat4(inf); + const vfloat4 l6 = (leftExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1)) : vfloat4(inf); + const vfloat4 l7 = (leftExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1)) : vfloat4(inf); transpose(l0,l1,l2,l3,l4,l5,l6,l7,pL.x,pL.y,pL.z,pL.w); - const vfloat4 r0 = (primIDs[0] != -1 && geom->segmentRightExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf); - const vfloat4 r1 = (primIDs[1] != -1 && geom->segmentRightExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf); - const vfloat4 r2 = (primIDs[2] != -1 && geom->segmentRightExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf); - const vfloat4 r3 = (primIDs[3] != -1 && geom->segmentRightExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf); - const vfloat4 r4 = (primIDs[4] != -1 && geom->segmentRightExists(primIDs[4])) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2)) : vfloat4(inf); - const vfloat4 r5 = (primIDs[5] != -1 && geom->segmentRightExists(primIDs[5])) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2)) : vfloat4(inf); - const vfloat4 r6 = (primIDs[6] != -1 && geom->segmentRightExists(primIDs[6])) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2)) : vfloat4(inf); - const vfloat4 r7 = (primIDs[7] != -1 && geom->segmentRightExists(primIDs[7])) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2)) : vfloat4(inf); + const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2)) : vfloat4(inf); + const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2)) : vfloat4(inf); + const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2)) : vfloat4(inf); + const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2)) : vfloat4(inf); + const vfloat4 r4 = (rightExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2)) : vfloat4(inf); + const vfloat4 r5 = (rightExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2)) : vfloat4(inf); + const vfloat4 r6 = (rightExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2)) : vfloat4(inf); + const vfloat4 r7 = (rightExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2)) : vfloat4(inf); transpose(r0,r1,r2,r3,r4,r5,r6,r7,pR.x,pR.y,pR.z,pR.w); } @@ -540,24 +607,24 @@ namespace embree const vfloat4 b7 = vfloat4::loadu(geom->vertexPtr(v0[7]+1,itime)); transpose(b0,b1,b2,b3,b4,b5,b6,b7,p1.x,p1.y,p1.z,p1.w); - const vfloat4 l0 = (primIDs[0] != -1 && geom->segmentLeftExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf); - const vfloat4 l1 = (primIDs[1] != -1 && geom->segmentLeftExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf); - const vfloat4 l2 = (primIDs[2] != -1 && geom->segmentLeftExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf); - const vfloat4 l3 = (primIDs[3] != -1 && geom->segmentLeftExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf); - const vfloat4 l4 = (primIDs[4] != -1 && geom->segmentLeftExists(primIDs[4])) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1,itime)) : vfloat4(inf); - const vfloat4 l5 = (primIDs[5] != -1 && geom->segmentLeftExists(primIDs[5])) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1,itime)) : vfloat4(inf); - const vfloat4 l6 = (primIDs[6] != -1 && geom->segmentLeftExists(primIDs[6])) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1,itime)) : vfloat4(inf); - const vfloat4 l7 = (primIDs[7] != -1 && geom->segmentLeftExists(primIDs[7])) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1,itime)) : vfloat4(inf); + const vfloat4 l0 = (leftExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]-1,itime)) : vfloat4(inf); + const vfloat4 l1 = (leftExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]-1,itime)) : vfloat4(inf); + const vfloat4 l2 = (leftExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]-1,itime)) : vfloat4(inf); + const vfloat4 l3 = (leftExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]-1,itime)) : vfloat4(inf); + const vfloat4 l4 = (leftExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]-1,itime)) : vfloat4(inf); + const vfloat4 l5 = (leftExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]-1,itime)) : vfloat4(inf); + const vfloat4 l6 = (leftExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]-1,itime)) : vfloat4(inf); + const vfloat4 l7 = (leftExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]-1,itime)) : vfloat4(inf); transpose(l0,l1,l2,l3,l4,l5,l6,l7,pL.x,pL.y,pL.z,pL.w); - const vfloat4 r0 = (primIDs[0] != -1 && geom->segmentRightExists(primIDs[0])) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf); - const vfloat4 r1 = (primIDs[1] != -1 && geom->segmentRightExists(primIDs[1])) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf); - const vfloat4 r2 = (primIDs[2] != -1 && geom->segmentRightExists(primIDs[2])) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf); - const vfloat4 r3 = (primIDs[3] != -1 && geom->segmentRightExists(primIDs[3])) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf); - const vfloat4 r4 = (primIDs[4] != -1 && geom->segmentRightExists(primIDs[4])) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2,itime)) : vfloat4(inf); - const vfloat4 r5 = (primIDs[5] != -1 && geom->segmentRightExists(primIDs[5])) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2,itime)) : vfloat4(inf); - const vfloat4 r6 = (primIDs[6] != -1 && geom->segmentRightExists(primIDs[6])) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2,itime)) : vfloat4(inf); - const vfloat4 r7 = (primIDs[7] != -1 && geom->segmentRightExists(primIDs[7])) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2,itime)) : vfloat4(inf); + const vfloat4 r0 = (rightExists & (1<<0)) ? vfloat4::loadu(geom->vertexPtr(v0[0]+2,itime)) : vfloat4(inf); + const vfloat4 r1 = (rightExists & (1<<1)) ? vfloat4::loadu(geom->vertexPtr(v0[1]+2,itime)) : vfloat4(inf); + const vfloat4 r2 = (rightExists & (1<<2)) ? vfloat4::loadu(geom->vertexPtr(v0[2]+2,itime)) : vfloat4(inf); + const vfloat4 r3 = (rightExists & (1<<3)) ? vfloat4::loadu(geom->vertexPtr(v0[3]+2,itime)) : vfloat4(inf); + const vfloat4 r4 = (rightExists & (1<<4)) ? vfloat4::loadu(geom->vertexPtr(v0[4]+2,itime)) : vfloat4(inf); + const vfloat4 r5 = (rightExists & (1<<5)) ? vfloat4::loadu(geom->vertexPtr(v0[5]+2,itime)) : vfloat4(inf); + const vfloat4 r6 = (rightExists & (1<<6)) ? vfloat4::loadu(geom->vertexPtr(v0[6]+2,itime)) : vfloat4(inf); + const vfloat4 r7 = (rightExists & (1<<7)) ? vfloat4::loadu(geom->vertexPtr(v0[7]+2,itime)) : vfloat4(inf); transpose(r0,r1,r2,r3,r4,r5,r6,r7,pR.x,pR.y,pR.z,pR.w); } @@ -581,6 +648,52 @@ namespace embree pL = lerp(aL,bL,vfloat8(ftime)); pR = lerp(aR,bR,vfloat8(ftime)); } + + template<> + __forceinline void LineMi<8>::gather(Vec4vf8& p0, + Vec4vf8& p1, + vbool8& cL, + vbool8& cR, + const LineSegments* geom) const + { + gather(p0,p1,geom); + cL = !vbool8(leftExists); + cR = !vbool8(rightExists); + } + + template<> + __forceinline void LineMi<8>::gatheri(Vec4vf8& p0, + Vec4vf8& p1, + vbool8& cL, + vbool8& cR, + const LineSegments* geom, + const int itime) const + { + gatheri(p0,p1,geom,itime); + cL = !vbool8(leftExists); + cR = !vbool8(rightExists); + } + + template<> + __forceinline void LineMi<8>::gather(Vec4vf8& p0, + Vec4vf8& p1, + vbool8& cL, + vbool8& cR, + const LineSegments* geom, + float time) const + { + float ftime; + const int itime = geom->timeSegment(time, ftime); + + Vec4vf8 a0,a1; + gatheri(a0,a1,geom,itime); + Vec4vf8 b0,b1; + gatheri(b0,b1,geom,itime+1); + p0 = lerp(a0,b0,vfloat8(ftime)); + p1 = lerp(a1,b1,vfloat8(ftime)); + cL = !vbool8(leftExists); + cR = !vbool8(rightExists); + } #endif diff --git a/kernels/geometry/linei_intersector.h b/kernels/geometry/linei_intersector.h index a431796a88..5992827f5b 100644 --- a/kernels/geometry/linei_intersector.h +++ b/kernels/geometry/linei_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,7 +11,7 @@ namespace embree { namespace isa { - template + template struct FlatLinearCurveMiIntersector1 { typedef LineMi Primitive; @@ -22,8 +22,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom); - const vbool valid = line.template valid(); - FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line) @@ -31,8 +31,8 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom); - const vbool valid = line.template valid(); - return FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line) @@ -41,7 +41,7 @@ namespace embree } }; - template + template struct FlatLinearCurveMiMBIntersector1 { typedef LineMi Primitive; @@ -52,8 +52,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom,ray.time()); - const vbool valid = line.template valid(); - FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line) @@ -61,8 +61,8 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom,ray.time()); - const vbool valid = line.template valid(); - return FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return FlatLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line) @@ -71,7 +71,7 @@ namespace embree } }; - template + template struct FlatLinearCurveMiIntersectorK { typedef LineMi Primitive; @@ -82,8 +82,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom); - const vbool valid = line.template valid(); - FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& line) @@ -91,12 +91,12 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom); - const vbool valid = line.template valid(); - return FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); } }; - template + template struct FlatLinearCurveMiMBIntersectorK { typedef LineMi Primitive; @@ -107,8 +107,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom,ray.time()[k]); - const vbool valid = line.template valid(); - FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& line) @@ -116,8 +116,8 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1; line.gather(v0,v1,geom,ray.time()[k]); - const vbool valid = line.template valid(); - return FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return FlatLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); } }; } diff --git a/kernels/geometry/object.h b/kernels/geometry/object.h index f26391de52..2a61829ffd 100644 --- a/kernels/geometry/object.h +++ b/kernels/geometry/object.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/object_intersector.h b/kernels/geometry/object_intersector.h index 97882e0e59..e4ad01852f 100644 --- a/kernels/geometry/object_intersector.h +++ b/kernels/geometry/object_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -32,7 +32,7 @@ namespace embree return; #endif - accel->intersect(ray,prim.geomID(),prim.primID(),context,reportIntersection1); + accel->intersect(ray,prim.geomID(),prim.primID(),context); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& prim) @@ -44,7 +44,7 @@ namespace embree return false; #endif - accel->occluded(ray,prim.geomID(),prim.primID(),context,&reportOcclusion1); + accel->occluded(ray,prim.geomID(),prim.primID(),context); return ray.tfar < 0.0f; } @@ -89,7 +89,7 @@ namespace embree valid &= (ray.mask & accel->mask) != 0; if (none(valid)) return; #endif - accel->intersect(valid,ray,prim.geomID(),prim.primID(),context,&reportIntersection1); + accel->intersect(valid,ray,prim.geomID(),prim.primID(),context); } static __forceinline vbool occluded(const vbool& valid_i, const Precalculations& pre, RayK& ray, IntersectContext* context, const Primitive& prim) @@ -102,7 +102,7 @@ namespace embree valid &= (ray.mask & accel->mask) != 0; if (none(valid)) return false; #endif - accel->occluded(valid,ray,prim.geomID(),prim.primID(),context,&reportOcclusion1); + accel->occluded(valid,ray,prim.geomID(),prim.primID(),context); return ray.tfar < 0.0f; } diff --git a/kernels/geometry/plane.h b/kernels/geometry/plane.h index ebe45db558..e447122eab 100644 --- a/kernels/geometry/plane.h +++ b/kernels/geometry/plane.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/pointi.h b/kernels/geometry/pointi.h index a31c239304..174a1104c8 100644 --- a/kernels/geometry/pointi.h +++ b/kernels/geometry/pointi.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -57,58 +57,33 @@ namespace embree } /* Returns a mask that tells which line segments are valid */ - __forceinline vbool valid() const - { - //return primIDs != vuint(-1); + __forceinline vbool valid() const { return vint(step) < vint(numPrimitives); } - /* Returns a mask that tells which line segments are valid */ - template - __forceinline vbool valid() const - { - //return vuint(primIDs) != vuint(-1); - return vint(step) < vint(numPrimitives); - } - /* Returns if the specified line segment is valid */ __forceinline bool valid(const size_t i) const { assert(i < M); - //return primIDs[i] != -1; return i < numPrimitives; } /* Returns the number of stored line segments */ - __forceinline size_t size() const - { - //return bsf(~movemask(valid())); + __forceinline size_t size() const { return numPrimitives; } - /* Returns the geometry IDs */ - // template - // static __forceinline T unmask(T &index) { return index & 0x3fffffff; } - - __forceinline unsigned int geomID(unsigned int i = 0) const - { + __forceinline unsigned int geomID(unsigned int i = 0) const { return sharedGeomID; } - //__forceinline vuint geomID() { return unmask(geomIDs); } - //__forceinline const vuint geomID() const { return unmask(geomIDs); } - //__forceinline unsigned int geomID(const size_t i) const { assert(i& primID() - { + __forceinline vuint& primID() { return primIDs; } - __forceinline const vuint& primID() const - { + __forceinline const vuint& primID() const { return primIDs; } - __forceinline unsigned int primID(const size_t i) const - { + __forceinline unsigned int primID(const size_t i) const { assert(i < M); return primIDs[i]; } @@ -117,8 +92,8 @@ namespace embree __forceinline void gather(Vec4vf& p0, const Points* geom) const; __forceinline void gather(Vec4vf& p0, Vec3vf& n0, const Points* geom) const; - __forceinline void gatheri(Vec4vf& p0, const Points* geom, const vint& itime) const; - __forceinline void gatheri(Vec4vf& p0, Vec3vf& n0, const Points* geom, const vint& itime) const; + __forceinline void gatheri(Vec4vf& p0, const Points* geom, const int itime) const; + __forceinline void gatheri(Vec4vf& p0, Vec3vf& n0, const Points* geom, const int itime) const; __forceinline void gather(Vec4vf& p0, const Points* geom, float time) const; __forceinline void gather(Vec4vf& p0, Vec3vf& n0, const Points* geom, float time) const; @@ -237,7 +212,7 @@ namespace embree /*! output operator */ friend __forceinline embree_ostream operator<<(embree_ostream cout, const PointMi& line) { - return cout << "Line" << M << "i {" << line.v0 << ", " << line.geomID() << ", " << line.primID() << "}"; + return cout << "Line" << M << "i {" << line.geomID() << ", " << line.primID() << "}"; } public: @@ -275,55 +250,53 @@ namespace embree } template<> - __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, const Points* geom, const vint4& itime) const + __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, const Points* geom, const int itime) const { - const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime[0])); - const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime[1])); - const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime[2])); - const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime[3])); + const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); + const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); + const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); + const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w); } template<> - __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, const vint4& itime) const + __forceinline void PointMi<4>::gatheri(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, const int itime) const { - const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime[0])); - const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime[1])); - const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime[2])); - const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime[3])); + const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); + const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); + const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); + const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); transpose(a0, a1, a2, a3, p0.x, p0.y, p0.z, p0.w); - const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime[0])); - const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime[1])); - const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime[2])); - const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime[3])); + const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime)); + const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime)); + const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime)); + const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime)); transpose(b0, b1, b2, b3, n0.x, n0.y, n0.z); } template<> __forceinline void PointMi<4>::gather(Vec4vf4& p0, const Points* geom, float time) const { - const vfloat4 numTimeSegments(geom->fnumTimeSegments); - vfloat4 ftime; - const vint4 itime = getTimeSegment(vfloat4(time), numTimeSegments, ftime); + float ftime; + const int itime = geom->timeSegment(time, ftime); Vec4vf4 a0; gatheri(a0, geom, itime); Vec4vf4 b0; gatheri(b0, geom, itime + 1); - p0 = lerp(a0, b0, ftime); + p0 = lerp(a0, b0, vfloat4(ftime)); } template<> __forceinline void PointMi<4>::gather(Vec4vf4& p0, Vec3vf4& n0, const Points* geom, float time) const { - const vfloat4 numTimeSegments(geom->fnumTimeSegments); - vfloat4 ftime; - const vint4 itime = getTimeSegment(vfloat4(time), numTimeSegments, ftime); + float ftime; + const int itime = geom->timeSegment(time, ftime); Vec4vf4 a0, b0; Vec3vf4 norm0, norm1; gatheri(a0, norm0, geom, itime); gatheri(b0, norm1, geom, itime + 1); - p0 = lerp(a0, b0, ftime); - n0 = lerp(norm0, norm1, ftime); + p0 = lerp(a0, b0, vfloat4(ftime)); + n0 = lerp(norm0, norm1, vfloat4(ftime)); } #if defined(__AVX__) @@ -366,69 +339,67 @@ namespace embree } template<> - __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, const Points* geom, const vint8& itime) const + __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, const Points* geom, const int itime) const { - const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime[0])); - const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime[1])); - const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime[2])); - const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime[3])); - const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime[4])); - const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime[5])); - const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime[6])); - const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime[7])); + const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); + const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); + const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); + const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); + const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime)); + const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime)); + const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime)); + const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime)); transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w); } template<> - __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, const vint8& itime) const + __forceinline void PointMi<8>::gatheri(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, const int itime) const { - const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime[0])); - const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime[1])); - const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime[2])); - const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime[3])); - const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime[4])); - const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime[5])); - const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime[6])); - const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime[7])); + const vfloat4 a0 = vfloat4::loadu(geom->vertexPtr(primID(0), itime)); + const vfloat4 a1 = vfloat4::loadu(geom->vertexPtr(primID(1), itime)); + const vfloat4 a2 = vfloat4::loadu(geom->vertexPtr(primID(2), itime)); + const vfloat4 a3 = vfloat4::loadu(geom->vertexPtr(primID(3), itime)); + const vfloat4 a4 = vfloat4::loadu(geom->vertexPtr(primID(4), itime)); + const vfloat4 a5 = vfloat4::loadu(geom->vertexPtr(primID(5), itime)); + const vfloat4 a6 = vfloat4::loadu(geom->vertexPtr(primID(6), itime)); + const vfloat4 a7 = vfloat4::loadu(geom->vertexPtr(primID(7), itime)); transpose(a0, a1, a2, a3, a4, a5, a6, a7, p0.x, p0.y, p0.z, p0.w); - const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime[0])); - const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime[1])); - const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime[2])); - const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime[3])); - const vfloat4 b4 = vfloat4(geom->normal(primID(4), itime[4])); - const vfloat4 b5 = vfloat4(geom->normal(primID(5), itime[5])); - const vfloat4 b6 = vfloat4(geom->normal(primID(6), itime[6])); - const vfloat4 b7 = vfloat4(geom->normal(primID(7), itime[7])); + const vfloat4 b0 = vfloat4(geom->normal(primID(0), itime)); + const vfloat4 b1 = vfloat4(geom->normal(primID(1), itime)); + const vfloat4 b2 = vfloat4(geom->normal(primID(2), itime)); + const vfloat4 b3 = vfloat4(geom->normal(primID(3), itime)); + const vfloat4 b4 = vfloat4(geom->normal(primID(4), itime)); + const vfloat4 b5 = vfloat4(geom->normal(primID(5), itime)); + const vfloat4 b6 = vfloat4(geom->normal(primID(6), itime)); + const vfloat4 b7 = vfloat4(geom->normal(primID(7), itime)); transpose(b0, b1, b2, b3, b4, b5, b6, b7, n0.x, n0.y, n0.z); } template<> __forceinline void PointMi<8>::gather(Vec4vf8& p0, const Points* geom, float time) const { - const vfloat8 numTimeSegments(geom->fnumTimeSegments); - vfloat8 ftime; - const vint8 itime = getTimeSegment(vfloat8(time), numTimeSegments, ftime); + float ftime; + const int itime = geom->timeSegment(time, ftime); Vec4vf8 a0; gatheri(a0, geom, itime); Vec4vf8 b0; gatheri(b0, geom, itime + 1); - p0 = lerp(a0, b0, ftime); + p0 = lerp(a0, b0, vfloat8(ftime)); } template<> __forceinline void PointMi<8>::gather(Vec4vf8& p0, Vec3vf8& n0, const Points* geom, float time) const { - const vfloat8 numTimeSegments(geom->fnumTimeSegments); - vfloat8 ftime; - const vint8 itime = getTimeSegment(vfloat8(time), numTimeSegments, ftime); + float ftime; + const int itime = geom->timeSegment(time, ftime); Vec4vf8 a0, b0; Vec3vf8 norm0, norm1; gatheri(a0, norm0, geom, itime); gatheri(b0, norm1, geom, itime + 1); - p0 = lerp(a0, b0, ftime); - n0 = lerp(norm0, norm1, ftime); + p0 = lerp(a0, b0, vfloat8(ftime)); + n0 = lerp(norm0, norm1, vfloat8(ftime)); } #endif @@ -437,4 +408,5 @@ namespace embree typedef PointMi<4> Point4i; typedef PointMi<8> Point8i; + } // namespace embree diff --git a/kernels/geometry/primitive.h b/kernels/geometry/primitive.h index 41e5b2b304..608d981dd7 100644 --- a/kernels/geometry/primitive.h +++ b/kernels/geometry/primitive.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/primitive4.cpp b/kernels/geometry/primitive4.cpp index f93574c9c8..9c953c5d35 100644 --- a/kernels/geometry/primitive4.cpp +++ b/kernels/geometry/primitive4.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "primitive.h" diff --git a/kernels/geometry/primitive8.cpp b/kernels/geometry/primitive8.cpp index e88adf8a9d..20596a3673 100644 --- a/kernels/geometry/primitive8.cpp +++ b/kernels/geometry/primitive8.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "primitive.h" diff --git a/kernels/geometry/quad_intersector.h b/kernels/geometry/quad_intersector.h index 57ff4e60e5..93c9526912 100644 --- a/kernels/geometry/quad_intersector.h +++ b/kernels/geometry/quad_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/quad_intersector_moeller.h b/kernels/geometry/quad_intersector_moeller.h index 192e770baa..3abc9d6f70 100644 --- a/kernels/geometry/quad_intersector_moeller.h +++ b/kernels/geometry/quad_intersector_moeller.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -28,8 +28,8 @@ namespace embree { const vfloat rcpAbsDen = rcp(absDen); vt = T * rcpAbsDen; - const vfloat u = U * rcpAbsDen; - const vfloat v = V * rcpAbsDen; + const vfloat u = min(U * rcpAbsDen,1.0f); + const vfloat v = min(V * rcpAbsDen,1.0f); const vfloat u1 = vfloat(1.0f) - u; const vfloat v1 = vfloat(1.0f) - v; #if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING) @@ -87,8 +87,8 @@ namespace embree { const vfloat rcpAbsDen = rcp(absDen); const vfloat t = T * rcpAbsDen; - const vfloat u0 = U * rcpAbsDen; - const vfloat v0 = V * rcpAbsDen; + const vfloat u0 = min(U * rcpAbsDen,1.0f); + const vfloat v0 = min(V * rcpAbsDen,1.0f); const vfloat u1 = vfloat(1.0f) - u0; const vfloat v1 = vfloat(1.0f) - v0; const vfloat u = select(flags,u1,u0); @@ -126,16 +126,17 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - MoellerTrumboreHitM hit; + UVIdentity mapUV; + MoellerTrumboreHitM> hit(mapUV); MoellerTrumboreIntersector1 intersector(ray,nullptr); - Intersect1EpilogM epilog(ray,context,geomID,primID); + Intersect1EpilogM epilog(ray,context,geomID,primID); /* intersect first triangle */ - if (intersector.intersect(ray,v0,v1,v3,hit)) + if (intersector.intersect(ray,v0,v1,v3,mapUV,hit)) epilog(hit.valid,hit); /* intersect second triangle */ - if (intersector.intersect(ray,v2,v3,v1,hit)) + if (intersector.intersect(ray,v2,v3,v1,mapUV,hit)) { hit.U = hit.absDen - hit.U; hit.V = hit.absDen - hit.V; @@ -147,19 +148,20 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - MoellerTrumboreHitM hit; + UVIdentity mapUV; + MoellerTrumboreHitM> hit(mapUV); MoellerTrumboreIntersector1 intersector(ray,nullptr); - Occluded1EpilogM epilog(ray,context,geomID,primID); + Occluded1EpilogM epilog(ray,context,geomID,primID); /* intersect first triangle */ - if (intersector.intersect(ray,v0,v1,v3,hit)) + if (intersector.intersect(ray,v0,v1,v3,mapUV,hit)) { if (epilog(hit.valid,hit)) return true; } /* intersect second triangle */ - if (intersector.intersect(ray,v2,v3,v1,hit)) + if (intersector.intersect(ray,v2,v3,v1,mapUV,hit)) { hit.U = hit.absDen - hit.U; hit.V = hit.absDen - hit.V; @@ -170,70 +172,7 @@ namespace embree } }; -#if defined(__AVX512ER__) // KNL - - /*! Intersects 4 quads with 1 ray using AVX512 */ - template - struct QuadMIntersector1MoellerTrumbore<4,filter> - { - __forceinline QuadMIntersector1MoellerTrumbore() {} - - __forceinline QuadMIntersector1MoellerTrumbore(const Ray& ray, const void* ptr) {} - - template - __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const - { - const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)), - select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)), - select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z))); -#if !defined(EMBREE_BACKFACE_CULLING) - const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z)); - const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z)); -#else - const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)), - select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)), - select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z))); - const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)), - select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)), - select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z))); -#endif - const vbool16 flags(0xf0f0); - - MoellerTrumboreHitM<16> hit; - MoellerTrumboreIntersector1<16> intersector(ray,nullptr); - if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,hit))) - { - vfloat16 U = hit.U, V = hit.V, absDen = hit.absDen; -#if !defined(EMBREE_BACKFACE_CULLING) - hit.U = select(flags,absDen-V,U); - hit.V = select(flags,absDen-U,V); - hit.vNg *= select(flags,vfloat16(-1.0f),vfloat16(1.0f)); // FIXME: use XOR -#else - hit.U = select(flags,absDen-U,U); - hit.V = select(flags,absDen-V,V); -#endif - if (likely(epilog(hit.valid,hit))) - return true; - } - return false; - } - - __forceinline bool intersect(RayHit& ray, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID))); - } - - __forceinline bool occluded(Ray& ray, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID))); - } - }; - -#elif defined(__AVX__) +#if defined(__AVX__) /*! Intersects 4 quads with 1 ray using AVX */ template @@ -254,10 +193,11 @@ namespace embree const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); #endif - MoellerTrumboreHitM<8> hit; + UVIdentity<8> mapUV; + MoellerTrumboreHitM<8,UVIdentity<8>> hit(mapUV); MoellerTrumboreIntersector1<8> intersector(ray,nullptr); const vbool8 flags(0,0,0,0,1,1,1,1); - if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,hit))) + if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit))) { vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen; @@ -279,14 +219,14 @@ namespace embree const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID))); + return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID))); } __forceinline bool occluded(Ray& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID))); + return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID))); } }; @@ -353,7 +293,7 @@ namespace embree const Vec3vf e1 = v0-v1; const Vec3vf e2 = v2-v0; const Vec3vf Ng = cross(e2,e1); - return intersect(ray,k,v0,e1,e2,Ng,flags,epilog); + return intersect(ray,k,v0,e1,e2,Ng,flags,epilog); } }; @@ -458,70 +398,24 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - Intersect1KEpilogM epilog(ray,k,context,geomID,primID); - MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog); - MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog); + Intersect1KEpilogM epilog(ray,k,context,geomID,primID); + MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog); + MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog); } __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - Occluded1KEpilogM epilog(ray,k,context,geomID,primID); - if (MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog)) return true; - if (MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog)) return true; + Occluded1KEpilogM epilog(ray,k,context,geomID,primID); + if (MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog)) return true; + if (MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog)) return true; return false; } }; -#if defined(__AVX512ER__) // KNL - - /*! Intersects 4 quads with 1 ray using AVX512 */ - template - struct QuadMIntersectorKMoellerTrumbore<4,K,filter> : public QuadMIntersectorKMoellerTrumboreBase<4,K,filter> - { - __forceinline QuadMIntersectorKMoellerTrumbore(const vbool& valid, const RayK& ray) - : QuadMIntersectorKMoellerTrumboreBase<4,K,filter>(valid,ray) {} - - template - __forceinline bool intersect1(RayK& ray, size_t k, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const - { - const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)), - select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)), - select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z))); -#if !defined(EMBREE_BACKFACE_CULLING) - const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z)); - const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z)); -#else - const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)), - select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)), - select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z))); - const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)), - select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)), - select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z))); -#endif - const vbool16 flags(0xf0f0); - return MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog); - } - - __forceinline bool intersect1(RayHitK& ray, size_t k, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); - } - - __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); - } - }; - -#elif defined(__AVX__) +#if defined(__AVX__) /*! Intersects 4 quads with 1 ray using AVX */ template @@ -543,21 +437,21 @@ namespace embree const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); #endif const vbool8 flags(0,0,0,0,1,1,1,1); - return MoellerTrumboreIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog); + return MoellerTrumboreIntersector1KTriangleM::intersect1<8,K>(ray,k,vtx0,vtx1,vtx2,flags,epilog); } __forceinline bool intersect1(RayHitK& ray, size_t k, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); + return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); } __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); + return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); } }; diff --git a/kernels/geometry/quad_intersector_pluecker.h b/kernels/geometry/quad_intersector_pluecker.h index 7665dee3b7..9873ff76ac 100644 --- a/kernels/geometry/quad_intersector_pluecker.h +++ b/kernels/geometry/quad_intersector_pluecker.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -34,8 +34,8 @@ namespace embree { const vbool invalid = abs(UVW) < min_rcp_input; const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); - const vfloat u = U * rcpUVW; - const vfloat v = V * rcpUVW; + const vfloat u = min(U * rcpUVW,1.0f); + const vfloat v = min(V * rcpUVW,1.0f); const vfloat u1 = vfloat(1.0f) - u; const vfloat v1 = vfloat(1.0f) - v; #if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING) @@ -92,8 +92,8 @@ namespace embree { const vbool invalid = abs(UVW) < min_rcp_input; const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); - const vfloat u0 = U * rcpUVW; - const vfloat v0 = V * rcpUVW; + const vfloat u0 = min(U * rcpUVW,1.0f); + const vfloat v0 = min(V * rcpUVW,1.0f); const vfloat u1 = vfloat(1.0f) - u0; const vfloat v1 = vfloat(1.0f) - v0; const vfloat u = select(flags,u1,u0); @@ -175,69 +175,23 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - Intersect1EpilogM epilog(ray,context,geomID,primID); - PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool(false),epilog); - PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool(true),epilog); + Intersect1EpilogM epilog(ray,context,geomID,primID); + PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool(false),epilog); + PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool(true),epilog); } __forceinline bool occluded(Ray& ray, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - Occluded1EpilogM epilog(ray,context,geomID,primID); - if (PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool(false),epilog)) return true; - if (PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool(true ),epilog)) return true; + Occluded1EpilogM epilog(ray,context,geomID,primID); + if (PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool(false),epilog)) return true; + if (PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool(true ),epilog)) return true; return false; } }; -#if defined(__AVX512ER__) // KNL - - /*! Intersects 4 quads with 1 ray using AVX512 */ - template - struct QuadMIntersector1Pluecker<4,filter> - { - __forceinline QuadMIntersector1Pluecker() {} - - __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {} - - template - __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const - { - const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)), - select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)), - select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z))); -#if !defined(EMBREE_BACKFACE_CULLING) - const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z)); - const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z)); -#else - const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)), - select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)), - select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z))); - const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)), - select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)), - select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z))); -#endif - const vbool16 flags(0xf0f0); - return PlueckerIntersectorTriangle1::intersect(ray,vtx0,vtx1,vtx2,flags,epilog); - } - - __forceinline bool intersect(RayHit& ray, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID))); - } - - __forceinline bool occluded(Ray& ray, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,16,filter>(ray,context,vuint8(geomID),vuint8(primID))); - } - }; - -#elif defined(__AVX__) +#if defined(__AVX__) /*! Intersects 4 quads with 1 ray using AVX */ template @@ -259,19 +213,19 @@ namespace embree const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); #endif const vbool8 flags(0,0,0,0,1,1,1,1); - return PlueckerIntersectorTriangle1::intersect(ray,vtx0,vtx1,vtx2,flags,epilog); + return PlueckerIntersectorTriangle1::intersect<8>(ray,vtx0,vtx1,vtx2,flags,epilog); } __forceinline bool intersect(RayHit& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID))); + return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID))); } __forceinline bool occluded(Ray& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,8,filter>(ray,context,vuint8(geomID),vuint8(primID))); + return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,filter>(ray,context,vuint8(geomID),vuint8(primID))); } }; @@ -305,18 +259,19 @@ namespace embree const Vec3vf e0 = v2-v0; const Vec3vf e1 = v0-v1; const Vec3vf e2 = v1-v2; - + /* perform edge tests */ const vfloat U = dot(cross(e0,v2+v0),D); const vfloat V = dot(cross(e1,v0+v1),D); const vfloat W = dot(cross(e2,v1+v2),D); + const vfloat UVW = U+V+W; const vfloat eps = float(ulp)*abs(UVW); #if defined(EMBREE_BACKFACE_CULLING) vbool valid = max(U,V,W) <= eps; #else vbool valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); -#endif +#endif if (unlikely(none(valid))) return false; /* calculate geometry normal and denominator */ @@ -423,69 +378,23 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - Intersect1KEpilogM epilog(ray,k,context,geomID,primID); - PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog); - PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog); + Intersect1KEpilogM epilog(ray,k,context,geomID,primID); + PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog); + PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog); } __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const vuint& geomID, const vuint& primID) const { - Occluded1KEpilogM epilog(ray,k,context,geomID,primID); - if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog)) return true; - if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog)) return true; + Occluded1KEpilogM epilog(ray,k,context,geomID,primID); + if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool(false),epilog)) return true; + if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool(true ),epilog)) return true; return false; } }; -#if defined(__AVX512ER__) // KNL - - /*! Intersects 4 quads with 1 ray using AVX512 */ - template - struct QuadMIntersectorKPluecker<4,K,filter> : public QuadMIntersectorKPlueckerBase<4,K,filter> - { - __forceinline QuadMIntersectorKPluecker(const vbool& valid, const RayK& ray) - : QuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {} - - template - __forceinline bool intersect1(RayK& ray, size_t k, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const - { - const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)), - select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)), - select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z))); -#if !defined(EMBREE_BACKFACE_CULLING) - const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z)); - const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z)); -#else - const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)), - select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)), - select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z))); - const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)), - select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)), - select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z))); -#endif - - const vbool16 flags(0xf0f0); - return PlueckerIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog); - } - - __forceinline bool intersect1(RayHitK& ray, size_t k, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); - } - - __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, - const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, - const vuint4& geomID, const vuint4& primID) const - { - return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,16,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); - } - }; - -#elif defined(__AVX__) +#if defined(__AVX__) /*! Intersects 4 quads with 1 ray using AVX */ template @@ -506,21 +415,21 @@ namespace embree const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); #endif - return PlueckerIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog); + return PlueckerIntersector1KTriangleM::intersect1<8,K>(ray,k,vtx0,vtx1,vtx2,flags,epilog); } __forceinline bool intersect1(RayHitK& ray, size_t k, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); + return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); } __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const vuint4& geomID, const vuint4& primID) const { - return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); + return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,K,filter>(ray,k,context,vuint8(geomID),vuint8(primID))); } }; diff --git a/kernels/geometry/quadi.h b/kernels/geometry/quadi.h index 741ec519ab..70a7bdf158 100644 --- a/kernels/geometry/quadi.h +++ b/kernels/geometry/quadi.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -349,7 +349,7 @@ namespace embree const QuadMesh* mesh = scene->get(geomID(index)); vfloat ftime; - const vint itime = mesh->timeSegment(time, ftime); + const vint itime = mesh->timeSegment(time, ftime); const size_t first = bsf(movemask(valid)); if (likely(all(valid,itime[first] == itime))) @@ -361,10 +361,10 @@ namespace embree } else { - p0 = getVertex<0>(valid, index, scene, itime, ftime); - p1 = getVertex<1>(valid, index, scene, itime, ftime); - p2 = getVertex<2>(valid, index, scene, itime, ftime); - p3 = getVertex<3>(valid, index, scene, itime, ftime); + p0 = getVertex<0,K>(valid, index, scene, itime, ftime); + p1 = getVertex<1,K>(valid, index, scene, itime, ftime); + p2 = getVertex<2,K>(valid, index, scene, itime, ftime); + p3 = getVertex<3,K>(valid, index, scene, itime, ftime); } } diff --git a/kernels/geometry/quadi_intersector.h b/kernels/geometry/quadi_intersector.h index 96cf7f1ca2..20a98c3406 100644 --- a/kernels/geometry/quadi_intersector.h +++ b/kernels/geometry/quadi_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -230,7 +230,7 @@ namespace embree { if (!quad.valid(i)) break; STAT3(normal.trav_prims,1,popcnt(valid_i),K); - Vec3vf v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); + Vec3vf v0,v1,v2,v3; quad.template gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM(ray,context,quad.geomID(),quad.primID(),i)); } } @@ -243,7 +243,7 @@ namespace embree { if (!quad.valid(i)) break; STAT3(shadow.trav_prims,1,popcnt(valid0),K); - Vec3vf v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); + Vec3vf v0,v1,v2,v3; quad.template gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM(valid0,ray,context,quad.geomID(),quad.primID(),i))) break; } @@ -310,7 +310,7 @@ namespace embree { if (!quad.valid(i)) break; STAT3(normal.trav_prims,1,popcnt(valid_i),K); - Vec3vf v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); + Vec3vf v0,v1,v2,v3; quad.template gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); pre.intersectK(valid_i,ray,v0,v1,v2,v3,IntersectKEpilogM(ray,context,quad.geomID(),quad.primID(),i)); } } @@ -323,7 +323,7 @@ namespace embree { if (!quad.valid(i)) break; STAT3(shadow.trav_prims,1,popcnt(valid0),K); - Vec3vf v0,v1,v2,v3; quad.gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); + Vec3vf v0,v1,v2,v3; quad.template gather(valid_i,v0,v1,v2,v3,i,context->scene,ray.time()); if (pre.intersectK(valid0,ray,v0,v1,v2,v3,OccludedKEpilogM(valid0,ray,context,quad.geomID(),quad.primID(),i))) break; } diff --git a/kernels/geometry/quadv.h b/kernels/geometry/quadv.h index 0a1fe4d128..514e519b0c 100644 --- a/kernels/geometry/quadv.h +++ b/kernels/geometry/quadv.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -152,7 +152,7 @@ namespace embree Vec3vf v0; // 1st vertex of the quads Vec3vf v1; // 2nd vertex of the quads Vec3vf v2; // 3rd vertex of the quads - Vec3vf v3; // 4rd vertex of the quads + Vec3vf v3; // 4th vertex of the quads private: vuint geomIDs; // geometry ID vuint primIDs; // primitive ID diff --git a/kernels/geometry/quadv_intersector.h b/kernels/geometry/quadv_intersector.h index 30a24b291a..9b28e05614 100644 --- a/kernels/geometry/quadv_intersector.h +++ b/kernels/geometry/quadv_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/roundline_intersector.h b/kernels/geometry/roundline_intersector.h index 4ff4edafdb..764ff93fec 100644 --- a/kernels/geometry/roundline_intersector.h +++ b/kernels/geometry/roundline_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -19,7 +19,7 @@ For multiple connected round linear curve segments this construction yield a proper shape when viewed from the outside. Using the - following CSG we can also handle the interiour in most common cases: + following CSG we can also handle the interior in most common cases: round_linear_curve(pl,rl,p0,r0,p1,r1,pr,rr) = cone_sphere(p0,r0,p1,r1) - cone(pl,rl,p0,r0) - cone(p1,r1,pr,rr) @@ -81,7 +81,11 @@ namespace embree __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } __forceinline float t (const size_t i) const { return vt[i]; } __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } - + + __forceinline Vec2vf uv() const { return Vec2vf(vu,vv); } + __forceinline vfloat t () const { return vt; } + __forceinline Vec3vf Ng() const { return vNg; } + public: vfloat vu; vfloat vv; @@ -323,8 +327,6 @@ namespace embree * case. */ valid &= abs(A) > min_rcp_input; if (unlikely(none(valid))) { - lower = vfloat(pos_inf); - upper = vfloat(neg_inf); return false; } @@ -332,13 +334,13 @@ namespace embree const vfloat Q = sqrt(D); const vfloat rcp_2A = rcp(2.0f*A); t_cone_front = (-B-Q)*rcp_2A; - t_cone_back = (-B+Q)*rcp_2A; - y_cone_front = yp + t_cone_front*dOdP; - y_cone_back = yp + t_cone_back *dOdP; lower = select( (y_cone_front > -(float)ulp) & (y_cone_front <= g) & (g > 0.0f), t_cone_front, vfloat(pos_inf)); +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) + t_cone_back = (-B+Q)*rcp_2A; + y_cone_back = yp + t_cone_back *dOdP; upper = select( (y_cone_back > -(float)ulp) & (y_cone_back <= g) & (g > 0.0f), t_cone_back , vfloat(neg_inf)); - +#endif return true; } @@ -358,18 +360,22 @@ namespace embree const vfloat O1dO = dot(O1,dO); const vfloat h2 = sqr(O1dO) - dOdO*(sqr(O1) - sqr(r1)); const vfloat rhs1 = select( h2 >= 0.0f, sqrt(h2), vfloat(neg_inf) ); - t_sph1_front = (-O1dO - rhs1)*rcp_dOdO; - t_sph1_back = (-O1dO + rhs1)*rcp_dOdO; /* clip away front hit if it is inside next cone segment */ + t_sph1_front = (-O1dO - rhs1)*rcp_dOdO; const Vec3vf hit_front = org + t_sph1_front*dO; vbool valid_sph1_front = h2 >= 0.0f & yp + t_sph1_front*dOdP > g & !coneR.isClippedByPlane (valid, hit_front); lower = select(valid_sph1_front, t_sph1_front, vfloat(pos_inf)); +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) /* clip away back hit if it is inside next cone segment */ + t_sph1_back = (-O1dO + rhs1)*rcp_dOdO; const Vec3vf hit_back = org + t_sph1_back*dO; vbool valid_sph1_back = h2 >= 0.0f & yp + t_sph1_back*dOdP > g & !coneR.isClippedByPlane (valid, hit_back); upper = select(valid_sph1_back, t_sph1_back, vfloat(neg_inf)); +#else + upper = vfloat(neg_inf); +#endif } __forceinline void intersectBeginSphere(const vbool& valid, @@ -380,16 +386,20 @@ namespace embree const vfloat O1dO = dot(O1,dO); const vfloat h2 = sqr(O1dO) - dOdO*(sqr(O1) - sqr(r0)); const vfloat rhs1 = select( h2 >= 0.0f, sqrt(h2), vfloat(neg_inf) ); - t_sph0_front = (-O1dO - rhs1)*rcp_dOdO; - t_sph0_back = (-O1dO + rhs1)*rcp_dOdO; /* clip away front hit if it is inside next cone segment */ + t_sph0_front = (-O1dO - rhs1)*rcp_dOdO; vbool valid_sph1_front = valid & h2 >= 0.0f & yp + t_sph0_front*dOdP < 0; lower = select(valid_sph1_front, t_sph0_front, vfloat(pos_inf)); - + +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) /* clip away back hit if it is inside next cone segment */ + t_sph0_back = (-O1dO + rhs1)*rcp_dOdO; vbool valid_sph1_back = valid & h2 >= 0.0f & yp + t_sph0_back*dOdP < 0; upper = select(valid_sph1_back, t_sph0_back, vfloat(neg_inf)); +#else + upper = vfloat(neg_inf); +#endif } /* @@ -421,7 +431,7 @@ namespace embree Ng' = (h-u*dP) - (w0+u*dw)*dw/dP^2*dP Inserting the definition of w0 and dw and refactoring - yield a furhter scaled Ng'': + yield a further scaled Ng'': Ng'' = (dP^2 - dr^2) (h-q) - (r0+u*dr)*dr*dP @@ -439,10 +449,15 @@ namespace embree __forceinline Vec3vf Ng_cone(const vbool& front_hit) const { +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) const vfloat y = select(front_hit, y_cone_front, y_cone_back); const vfloat t = select(front_hit, t_cone_front, t_cone_back); const Vec3vf h = O + t*dO; return g*h-dP*y; +#else + const Vec3vf h = O + t_cone_front*dO; + return g*h-dP*y_cone_front; +#endif } /* compute geometry normal of sphere hit as the difference @@ -450,14 +465,22 @@ namespace embree __forceinline Vec3vf Ng_sphere1(const vbool& front_hit) const { +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) const vfloat t_sph1 = select(front_hit, t_sph1_front, t_sph1_back); return org+t_sph1*dO-p1; +#else + return org+t_sph1_front*dO-p1; +#endif } __forceinline Vec3vf Ng_sphere0(const vbool& front_hit) const { +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) const vfloat t_sph0 = select(front_hit, t_sph0_front, t_sph0_back); return org+t_sph0*dO-p0; +#else + return org+t_sph0_front*dO-p0; +#endif } /* @@ -470,8 +493,12 @@ namespace embree __forceinline vfloat u_cone(const vbool& front_hit) const { +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) const vfloat y = select(front_hit, y_cone_front, y_cone_back); return clamp(y*rcp(g)); +#else + return clamp(y_cone_front*rcp(g)); +#endif } private: @@ -487,16 +514,20 @@ namespace embree private: vfloat yp; vfloat y_cone_front; - vfloat y_cone_back; vfloat t_cone_front; +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) + vfloat y_cone_back; vfloat t_cone_back; +#endif /* for ray/sphere intersection */ private: vfloat t_sph1_front; - vfloat t_sph1_back; vfloat t_sph0_front; +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) + vfloat t_sph1_back; vfloat t_sph0_back; +#endif }; @@ -530,29 +561,29 @@ namespace embree /* cone hits inside the neighboring capped cones are inside the geometry and thus ignored */ const ConeGeometry coneL (v0, vL); const ConeGeometry coneR (v1, vR); +#if !defined(EMBREE_BACKFACE_CULLING_CURVES) const Vec3vf hit_lower = ray_org + t_cone_lower*ray_dir; const Vec3vf hit_upper = ray_org + t_cone_upper*ray_dir; t_cone_lower = select (!coneL.isInsideCappedCone (validCone, hit_lower) & !coneR.isInsideCappedCone (validCone, hit_lower), t_cone_lower, vfloat(pos_inf)); t_cone_upper = select (!coneL.isInsideCappedCone (validCone, hit_upper) & !coneR.isInsideCappedCone (validCone, hit_upper), t_cone_upper, vfloat(neg_inf)); +#endif /* intersect ending sphere */ vfloat t_sph1_lower, t_sph1_upper; vfloat t_sph0_lower = vfloat(pos_inf); vfloat t_sph0_upper = vfloat(neg_inf); - vfloat t_sph_lower = vfloat(pos_inf); - vfloat t_sph_upper = vfloat(neg_inf); cone.intersectEndSphere(valid, coneR, t_sph1_lower, t_sph1_upper); const vbool isBeginPoint = valid & (vL[0] == vfloat(pos_inf)); if (unlikely(any(isBeginPoint))) { cone.intersectBeginSphere (isBeginPoint, t_sph0_lower, t_sph0_upper); } - - t_sph_lower = min(t_sph0_lower, t_sph1_lower); - t_sph_upper = max(t_sph0_upper, t_sph1_upper); /* CSG union of cone and end sphere */ + vfloat t_sph_lower = min(t_sph0_lower, t_sph1_lower); vfloat t_cone_sphere_lower = min(t_cone_lower, t_sph_lower); +#if !defined (EMBREE_BACKFACE_CULLING_CURVES) + vfloat t_sph_upper = max(t_sph0_upper, t_sph1_upper); vfloat t_cone_sphere_upper = max(t_cone_upper, t_sph_upper); /* filter out hits that are not in tnear/tfar range */ @@ -591,6 +622,26 @@ namespace embree const bool is_hit_second = epilog(valid_second, hit); return is_hit_first | is_hit_second; +#else + /* filter out hits that are not in tnear/tfar range */ + const vbool valid_lower = valid & ray_tnear <= dt+t_cone_sphere_lower & dt+t_cone_sphere_lower <= ray_tfar() & t_cone_sphere_lower != vfloat(pos_inf); + + /* check if there is a valid hit */ + if (unlikely(none(valid_lower))) + return false; + + /* construct first hit */ + const vbool cone_hit_first = t_cone_sphere_lower == t_cone_lower | t_cone_sphere_lower == t_cone_upper; + const vbool sph0_hit_first = t_cone_sphere_lower == t_sph0_lower | t_cone_sphere_lower == t_sph0_upper; + const Vec3vf Ng_first = select(cone_hit_first, cone.Ng_cone(valid_lower), select (sph0_hit_first, cone.Ng_sphere0(valid_lower), cone.Ng_sphere1(valid_lower))); + const vfloat u_first = select(cone_hit_first, cone.u_cone(valid_lower), select (sph0_hit_first, vfloat(zero), vfloat(one))); + + /* invoke intersection filter for first hit */ + RoundLineIntersectorHitM hit(u_first,zero,dt+t_cone_sphere_lower,Ng_first); + const bool is_hit_first = epilog(valid_lower, hit); + + return is_hit_first; +#endif } } // end namespace __roundline_internal @@ -599,14 +650,15 @@ namespace embree struct RoundLinearCurveIntersector1 { typedef CurvePrecalculations1 Precalculations; - + + template struct ray_tfar { Ray& ray; __forceinline ray_tfar(Ray& ray) : ray(ray) {} __forceinline vfloat operator() () const { return ray.tfar; }; }; - - template + + template static __forceinline bool intersect(const vbool& valid_i, Ray& ray, IntersectContext* context, @@ -619,11 +671,11 @@ namespace embree const Vec3vf ray_org(ray.org.x, ray.org.y, ray.org.z); const Vec3vf ray_dir(ray.dir.x, ray.dir.y, ray.dir.z); const vfloat ray_tnear(ray.tnear()); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); - const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); - const Vec4vf vL = enlargeRadiusToMinWidth(context,geom,ray_org,vLi); - const Vec4vf vR = enlargeRadiusToMinWidth(context,geom,ray_org,vRi); - return __roundline_internal::intersectConeSphere(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray),v0,v1,vL,vR,epilog); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); + const Vec4vf vL = enlargeRadiusToMinWidth(context,geom,ray_org,vLi); + const Vec4vf vR = enlargeRadiusToMinWidth(context,geom,ray_org,vRi); + return __roundline_internal::intersectConeSphere(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray),v0,v1,vL,vR,epilog); } }; @@ -652,11 +704,11 @@ namespace embree const Vec3vf ray_org(ray.org.x[k], ray.org.y[k], ray.org.z[k]); const Vec3vf ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]); const vfloat ray_tnear = ray.tnear()[k]; - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); - const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); - const Vec4vf vL = enlargeRadiusToMinWidth(context,geom,ray_org,vLi); - const Vec4vf vR = enlargeRadiusToMinWidth(context,geom,ray_org,vRi); - return __roundline_internal::intersectConeSphere(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,vL,vR,epilog); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v1 = enlargeRadiusToMinWidth(context,geom,ray_org,v1i); + const Vec4vf vL = enlargeRadiusToMinWidth(context,geom,ray_org,vLi); + const Vec4vf vR = enlargeRadiusToMinWidth(context,geom,ray_org,vRi); + return __roundline_internal::intersectConeSphere(valid_i,ray_org,ray_dir,ray_tnear,ray_tfar(ray,k),v0,v1,vL,vR,epilog); } }; } diff --git a/kernels/geometry/roundlinei_intersector.h b/kernels/geometry/roundlinei_intersector.h index 079817335e..29061d6475 100644 --- a/kernels/geometry/roundlinei_intersector.h +++ b/kernels/geometry/roundlinei_intersector.h @@ -1,18 +1,5 @@ -// ======================================================================== // -// Copyright 2009-2020 Intel Corporation // -// // -// Licensed under the Apache License, Version 2.0 (the "License"); // -// you may not use this file except in compliance with the License. // -// You may obtain a copy of the License at // -// // -// http://www.apache.org/licenses/LICENSE-2.0 // -// // -// Unless required by applicable law or agreed to in writing, software // -// distributed under the License is distributed on an "AS IS" BASIS, // -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // -// See the License for the specific language governing permissions and // -// limitations under the License. // -// ======================================================================== // +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 #pragma once @@ -23,7 +10,7 @@ namespace embree { namespace isa { - template + template struct RoundLinearCurveMiIntersector1 { typedef LineMi Primitive; @@ -34,8 +21,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom); - const vbool valid = line.template valid(); - RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line) @@ -43,8 +30,8 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom); - const vbool valid = line.template valid(); - return RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line) @@ -53,7 +40,7 @@ namespace embree } }; - template + template struct RoundLinearCurveMiMBIntersector1 { typedef LineMi Primitive; @@ -64,8 +51,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()); - const vbool valid = line.template valid(); - RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Intersect1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& line) @@ -73,8 +60,8 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()); - const vbool valid = line.template valid(); - return RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return RoundLinearCurveIntersector1::intersect(valid,ray,context,geom,pre,v0,v1,vL,vR,Occluded1EpilogM(ray,context,line.geomID(),line.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& line) @@ -83,7 +70,7 @@ namespace embree } }; - template + template struct RoundLinearCurveMiIntersectorK { typedef LineMi Primitive; @@ -94,8 +81,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom); - const vbool valid = line.template valid(); - RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& line) @@ -103,12 +90,12 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom); - const vbool valid = line.template valid(); - return RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); } }; - template + template struct RoundLinearCurveMiMBIntersectorK { typedef LineMi Primitive; @@ -119,8 +106,8 @@ namespace embree STAT3(normal.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()[k]); - const vbool valid = line.template valid(); - RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Intersect1KEpilogM(ray,k,context,line.geomID(),line.primID())); } static __forceinline bool occluded(const Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& line) @@ -128,8 +115,8 @@ namespace embree STAT3(shadow.trav_prims,1,1,1); const LineSegments* geom = context->scene->get(line.geomID()); Vec4vf v0,v1,vL,vR; line.gather(v0,v1,vL,vR,geom,ray.time()[k]); - const vbool valid = line.template valid(); - return RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); + const vbool valid = line.valid(); + return RoundLinearCurveIntersectorK::intersect(valid,ray,k,context,geom,pre,v0,v1,vL,vR,Occluded1KEpilogM(ray,k,context,line.geomID(),line.primID())); } }; } diff --git a/kernels/geometry/sphere_intersector.h b/kernels/geometry/sphere_intersector.h index 3ab90c29ef..2670f9762d 100644 --- a/kernels/geometry/sphere_intersector.h +++ b/kernels/geometry/sphere_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -105,7 +105,7 @@ namespace embree const Precalculations& pre, const Vec4vf& v0i, const Epilog& epilog) { const Vec3vf ray_org(ray.org.x, ray.org.y, ray.org.z); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); return intersect(valid_i,ray,pre,v0,epilog); } }; @@ -130,7 +130,7 @@ namespace embree const Vec3vf ray_dir(ray.dir.x[k], ray.dir.y[k], ray.dir.z[k]); const vfloat rd2 = rcp(dot(ray_dir, ray_dir)); - const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); + const Vec4vf v0 = enlargeRadiusToMinWidth(context,geom,ray_org,v0i); const Vec3vf center = v0.xyz(); const vfloat radius = v0.w; diff --git a/kernels/geometry/spherei_intersector.h b/kernels/geometry/spherei_intersector.h index 1146847602..7a0b428117 100644 --- a/kernels/geometry/spherei_intersector.h +++ b/kernels/geometry/spherei_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,7 +11,7 @@ namespace embree { namespace isa { - template + template struct SphereMiIntersector1 { typedef PointMi Primitive; @@ -25,9 +25,9 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom); - const vbool valid = sphere.template valid(); - SphereIntersector1::intersect( - valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, sphere.geomID(), sphere.primID())); + const vbool valid = sphere.valid(); + SphereIntersector1::intersect( + valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, sphere.geomID(), sphere.primID())); } static __forceinline bool occluded(const Precalculations& pre, @@ -38,9 +38,9 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom); - const vbool valid = sphere.template valid(); - return SphereIntersector1::intersect( - valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, sphere.geomID(), sphere.primID())); + const vbool valid = sphere.valid(); + return SphereIntersector1::intersect( + valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, sphere.geomID(), sphere.primID())); } static __forceinline bool pointQuery(PointQuery* query, @@ -51,7 +51,7 @@ namespace embree } }; - template + template struct SphereMiMBIntersector1 { typedef PointMi Primitive; @@ -65,9 +65,9 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom, ray.time()); - const vbool valid = sphere.template valid(); - SphereIntersector1::intersect( - valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, sphere.geomID(), sphere.primID())); + const vbool valid = sphere.valid(); + SphereIntersector1::intersect( + valid, ray, context, geom, pre, v0, Intersect1EpilogM(ray, context, sphere.geomID(), sphere.primID())); } static __forceinline bool occluded(const Precalculations& pre, @@ -78,9 +78,9 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom, ray.time()); - const vbool valid = sphere.template valid(); - return SphereIntersector1::intersect( - valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, sphere.geomID(), sphere.primID())); + const vbool valid = sphere.valid(); + return SphereIntersector1::intersect( + valid, ray, context, geom, pre, v0, Occluded1EpilogM(ray, context, sphere.geomID(), sphere.primID())); } static __forceinline bool pointQuery(PointQuery* query, @@ -91,7 +91,7 @@ namespace embree } }; - template + template struct SphereMiIntersectorK { typedef PointMi Primitive; @@ -103,10 +103,10 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom); - const vbool valid = sphere.template valid(); - SphereIntersectorK::intersect( + const vbool valid = sphere.valid(); + SphereIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Intersect1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); + Intersect1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); } static __forceinline bool occluded( @@ -115,14 +115,14 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom); - const vbool valid = sphere.template valid(); - return SphereIntersectorK::intersect( + const vbool valid = sphere.valid(); + return SphereIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Occluded1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); + Occluded1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); } }; - template + template struct SphereMiMBIntersectorK { typedef PointMi Primitive; @@ -134,10 +134,10 @@ namespace embree STAT3(normal.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom, ray.time()[k]); - const vbool valid = sphere.template valid(); - SphereIntersectorK::intersect( + const vbool valid = sphere.valid(); + SphereIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Intersect1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); + Intersect1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); } static __forceinline bool occluded( @@ -146,10 +146,10 @@ namespace embree STAT3(shadow.trav_prims, 1, 1, 1); const Points* geom = context->scene->get(sphere.geomID()); Vec4vf v0; sphere.gather(v0, geom, ray.time()[k]); - const vbool valid = sphere.template valid(); - return SphereIntersectorK::intersect( + const vbool valid = sphere.valid(); + return SphereIntersectorK::intersect( valid, ray, k, context, geom, pre, v0, - Occluded1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); + Occluded1KEpilogM(ray, k, context, sphere.geomID(), sphere.primID())); } }; } // namespace isa diff --git a/kernels/geometry/subdivpatch1.h b/kernels/geometry/subdivpatch1.h index 94ad46ad87..ae0d4e2616 100644 --- a/kernels/geometry/subdivpatch1.h +++ b/kernels/geometry/subdivpatch1.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/subdivpatch1_intersector.h b/kernels/geometry/subdivpatch1_intersector.h index 74ec1de258..b4b15a1210 100644 --- a/kernels/geometry/subdivpatch1_intersector.h +++ b/kernels/geometry/subdivpatch1_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -43,28 +43,28 @@ namespace embree } /*! Intersect a ray with the primitive. */ - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) GridSOAIntersector1::intersect(pre,ray,context,prim,lazy_node); else processLazyNode(pre,context,prim,lazy_node); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { intersect(This,pre,ray,context,prim,ty,tray,lazy_node); } /*! Test if the ray is occluded by the primitive */ - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) return GridSOAIntersector1::occluded(pre,ray,context,prim,lazy_node); else return processLazyNode(pre,context,prim,lazy_node); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { return occluded(This,pre,ray,context,prim,ty,tray,lazy_node); } @@ -100,28 +100,28 @@ namespace embree } /*! Intersect a ray with the primitive. */ - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) GridSOAMBIntersector1::intersect(pre,ray,context,prim,lazy_node); else processLazyNode(pre,ray,context,prim,lazy_node); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { intersect(This,pre,ray,context,prim,ty,tray,lazy_node); } /*! Test if the ray is occluded by the primitive */ - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) return GridSOAMBIntersector1::occluded(pre,ray,context,prim,lazy_node); else return processLazyNode(pre,ray,context,prim,lazy_node); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { return occluded(This,pre,ray,context,prim,ty,tray,lazy_node); } @@ -133,7 +133,7 @@ namespace embree return false; } - template + template static __forceinline bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context, size_t ty0, const Primitive* prim, size_t ty, const TravPointQuery &tquery, size_t& lazy_node) { return pointQuery(This,query,context,prim,ty,tquery,lazy_node); } @@ -166,15 +166,15 @@ namespace embree else return processLazyNode(pre,context,prim,lazy_node); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) GridSOAIntersectorK::intersect(pre,ray,k,context,prim,lazy_node); else processLazyNode(pre,context,prim,lazy_node); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) return GridSOAIntersectorK::occluded(pre,ray,k,context,prim,lazy_node); else return processLazyNode(pre,context,prim,lazy_node); @@ -215,15 +215,15 @@ namespace embree else return processLazyNode(pre,context,prim,lazy_node); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) GridSOAMBIntersectorK::intersect(pre,ray,k,context,prim,lazy_node); else processLazyNode(pre,context,prim,lazy_node); } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t ty, const TravRay &tray, size_t& lazy_node) { if (likely(ty == 0)) return GridSOAMBIntersectorK::occluded(pre,ray,k,context,prim,lazy_node); else return processLazyNode(pre,context,prim,lazy_node); diff --git a/kernels/geometry/subgrid.h b/kernels/geometry/subgrid.h index 39fa6fb0f0..ce54421cab 100644 --- a/kernels/geometry/subgrid.h +++ b/kernels/geometry/subgrid.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/subgrid_intersector.h b/kernels/geometry/subgrid_intersector.h index 045eee4329..e241073812 100644 --- a/kernels/geometry/subgrid_intersector.h +++ b/kernels/geometry/subgrid_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -53,14 +53,14 @@ namespace embree return accel->pointQuery(query, context); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); #if defined(__AVX__) STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1); @@ -75,15 +75,15 @@ namespace embree } } } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); while(mask != 0) { @@ -155,14 +155,14 @@ namespace embree return accel->pointQuery(query, context); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); #if defined(__AVX__) STAT3(normal.trav_hit_boxes[popcnt(mask)],1,1,1); @@ -178,14 +178,14 @@ namespace embree } } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); while(mask != 0) { @@ -264,8 +264,8 @@ namespace embree const Vec3vf p2 = vtx[i*4+2]; const Vec3vf p3 = vtx[i*4+3]; STAT3(shadow.trav_prims,1,popcnt(valid0),K); - if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i))) - break; + pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)); + if (none(valid0)) break; } return !valid0; } @@ -326,14 +326,14 @@ namespace embree return !valid0; } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); while(mask != 0) { @@ -346,14 +346,14 @@ namespace embree } } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); while(mask != 0) { @@ -408,8 +408,8 @@ namespace embree const Vec3vf p2 = vtx[i*4+2]; const Vec3vf p3 = vtx[i*4+3]; STAT3(shadow.trav_prims,1,popcnt(valid0),K); - if (pre.intersectK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i))) - break; + pre.occludedK(valid0,ray,p0,p1,p2,p3,g,subgrid,i,OccludedKEpilogM<4,K,filter>(valid0,ray,context,subgrid.geomID(),subgrid.primID(),i)); + if (none(valid0)) break; } return !valid0; } @@ -470,14 +470,14 @@ namespace embree return !valid0; } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); while(mask != 0) { @@ -490,14 +490,14 @@ namespace embree } } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,dist); while(mask != 0) { @@ -511,8 +511,5 @@ namespace embree return false; } }; - - - } } diff --git a/kernels/geometry/subgrid_intersector_moeller.h b/kernels/geometry/subgrid_intersector_moeller.h index 52b44c19c5..64937d34fe 100644 --- a/kernels/geometry/subgrid_intersector_moeller.h +++ b/kernels/geometry/subgrid_intersector_moeller.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -16,13 +16,13 @@ namespace embree /* ----------------------------- */ template - __forceinline void interpolateUV(MoellerTrumboreHitM &hit,const GridMesh::Grid &g, const SubGrid& subgrid) + __forceinline void interpolateUV(MoellerTrumboreHitM> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint &stepX, const vint &stepY) { /* correct U,V interpolation across the entire grid */ const vint sx((int)subgrid.x()); const vint sy((int)subgrid.y()); - const vint sxM(sx + vint(0,1,1,0)); - const vint syM(sy + vint(0,0,1,1)); + const vint sxM(sx + stepX); + const vint syM(sy + stepY); const float inv_resX = rcp((float)((int)g.resX-1)); const float inv_resY = rcp((float)((int)g.resY-1)); hit.U = (hit.U + (vfloat)sxM * hit.absDen) * inv_resX; @@ -43,23 +43,24 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid& subgrid) const { - MoellerTrumboreHitM hit; + UVIdentity mapUV; + MoellerTrumboreHitM> hit(mapUV); MoellerTrumboreIntersector1 intersector(ray,nullptr); Intersect1EpilogMU epilog(ray,context,subgrid.geomID(),subgrid.primID()); /* intersect first triangle */ - if (intersector.intersect(ray,v0,v1,v3,hit)) + if (intersector.intersect(ray,v0,v1,v3,mapUV,hit)) { - interpolateUV(hit,g,subgrid); + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); epilog(hit.valid,hit); } /* intersect second triangle */ - if (intersector.intersect(ray,v2,v3,v1,hit)) + if (intersector.intersect(ray,v2,v3,v1,mapUV,hit)) { hit.U = hit.absDen - hit.U; hit.V = hit.absDen - hit.V; - interpolateUV(hit,g,subgrid); + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); epilog(hit.valid,hit); } } @@ -68,24 +69,25 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid& subgrid) const { - MoellerTrumboreHitM hit; + UVIdentity mapUV; + MoellerTrumboreHitM> hit(mapUV); MoellerTrumboreIntersector1 intersector(ray,nullptr); Occluded1EpilogMU epilog(ray,context,subgrid.geomID(),subgrid.primID()); /* intersect first triangle */ - if (intersector.intersect(ray,v0,v1,v3,hit)) + if (intersector.intersect(ray,v0,v1,v3,mapUV,hit)) { - interpolateUV(hit,g,subgrid); + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) return true; } /* intersect second triangle */ - if (intersector.intersect(ray,v2,v3,v1,hit)) + if (intersector.intersect(ray,v2,v3,v1,mapUV,hit)) { hit.U = hit.absDen - hit.U; hit.V = hit.absDen - hit.V; - interpolateUV(hit,g,subgrid); + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) return true; } @@ -114,31 +116,19 @@ namespace embree const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); #endif - MoellerTrumboreHitM<8> hit; + UVIdentity<8> mapUV; + MoellerTrumboreHitM<8,UVIdentity<8>> hit(mapUV); MoellerTrumboreIntersector1<8> intersector(ray,nullptr); const vbool8 flags(0,0,0,0,1,1,1,1); - if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,hit))) + if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit))) { - vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen; - -#if !defined(EMBREE_BACKFACE_CULLING) - hit.U = select(flags,absDen-V,U); - hit.V = select(flags,absDen-U,V); - hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); -#else - hit.U = select(flags,absDen-U,U); - hit.V = select(flags,absDen-V,V); -#endif - /* correct U,V interpolation across the entire grid */ - const vint8 sx((int)subgrid.x()); - const vint8 sy((int)subgrid.y()); - const vint8 sx8(sx + vint8(0,1,1,0,0,1,1,0)); - const vint8 sy8(sy + vint8(0,0,1,1,0,0,1,1)); - const float inv_resX = rcp((float)((int)g.resX-1)); - const float inv_resY = rcp((float)((int)g.resY-1)); - hit.U = (hit.U + (vfloat8)sx8 * absDen) * inv_resX; - hit.V = (hit.V + (vfloat8)sy8 * absDen) * inv_resY; - + /* correct U,V interpolation across the entire grid */ + const vfloat8 U = select(flags,hit.absDen - hit.V,hit.U); + const vfloat8 V = select(flags,hit.absDen - hit.U,hit.V); + hit.U = U; + hit.V = V; + hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); + interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); if (unlikely(epilog(hit.valid,hit))) return true; } @@ -172,132 +162,24 @@ namespace embree /* ----------------------------- */ template - struct SubGridQuadHitK - { - __forceinline SubGridQuadHitK(const vfloat& U, - const vfloat& V, - const vfloat& T, - const vfloat& absDen, - const Vec3vf& Ng, - const vbool& flags, - const GridMesh::Grid &g, - const SubGrid& subgrid, - const unsigned int i) - : U(U), V(V), T(T), absDen(absDen), flags(flags), tri_Ng(Ng), g(g), subgrid(subgrid), i(i) {} - - __forceinline std::tuple,vfloat,vfloat,Vec3vf> operator() () const - { - const vfloat rcpAbsDen = rcp(absDen); - const vfloat t = T * rcpAbsDen; - const vfloat u0 = U * rcpAbsDen; - const vfloat v0 = V * rcpAbsDen; - const vfloat u1 = vfloat(1.0f) - u0; - const vfloat v1 = vfloat(1.0f) - v0; - const vfloat uu = select(flags,u1,u0); - const vfloat vv = select(flags,v1,v0); - const unsigned int sx = subgrid.x() + (unsigned int)(i % 2); - const unsigned int sy = subgrid.y() + (unsigned int)(i >>1); - const float inv_resX = rcp((float)(int)(g.resX-1)); - const float inv_resY = rcp((float)(int)(g.resY-1)); - const vfloat u = (uu + (float)(int)sx) * inv_resX; - const vfloat v = (vv + (float)(int)sy) * inv_resY; - const Vec3vf Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z); - return std::make_tuple(u,v,t,Ng); - } - - private: - const vfloat U; - const vfloat V; - const vfloat T; - const vfloat absDen; - const vbool flags; - const Vec3vf tri_Ng; - - const GridMesh::Grid &g; - const SubGrid& subgrid; - const size_t i; - }; - + __forceinline void interpolateUV(const vbool& valid, MoellerTrumboreHitK> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const unsigned int i) + { + /* correct U,V interpolation across the entire grid */ + const unsigned int sx = subgrid.x() + (unsigned int)(i % 2); + const unsigned int sy = subgrid.y() + (unsigned int)(i >>1); + const float inv_resX = rcp((float)(int)(g.resX-1)); + const float inv_resY = rcp((float)(int)(g.resY-1)); + hit.U = select(valid,(hit.U + vfloat((float)sx) * hit.absDen) * inv_resX,hit.U); + hit.V = select(valid,(hit.V + vfloat((float)sy) * hit.absDen) * inv_resY,hit.V); + } + template struct SubGridQuadMIntersectorKMoellerTrumboreBase { __forceinline SubGridQuadMIntersectorKMoellerTrumboreBase(const vbool& valid, const RayK& ray) {} - - template - __forceinline vbool intersectK(const vbool& valid0, - RayK& ray, - const Vec3vf& tri_v0, - const Vec3vf& tri_e1, - const Vec3vf& tri_e2, - const Vec3vf& tri_Ng, - const vbool& flags, - const GridMesh::Grid &g, - const SubGrid &subgrid, - const unsigned int i, - const Epilog& epilog) const - { - /* calculate denominator */ - vbool valid = valid0; - const Vec3vf C = tri_v0 - ray.org; - const Vec3vf R = cross(C,ray.dir); - const vfloat den = dot(tri_Ng,ray.dir); - const vfloat absDen = abs(den); - const vfloat sgnDen = signmsk(den); - - /* test against edge p2 p0 */ - const vfloat U = dot(R,tri_e2) ^ sgnDen; - valid &= U >= 0.0f; - if (likely(none(valid))) return false; - - /* test against edge p0 p1 */ - const vfloat V = dot(R,tri_e1) ^ sgnDen; - valid &= V >= 0.0f; - if (likely(none(valid))) return false; - - /* test against edge p1 p2 */ - const vfloat W = absDen-U-V; - valid &= W >= 0.0f; - if (likely(none(valid))) return false; - - /* perform depth test */ - const vfloat T = dot(tri_Ng,C) ^ sgnDen; - valid &= (absDen*ray.tnear() < T) & (T <= absDen*ray.tfar); - if (unlikely(none(valid))) return false; - - /* perform backface culling */ -#if defined(EMBREE_BACKFACE_CULLING) - valid &= den < vfloat(zero); - if (unlikely(none(valid))) return false; -#else - valid &= den != vfloat(zero); - if (unlikely(none(valid))) return false; -#endif - - /* calculate hit information */ - SubGridQuadHitK hit(U,V,T,absDen,tri_Ng,flags,g,subgrid,i); - return epilog(valid,hit); - } - - template - __forceinline vbool intersectK(const vbool& valid0, - RayK& ray, - const Vec3vf& tri_v0, - const Vec3vf& tri_v1, - const Vec3vf& tri_v2, - const vbool& flags, - const GridMesh::Grid &g, - const SubGrid &subgrid, - const unsigned int i, - const Epilog& epilog) const - { - const Vec3vf e1 = tri_v0-tri_v1; - const Vec3vf e2 = tri_v2-tri_v0; - const Vec3vf Ng = cross(e2,e1); - return intersectK(valid0,ray,tri_v0,e1,e2,Ng,flags,g,subgrid,i,epilog); - } template - __forceinline bool intersectK(const vbool& valid0, + __forceinline bool intersectK(const vbool& valid, RayK& ray, const Vec3vf& v0, const Vec3vf& v1, @@ -308,49 +190,62 @@ namespace embree const unsigned int i, const Epilog& epilog) const { - intersectK(valid0,ray,v0,v1,v3,vbool(false),g,subgrid,i,epilog); - if (none(valid0)) return true; - intersectK(valid0,ray,v2,v3,v1,vbool(true ),g,subgrid,i,epilog); - return none(valid0); + UVIdentity mapUV; + MoellerTrumboreHitK> hit(mapUV); + MoellerTrumboreIntersectorK intersector; + + const vbool valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit); + if (any(valid0)) + { + interpolateUV(valid0,hit,g,subgrid,i); + epilog(valid0,hit); + } + const vbool valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit); + if (any(valid1)) + { + hit.U = hit.absDen - hit.U; + hit.V = hit.absDen - hit.V; + interpolateUV(valid1,hit,g,subgrid,i); + epilog(valid1,hit); + } + return any(valid0|valid1); } - static __forceinline bool intersect1(RayK& ray, - size_t k, - const Vec3vf& tri_v0, - const Vec3vf& tri_e1, - const Vec3vf& tri_e2, - const Vec3vf& tri_Ng, - MoellerTrumboreHitM &hit) + template + __forceinline bool occludedK(const vbool& valid, + RayK& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const Vec3vf& v3, + const GridMesh::Grid &g, + const SubGrid &subgrid, + const unsigned int i, + const Epilog& epilog) const { - /* calculate denominator */ - const Vec3vf O = broadcast>(ray.org,k); - const Vec3vf D = broadcast>(ray.dir,k); - const Vec3vf C = Vec3vf(tri_v0) - O; - const Vec3vf R = cross(C,D); - const vfloat den = dot(Vec3vf(tri_Ng),D); - const vfloat absDen = abs(den); - const vfloat sgnDen = signmsk(den); - - /* perform edge tests */ - const vfloat U = dot(R,Vec3vf(tri_e2)) ^ sgnDen; - const vfloat V = dot(R,Vec3vf(tri_e1)) ^ sgnDen; - - /* perform backface culling */ -#if defined(EMBREE_BACKFACE_CULLING) - vbool valid = (den < vfloat(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); -#else - vbool valid = (den != vfloat(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); -#endif - if (likely(none(valid))) return false; - - /* perform depth test */ - const vfloat T = dot(Vec3vf(tri_Ng),C) ^ sgnDen; - valid &= (absDen*vfloat(ray.tnear()[k]) < T) & (T <= absDen*vfloat(ray.tfar[k])); - if (likely(none(valid))) return false; - - /* calculate hit information */ - new (&hit) MoellerTrumboreHitM(valid,U,V,T,absDen,tri_Ng); - return true; + UVIdentity mapUV; + MoellerTrumboreHitK> hit(mapUV); + MoellerTrumboreIntersectorK intersector; + + vbool valid_final = valid; + const vbool valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit); + if (any(valid0)) + { + interpolateUV(valid0,hit,g,subgrid,i); + epilog(valid0,hit); + valid_final &= !valid0; + } + if (none(valid_final)) return true; + const vbool valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit); + if (any(valid1)) + { + hit.U = hit.absDen - hit.U; + hit.V = hit.absDen - hit.V; + interpolateUV(valid1,hit,g,subgrid,i); + epilog(valid1,hit); + valid_final &= !valid1; + } + return none(valid_final); } static __forceinline bool intersect1(RayK& ray, @@ -358,14 +253,15 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, - MoellerTrumboreHitM &hit) + MoellerTrumboreHitM> &hit) { const Vec3vf e1 = v0-v1; const Vec3vf e2 = v2-v0; - const Vec3vf Ng = cross(e2,e1); - return intersect1(ray,k,v0,e1,e2,Ng,hit); + MoellerTrumboreIntersectorK<8,K> intersector; + UVIdentity mapUV; + return intersector.intersectEdge(ray,k,v0,e1,e2,mapUV,hit); } - + }; template @@ -377,42 +273,47 @@ namespace embree __forceinline void intersect1(RayHitK& ray, size_t k, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const { + UVIdentity mapUV; + MoellerTrumboreHitM> hit(mapUV); Intersect1KEpilogMU epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); + MoellerTrumboreIntersectorK intersector; + /* intersect first triangle */ + if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit)) + { + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); + epilog(hit.valid,hit); + } - MoellerTrumboreHitM<4> hit; - if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,hit)) - { - interpolateUV(hit,g,subgrid); - epilog(hit.valid,hit); - } - - if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,hit)) - { - hit.U = hit.absDen - hit.U; - hit.V = hit.absDen - hit.V; - interpolateUV(hit,g,subgrid); - epilog(hit.valid,hit); - } - + /* intersect second triangle */ + if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit)) + { + hit.U = hit.absDen - hit.U; + hit.V = hit.absDen - hit.V; + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); + epilog(hit.valid,hit); + } } __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const { - Occluded1KEpilogMU epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); - - MoellerTrumboreHitM<4> hit; - if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,hit)) + UVIdentity mapUV; + MoellerTrumboreHitM> hit(mapUV); + Occluded1KEpilogMU epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); + MoellerTrumboreIntersectorK intersector; + /* intersect first triangle */ + if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit)) { - interpolateUV(hit,g,subgrid); + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) return true; } - if (SubGridQuadMIntersectorKMoellerTrumboreBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,hit)) + /* intersect second triangle */ + if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit)) { hit.U = hit.absDen - hit.U; - hit.V = hit.absDen - hit.V; - interpolateUV(hit,g,subgrid); + hit.V = hit.absDen - hit.V; + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) return true; } return false; @@ -443,28 +344,16 @@ namespace embree #endif const vbool8 flags(0,0,0,0,1,1,1,1); - MoellerTrumboreHitM<8> hit; + UVIdentity<8> mapUV; + MoellerTrumboreHitM<8,UVIdentity<8>> hit(mapUV); if (SubGridQuadMIntersectorKMoellerTrumboreBase<8,K,filter>::intersect1(ray,k,vtx0,vtx1,vtx2,hit)) { - vfloat8 U = hit.U, V = hit.V, absDen = hit.absDen; -#if !defined(EMBREE_BACKFACE_CULLING) - hit.U = select(flags,absDen-V,U); - hit.V = select(flags,absDen-U,V); - hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); -#else - hit.U = select(flags,absDen-U,U); - hit.V = select(flags,absDen-V,V); -#endif - - /* correct U,V interpolation across the entire grid */ - const vint8 sx((int)subgrid.x()); - const vint8 sy((int)subgrid.y()); - const vint8 sx8(sx + vint8(0,1,1,0,0,1,1,0)); - const vint8 sy8(sy + vint8(0,0,1,1,0,0,1,1)); - const float inv_resX = rcp((float)((int)g.resX-1)); - const float inv_resY = rcp((float)((int)g.resY-1)); - hit.U = (hit.U + (vfloat8)sx8 * absDen) * inv_resX; - hit.V = (hit.V + (vfloat8)sy8 * absDen) * inv_resY; + const vfloat8 U = select(flags,hit.absDen - hit.V,hit.U); + const vfloat8 V = select(flags,hit.absDen - hit.U,hit.V); + hit.U = U; + hit.V = V; + hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); + interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); if (unlikely(epilog(hit.valid,hit))) return true; diff --git a/kernels/geometry/subgrid_intersector_pluecker.h b/kernels/geometry/subgrid_intersector_pluecker.h index cf13c05714..5ded56e1f7 100644 --- a/kernels/geometry/subgrid_intersector_pluecker.h +++ b/kernels/geometry/subgrid_intersector_pluecker.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -13,60 +13,7 @@ namespace embree { template - struct SubGridQuadHitPlueckerM - { - __forceinline SubGridQuadHitPlueckerM() {} - - __forceinline SubGridQuadHitPlueckerM(const vbool& valid, - const vfloat& U, - const vfloat& V, - const vfloat& UVW, - const vfloat& t, - const Vec3vf& Ng, - const vbool& flags) : valid(valid), vt(t) - { - const vbool invalid = abs(UVW) < min_rcp_input; - const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); - const vfloat u = U * rcpUVW; - const vfloat v = V * rcpUVW; - const vfloat u1 = vfloat(1.0f) - u; - const vfloat v1 = vfloat(1.0f) - v; -#if !defined(__AVX__) || defined(EMBREE_BACKFACE_CULLING) - vu = select(flags,u1,u); - vv = select(flags,v1,v); - vNg = Vec3vf(Ng.x,Ng.y,Ng.z); -#else - const vfloat flip = select(flags,vfloat(-1.0f),vfloat(1.0f)); - vv = select(flags,u1,v); - vu = select(flags,v1,u); - vNg = Vec3vf(flip*Ng.x,flip*Ng.y,flip*Ng.z); -#endif - } - - __forceinline void finalize() - { - } - - __forceinline Vec2f uv(const size_t i) - { - const float u = vu[i]; - const float v = vv[i]; - return Vec2f(u,v); - } - - __forceinline float t(const size_t i) { return vt[i]; } - __forceinline Vec3fa Ng(const size_t i) { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } - - public: - vbool valid; - vfloat vu; - vfloat vv; - vfloat vt; - Vec3vf vNg; - }; - - template - __forceinline void interpolateUV(SubGridQuadHitPlueckerM &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint &stepX, const vint &stepY) + __forceinline void interpolateUV(PlueckerHitM> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const vint &stepX, const vint &stepY) { /* correct U,V interpolation across the entire grid */ const vint sx((int)subgrid.x()); @@ -75,59 +22,10 @@ namespace embree const vint syM(sy + stepY); const float inv_resX = rcp((float)((int)g.resX-1)); const float inv_resY = rcp((float)((int)g.resY-1)); - hit.vu = (hit.vu + vfloat(sxM)) * inv_resX; - hit.vv = (hit.vv + vfloat(syM)) * inv_resY; + hit.U = (hit.U + vfloat(sxM) * hit.UVW) * inv_resX; + hit.V = (hit.V + vfloat(syM) * hit.UVW) * inv_resY; } - - template - __forceinline static bool intersectPluecker(Ray& ray, - const Vec3vf& tri_v0, - const Vec3vf& tri_v1, - const Vec3vf& tri_v2, - const vbool& flags, - SubGridQuadHitPlueckerM &hit) - { - /* calculate vertices relative to ray origin */ - const Vec3vf O = Vec3vf((Vec3fa)ray.org); - const Vec3vf D = Vec3vf((Vec3fa)ray.dir); - const Vec3vf v0 = tri_v0-O; - const Vec3vf v1 = tri_v1-O; - const Vec3vf v2 = tri_v2-O; - - /* calculate triangle edges */ - const Vec3vf e0 = v2-v0; - const Vec3vf e1 = v0-v1; - const Vec3vf e2 = v1-v2; - - /* perform edge tests */ - const vfloat U = dot(cross(e0,v2+v0),D); - const vfloat V = dot(cross(e1,v0+v1),D); - const vfloat W = dot(cross(e2,v1+v2),D); - const vfloat UVW = U+V+W; - const vfloat eps = float(ulp)*abs(UVW); -#if defined(EMBREE_BACKFACE_CULLING) - vbool valid = max(U,V,W) <= eps; -#else - vbool valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); -#endif - if (unlikely(none(valid))) return false; - - /* calculate geometry normal and denominator */ - const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); - const vfloat den = twice(dot(Ng,D)); - - /* perform depth test */ - const vfloat T = twice(dot(v0,Ng)); - const vfloat t = rcp(den)*T; - valid &= vfloat(ray.tnear()) <= t & t <= vfloat(ray.tfar); - valid &= den != vfloat(zero); - if (unlikely(none(valid))) return false; - - /* update hit information */ - new (&hit) SubGridQuadHitPlueckerM(valid,U,V,UVW,t,Ng,flags); - return true; - } - + template struct SubGridQuadMIntersector1Pluecker; @@ -142,19 +40,24 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid& subgrid) const { - SubGridQuadHitPlueckerM hit; + UVIdentity mapUV; + PlueckerHitM> hit(mapUV); + PlueckerIntersector1 intersector(ray,nullptr); + Intersect1EpilogMU epilog(ray,context,subgrid.geomID(),subgrid.primID()); /* intersect first triangle */ - if (intersectPluecker(ray,v0,v1,v3,vbool(false),hit)) + if (intersector.intersect(ray,v0,v1,v3,mapUV,hit)) { interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); epilog(hit.valid,hit); } /* intersect second triangle */ - if (intersectPluecker(ray,v2,v3,v1,vbool(true),hit)) + if (intersector.intersect(ray,v2,v3,v1,mapUV,hit)) { + hit.U = hit.UVW - hit.U; + hit.V = hit.UVW - hit.V; interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); epilog(hit.valid,hit); } @@ -164,25 +67,28 @@ namespace embree const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid& subgrid) const { - SubGridQuadHitPlueckerM hit; + UVIdentity mapUV; + PlueckerHitM> hit(mapUV); + PlueckerIntersector1 intersector(ray,nullptr); Occluded1EpilogMU epilog(ray,context,subgrid.geomID(),subgrid.primID()); - + /* intersect first triangle */ - if (intersectPluecker(ray,v0,v1,v3,vbool(false),hit)) + if (intersector.intersect(ray,v0,v1,v3,mapUV,hit)) { interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) - return true; + return true; } /* intersect second triangle */ - if (intersectPluecker(ray,v2,v3,v1,vbool(true),hit)) + if (intersector.intersect(ray,v2,v3,v1,mapUV,hit)) { + hit.U = hit.UVW - hit.U; + hit.V = hit.UVW - hit.V; interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) - return true; + return true; } - return false; } }; @@ -208,12 +114,20 @@ namespace embree const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); #endif - SubGridQuadHitPlueckerM<8> hit; + + UVIdentity<8> mapUV; + PlueckerHitM<8,UVIdentity<8>> hit(mapUV); + PlueckerIntersector1<8> intersector(ray,nullptr); const vbool8 flags(0,0,0,0,1,1,1,1); - if (unlikely(intersectPluecker(ray,vtx0,vtx1,vtx2,flags,hit))) + if (unlikely(intersector.intersect(ray,vtx0,vtx1,vtx2,mapUV,hit))) { - /* correct U,V interpolation across the entire grid */ - interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); + /* correct U,V interpolation across the entire grid */ + const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U); + const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V); + hit.U = U; + hit.V = V; + hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); + interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); if (unlikely(epilog(hit.valid,hit))) return true; } @@ -243,135 +157,24 @@ namespace embree /* ----------------------------- */ template - struct SubGridQuadHitPlueckerK - { - __forceinline SubGridQuadHitPlueckerK(const vfloat& U, - const vfloat& V, - const vfloat& UVW, - const vfloat& t, - const Vec3vf& Ng, - const vbool& flags, - const GridMesh::Grid &g, - const SubGrid& subgrid, - const unsigned int i) - : U(U), V(V), UVW(UVW), t(t), flags(flags), tri_Ng(Ng), g(g), subgrid(subgrid), i(i) {} - - __forceinline std::tuple,vfloat,vfloat,Vec3vf> operator() () const - { - const vbool invalid = abs(UVW) < min_rcp_input; - const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); - const vfloat u0 = U * rcpUVW; - const vfloat v0 = V * rcpUVW; - const vfloat u1 = vfloat(1.0f) - u0; - const vfloat v1 = vfloat(1.0f) - v0; - const vfloat uu = select(flags,u1,u0); - const vfloat vv = select(flags,v1,v0); - const unsigned int sx = subgrid.x() + (unsigned int)(i % 2); - const unsigned int sy = subgrid.y() + (unsigned int)(i >>1); - const float inv_resX = rcp((float)(int)(g.resX-1)); - const float inv_resY = rcp((float)(int)(g.resY-1)); - const vfloat u = (uu + (float)(int)sx) * inv_resX; - const vfloat v = (vv + (float)(int)sy) * inv_resY; - const Vec3vf Ng(tri_Ng.x,tri_Ng.y,tri_Ng.z); - return std::make_tuple(u,v,t,Ng); - } - - private: - const vfloat U; - const vfloat V; - const vfloat UVW; - const vfloat t; - const vfloat absDen; - const vbool flags; - const Vec3vf tri_Ng; - - const GridMesh::Grid &g; - const SubGrid& subgrid; - const size_t i; - }; - - + __forceinline void interpolateUV(const vbool& valid, PlueckerHitK> &hit,const GridMesh::Grid &g, const SubGrid& subgrid, const unsigned int i) + { + /* correct U,V interpolation across the entire grid */ + const unsigned int sx = subgrid.x() + (unsigned int)(i % 2); + const unsigned int sy = subgrid.y() + (unsigned int)(i >>1); + const float inv_resX = rcp((float)(int)(g.resX-1)); + const float inv_resY = rcp((float)(int)(g.resY-1)); + hit.U = select(valid,(hit.U + vfloat((float)sx) * hit.UVW) * inv_resX,hit.U); + hit.V = select(valid,(hit.V + vfloat((float)sy) * hit.UVW) * inv_resY,hit.V); + } + template struct SubGridQuadMIntersectorKPlueckerBase { __forceinline SubGridQuadMIntersectorKPlueckerBase(const vbool& valid, const RayK& ray) {} - - template - __forceinline vbool intersectK(const vbool& valid0, - RayK& ray, - const Vec3vf& tri_v0, - const Vec3vf& tri_v1, - const Vec3vf& tri_v2, - const Vec3vf& tri_Ng, - const vbool& flags, - const GridMesh::Grid &g, - const SubGrid &subgrid, - const unsigned int i, - const Epilog& epilog) const - { - /* calculate denominator */ - /* calculate vertices relative to ray origin */ - vbool valid = valid0; - const Vec3vf O = ray.org; - const Vec3vf D = ray.dir; - const Vec3vf v0 = tri_v0-O; - const Vec3vf v1 = tri_v1-O; - const Vec3vf v2 = tri_v2-O; - - /* calculate triangle edges */ - const Vec3vf e0 = v2-v0; - const Vec3vf e1 = v0-v1; - const Vec3vf e2 = v1-v2; - - /* perform edge tests */ - const vfloat U = dot(Vec3vf(cross(e0,v2+v0)),D); - const vfloat V = dot(Vec3vf(cross(e1,v0+v1)),D); - const vfloat W = dot(Vec3vf(cross(e2,v1+v2)),D); - const vfloat UVW = U+V+W; - const vfloat eps = float(ulp)*abs(UVW); -#if defined(EMBREE_BACKFACE_CULLING) - valid &= max(U,V,W) <= eps; -#else - valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); -#endif - if (unlikely(none(valid))) return false; - - /* calculate geometry normal and denominator */ - const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); - const vfloat den = twice(dot(Vec3vf(Ng),D)); - - /* perform depth test */ - const vfloat T = twice(dot(v0,Vec3vf(Ng))); - const vfloat t = rcp(den)*T; - valid &= ray.tnear() <= t & t <= ray.tfar; - valid &= den != vfloat(zero); - if (unlikely(none(valid))) return false; - - /* calculate hit information */ - SubGridQuadHitPlueckerK hit(U,V,UVW,t,tri_Ng,flags,g,subgrid,i); - return epilog(valid,hit); - } - - template - __forceinline vbool intersectK(const vbool& valid0, - RayK& ray, - const Vec3vf& v0, - const Vec3vf& v1, - const Vec3vf& v2, - const vbool& flags, - const GridMesh::Grid &g, - const SubGrid &subgrid, - const unsigned int i, - const Epilog& epilog) const - { - const Vec3vf e1 = v0-v1; - const Vec3vf e2 = v2-v0; - const Vec3vf Ng = cross(e2,e1); - return intersectK(valid0,ray,v0,v1,v2,Ng,flags,g,subgrid,i,epilog); - } template - __forceinline bool intersectK(const vbool& valid0, + __forceinline bool intersectK(const vbool& valid, RayK& ray, const Vec3vf& v0, const Vec3vf& v1, @@ -382,81 +185,70 @@ namespace embree const unsigned int i, const Epilog& epilog) const { - intersectK(valid0,ray,v0,v1,v3,vbool(false),g,subgrid,i,epilog); - if (none(valid0)) return true; - intersectK(valid0,ray,v2,v3,v1,vbool(true ),g,subgrid,i,epilog); - return none(valid0); + UVIdentity mapUV; + PlueckerHitK> hit(mapUV); + PlueckerIntersectorK intersector; + + const vbool valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit); + if (any(valid0)) + { + interpolateUV(valid0,hit,g,subgrid,i); + epilog(valid0,hit); + } + const vbool valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit); + if (any(valid1)) + { + hit.U = hit.UVW - hit.U; + hit.V = hit.UVW - hit.V; + interpolateUV(valid1,hit,g,subgrid,i); + epilog(valid1,hit); + } + return any(valid0|valid1); } - static __forceinline bool intersect1(RayK& ray, - size_t k, - const Vec3vf& tri_v0, - const Vec3vf& tri_v1, - const Vec3vf& tri_v2, - const Vec3vf& tri_Ng, - const vbool& flags, - SubGridQuadHitPlueckerM &hit) + template + __forceinline bool occludedK(const vbool& valid, + RayK& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const Vec3vf& v3, + const GridMesh::Grid &g, + const SubGrid &subgrid, + const unsigned int i, + const Epilog& epilog) const { - /* calculate vertices relative to ray origin */ - const Vec3vf O = broadcast>(ray.org,k); - const Vec3vf D = broadcast>(ray.dir,k); - const Vec3vf v0 = tri_v0-O; - const Vec3vf v1 = tri_v1-O; - const Vec3vf v2 = tri_v2-O; - - /* calculate triangle edges */ - const Vec3vf e0 = v2-v0; - const Vec3vf e1 = v0-v1; - const Vec3vf e2 = v1-v2; - - /* perform edge tests */ - const vfloat U = dot(cross(e0,v2+v0),D); - const vfloat V = dot(cross(e1,v0+v1),D); - const vfloat W = dot(cross(e2,v1+v2),D); - const vfloat UVW = U+V+W; - const vfloat eps = float(ulp)*abs(UVW); -#if defined(EMBREE_BACKFACE_CULLING) - vbool valid = max(U,V,W) <= eps ; -#else - vbool valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); -#endif - if (unlikely(none(valid))) return false; - - /* calculate geometry normal and denominator */ - const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); - const vfloat den = twice(dot(Ng,D)); - - /* perform depth test */ - const vfloat T = twice(dot(v0,Ng)); - const vfloat t = rcp(den)*T; - valid &= vfloat(ray.tnear()[k]) <= t & t <= vfloat(ray.tfar[k]); - if (unlikely(none(valid))) return false; - - /* avoid division by 0 */ - valid &= den != vfloat(zero); - if (unlikely(none(valid))) return false; - - /* update hit information */ - new (&hit) SubGridQuadHitPlueckerM(valid,U,V,UVW,t,tri_Ng,flags); - return true; - } - - static __forceinline bool intersect1(RayK& ray, - size_t k, - const Vec3vf& v0, - const Vec3vf& v1, - const Vec3vf& v2, - const vbool& flags, - SubGridQuadHitPlueckerM &hit) - { - const Vec3vf e1 = v0-v1; - const Vec3vf e2 = v2-v0; - const Vec3vf Ng = cross(e2,e1); // FIXME: optimize!!! - return intersect1(ray,k,v0,v1,v2,Ng,flags,hit); + UVIdentity mapUV; + PlueckerHitK> hit(mapUV); + PlueckerIntersectorK intersector; + + vbool valid_final = valid; + const vbool valid0 = intersector.intersectK(valid,ray,v0,v1,v3,mapUV,hit); + if (any(valid0)) + { + interpolateUV(valid0,hit,g,subgrid,i); + epilog(valid0,hit); + valid_final &= !valid0; + } + if (none(valid_final)) return true; + const vbool valid1 = intersector.intersectK(valid,ray,v2,v3,v1,mapUV,hit); + if (any(valid1)) + { + hit.U = hit.UVW - hit.U; + hit.V = hit.UVW - hit.V; + interpolateUV(valid1,hit,g,subgrid,i); + epilog(valid1,hit); + valid_final &= !valid1; + } + return none(valid_final); } + }; + + + template struct SubGridQuadMIntersectorKPluecker : public SubGridQuadMIntersectorKPlueckerBase { @@ -466,37 +258,48 @@ namespace embree __forceinline void intersect1(RayHitK& ray, size_t k, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const { + UVIdentity mapUV; + PlueckerHitM> hit(mapUV); Intersect1KEpilogMU epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); + PlueckerIntersectorK intersector; + + /* intersect first triangle */ + if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit)) + { + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); + epilog(hit.valid,hit); + } - SubGridQuadHitPlueckerM<4> hit; - if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,vboolf4(false),hit)) - { - interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); - epilog(hit.valid,hit); - } - - if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,vboolf4(true),hit)) - { - interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); - epilog(hit.valid,hit); - } - + /* intersect second triangle */ + if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit)) + { + hit.U = hit.UVW - hit.U; + hit.V = hit.UVW - hit.V; + interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); + epilog(hit.valid,hit); + } } __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, const Vec3vf& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const { - Occluded1KEpilogMU epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); - - SubGridQuadHitPlueckerM<4> hit; - if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v0,v1,v3,vboolf4(false),hit)) + UVIdentity mapUV; + PlueckerHitM> hit(mapUV); + Occluded1KEpilogMU epilog(ray,k,context,subgrid.geomID(),subgrid.primID()); + PlueckerIntersectorK intersector; + + /* intersect first triangle */ + if (intersector.intersect(ray,k,v0,v1,v3,mapUV,hit)) { interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) return true; } - if (SubGridQuadMIntersectorKPlueckerBase<4,K,filter>::intersect1(ray,k,v2,v3,v1,vboolf4(true),hit)) + /* intersect second triangle */ + if (intersector.intersect(ray,k,v2,v3,v1,mapUV,hit)) { + hit.U = hit.UVW - hit.U; + hit.V = hit.UVW - hit.V; interpolateUV(hit,g,subgrid,vint(0,1,1,0),vint(0,0,1,1)); if (epilog(hit.valid,hit)) return true; } @@ -504,5 +307,61 @@ namespace embree } }; + +#if defined (__AVX__) + + /*! Intersects 4 quads with 1 ray using AVX */ + template + struct SubGridQuadMIntersectorKPluecker<4,K,filter> : public SubGridQuadMIntersectorKPlueckerBase<4,K,filter> + { + __forceinline SubGridQuadMIntersectorKPluecker(const vbool& valid, const RayK& ray) + : SubGridQuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {} + + template + __forceinline bool intersect1(RayK& ray, size_t k,const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, + const GridMesh::Grid &g, const SubGrid &subgrid, const Epilog& epilog) const + { + const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z)); +#if !defined(EMBREE_BACKFACE_CULLING) + const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z)); + const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z)); +#else + const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z)); + const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z)); +#endif + UVIdentity<8> mapUV; + PlueckerHitM<8,UVIdentity<8>> hit(mapUV); + PlueckerIntersectorK<8,K> intersector; + const vbool8 flags(0,0,0,0,1,1,1,1); + if (unlikely(intersector.intersect(ray,k,vtx0,vtx1,vtx2,mapUV,hit))) + { + /* correct U,V interpolation across the entire grid */ + const vfloat8 U = select(flags,hit.UVW - hit.V,hit.U); + const vfloat8 V = select(flags,hit.UVW - hit.U,hit.V); + hit.U = U; + hit.V = V; + hit.vNg *= select(flags,vfloat8(-1.0f),vfloat8(1.0f)); + interpolateUV<8>(hit,g,subgrid,vint<8>(0,1,1,0,0,1,1,0),vint<8>(0,0,1,1,0,0,1,1)); + if (unlikely(epilog(hit.valid,hit))) + return true; + } + return false; + } + + __forceinline bool intersect1(RayHitK& ray, size_t k, IntersectContext* context, + const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const + { + return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Intersect1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID())); + } + + __forceinline bool occluded1(RayK& ray, size_t k, IntersectContext* context, + const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const GridMesh::Grid &g, const SubGrid &subgrid) const + { + return intersect1(ray,k,v0,v1,v2,v3,g,subgrid,Occluded1KEpilogMU<8,K,filter>(ray,k,context,subgrid.geomID(),subgrid.primID())); + } + }; +#endif + + } } diff --git a/kernels/geometry/subgrid_mb_intersector.h b/kernels/geometry/subgrid_mb_intersector.h index 400a88b985..473d656e24 100644 --- a/kernels/geometry/subgrid_mb_intersector.h +++ b/kernels/geometry/subgrid_mb_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -45,13 +45,13 @@ namespace embree return PrimitivePointQuery1::pointQuery(query, context, subgrid); } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; const float time = prim[i].adjustTime(ray.time()); assert(time <= 1.0f); @@ -68,15 +68,15 @@ namespace embree } } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; + vfloat dist; size_t mask = isec1.intersect(&prim[i].qnode,tray,time,dist); while(mask != 0) { @@ -132,7 +132,7 @@ namespace embree const GridMesh::Grid &g = mesh->grid(subgrid.primID()); vfloat ftime; - const vint itime = mesh->timeSegment(ray.time(), ftime); + const vint itime = mesh->timeSegment(ray.time(), ftime); Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]); pre.intersect1(ray,k,context,v0,v1,v2,v3,g,subgrid); } @@ -144,7 +144,7 @@ namespace embree const GridMesh::Grid &g = mesh->grid(subgrid.primID()); vfloat ftime; - const vint itime = mesh->timeSegment(ray.time(), ftime); + const vint itime = mesh->timeSegment(ray.time(), ftime); Vec3vf4 v0,v1,v2,v3; subgrid.gatherMB(v0,v1,v2,v3,context->scene,itime[k],ftime[k]); return pre.occluded1(ray,k,context,v0,v1,v2,v3,g,subgrid); } @@ -156,7 +156,7 @@ namespace embree for (size_t j=0;j time = prim[j].adjustTime(ray.time()); + const vfloat time = prim[j].template adjustTime(ray.time()); vfloat dist; while(m_valid) @@ -177,7 +177,7 @@ namespace embree for (size_t j=0;j time = prim[j].adjustTime(ray.time()); + const vfloat time = prim[j].template adjustTime(ray.time()); vfloat dist; while(m_valid) { @@ -190,10 +190,10 @@ namespace embree return !valid0; } - template - static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline void intersect(const Accel::Intersectors* This, Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i dist; @@ -210,10 +210,10 @@ namespace embree } } - template - static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) + template + static __forceinline bool occluded(const Accel::Intersectors* This, Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive* prim, size_t num, const TravRay &tray, size_t& lazy_node) { - BVHNQuantizedBaseNodeIntersector1 isec1; + BVHNQuantizedBaseNodeIntersector1 isec1; for (size_t i=0;i + template struct TriangleMIntersector1Moeller { typedef TriangleM Primitive; - typedef MoellerTrumboreIntersector1 Precalculations; + typedef MoellerTrumboreIntersector1 Precalculations; /*! Intersect a ray with the M triangles and updates the hit. */ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleM& tri) { STAT3(normal.trav_prims,1,1,1); - pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of M triangles. */ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleM& tri) { STAT3(shadow.trav_prims,1,1,1); - return pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersectEdge(ray,tri.v0,tri.e1,tri.e2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -39,11 +39,11 @@ namespace embree }; /*! Intersects M triangles with K rays. */ - template + template struct TriangleMIntersectorKMoeller { typedef TriangleM Primitive; - typedef MoellerTrumboreIntersectorK Precalculations; + typedef MoellerTrumboreIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const TriangleM& tri) @@ -56,7 +56,7 @@ namespace embree const Vec3vf p0 = broadcast>(tri.v0,i); const Vec3vf e1 = broadcast>(tri.e1,i); const Vec3vf e2 = broadcast>(tri.e2,i); - pre.intersectEdgeK(valid_i,ray,p0,e1,e2,IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); + pre.intersectEdgeK(valid_i,ray,p0,e1,e2,UVIdentity(),IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); } } @@ -72,7 +72,7 @@ namespace embree const Vec3vf p0 = broadcast>(tri.v0,i); const Vec3vf e1 = broadcast>(tri.e1,i); const Vec3vf e2 = broadcast>(tri.e2,i); - pre.intersectEdgeK(valid0,ray,p0,e1,e2,OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); + pre.intersectEdgeK(valid0,ray,p0,e1,e2,UVIdentity(),OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); if (none(valid0)) break; } return !valid0; @@ -82,14 +82,14 @@ namespace embree static __forceinline void intersect(Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const TriangleM& tri) { STAT3(normal.trav_prims,1,1,1); - pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const TriangleM& tri) { STAT3(shadow.trav_prims,1,1,1); - return pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + return pre.intersectEdge(ray,k,tri.v0,tri.e1,tri.e2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; } diff --git a/kernels/geometry/triangle_intersector_moeller.h b/kernels/geometry/triangle_intersector_moeller.h index b5a8519236..0a42d8f08b 100644 --- a/kernels/geometry/triangle_intersector_moeller.h +++ b/kernels/geometry/triangle_intersector_moeller.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -18,13 +18,13 @@ namespace embree { namespace isa { - template + template struct MoellerTrumboreHitM { - __forceinline MoellerTrumboreHitM() {} + __forceinline MoellerTrumboreHitM(const UVMapper& mapUV) : mapUV(mapUV) {} - __forceinline MoellerTrumboreHitM(const vbool& valid, const vfloat& U, const vfloat& V, const vfloat& T, const vfloat& absDen, const Vec3vf& Ng) - : U(U), V(V), T(T), absDen(absDen), valid(valid), vNg(Ng) {} + __forceinline MoellerTrumboreHitM(const vbool& valid, const vfloat& U, const vfloat& V, const vfloat& T, const vfloat& absDen, const Vec3vf& Ng, const UVMapper& mapUV) + : U(U), V(V), T(T), absDen(absDen), mapUV(mapUV), valid(valid), vNg(Ng) {} __forceinline void finalize() { @@ -32,8 +32,13 @@ namespace embree vt = T * rcpAbsDen; vu = U * rcpAbsDen; vv = V * rcpAbsDen; + mapUV(vu,vv,vNg); } + __forceinline Vec2vf uv() const { return Vec2vf(vu,vv); } + __forceinline vfloat t () const { return vt; } + __forceinline Vec3vf Ng() const { return vNg; } + __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } __forceinline float t (const size_t i) const { return vt[i]; } __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } @@ -43,6 +48,7 @@ namespace embree vfloat V; vfloat T; vfloat absDen; + UVMapper mapUV; public: vbool valid; @@ -52,20 +58,22 @@ namespace embree Vec3vf vNg; }; - template + template struct MoellerTrumboreIntersector1 { __forceinline MoellerTrumboreIntersector1() {} __forceinline MoellerTrumboreIntersector1(const Ray& ray, const void* ptr) {} + template __forceinline bool intersect(const vbool& valid0, Ray& ray, const Vec3vf& tri_v0, const Vec3vf& tri_e1, const Vec3vf& tri_e2, const Vec3vf& tri_Ng, - MoellerTrumboreHitM& hit) const + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const { /* calculate denominator */ vbool valid = valid0; @@ -88,122 +96,160 @@ namespace embree #else valid &= (den != vfloat(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); #endif - if (likely(none(valid))) return false; + if (likely(early_out && none(valid))) return false; /* perform depth test */ const vfloat T = dot(Vec3vf(tri_Ng),C) ^ sgnDen; valid &= (absDen*vfloat(ray.tnear()) < T) & (T <= absDen*vfloat(ray.tfar)); - if (likely(none(valid))) return false; - - + if (likely(early_out && none(valid))) return false; + /* update hit information */ - new (&hit) MoellerTrumboreHitM(valid,U,V,T,absDen,tri_Ng); + new (&hit) MoellerTrumboreHitM(valid,U,V,T,absDen,tri_Ng,mapUV); return true; } + template + __forceinline bool intersectEdge(const vbool& valid, + Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_e1, + const Vec3vf& tri_e2, + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const + { + const Vec3> tri_Ng = cross(tri_e2,tri_e1); + return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit); + } + + template __forceinline bool intersectEdge(Ray& ray, const Vec3vf& tri_v0, const Vec3vf& tri_e1, const Vec3vf& tri_e2, - MoellerTrumboreHitM& hit) const + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const { vbool valid = true; const Vec3> tri_Ng = cross(tri_e2,tri_e1); - return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,hit); + return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit); } - + + template __forceinline bool intersect(Ray& ray, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, - MoellerTrumboreHitM& hit) const + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const { const Vec3vf e1 = v0-v1; const Vec3vf e2 = v2-v0; - return intersectEdge(ray,v0,e1,e2,hit); + return intersectEdge(ray,v0,e1,e2,mapUV,hit); } + template __forceinline bool intersect(const vbool& valid, Ray& ray, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, - MoellerTrumboreHitM& hit) const + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const { const Vec3vf e1 = v0-v1; const Vec3vf e2 = v2-v0; - return intersectEdge(valid,ray,v0,e1,e2,hit); + return intersectEdge(valid,ray,v0,e1,e2,mapUV,hit); } - template + template __forceinline bool intersectEdge(Ray& ray, const Vec3vf& v0, const Vec3vf& e1, const Vec3vf& e2, + const UVMapper& mapUV, const Epilog& epilog) const { - MoellerTrumboreHitM hit; - if (likely(intersectEdge(ray,v0,e1,e2,hit))) return epilog(hit.valid,hit); + MoellerTrumboreHitM hit(mapUV); + if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit); return false; } - template + template __forceinline bool intersect(Ray& ray, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, + const UVMapper& mapUV, const Epilog& epilog) const { - MoellerTrumboreHitM hit; - if (likely(intersect(ray,v0,v1,v2,hit))) return epilog(hit.valid,hit); + MoellerTrumboreHitM hit(mapUV); + if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); return false; } template + __forceinline bool intersect(Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const Epilog& epilog) const + { + auto mapUV = UVIdentity(); + MoellerTrumboreHitM> hit(mapUV); + if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + template __forceinline bool intersect(const vbool& valid, Ray& ray, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, + const UVMapper& mapUV, const Epilog& epilog) const { - MoellerTrumboreHitM hit; - if (likely(intersect(valid,ray,v0,v1,v2,hit))) return epilog(hit.valid,hit); + MoellerTrumboreHitM hit(mapUV); + if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); return false; } }; - template + template struct MoellerTrumboreHitK { - __forceinline MoellerTrumboreHitK(const vfloat& U, const vfloat& V, const vfloat& T, const vfloat& absDen, const Vec3vf& Ng) - : U(U), V(V), T(T), absDen(absDen), Ng(Ng) {} + __forceinline MoellerTrumboreHitK(const UVMapper& mapUV) : mapUV(mapUV) {} + __forceinline MoellerTrumboreHitK(const vfloat& U, const vfloat& V, const vfloat& T, const vfloat& absDen, const Vec3vf& Ng, const UVMapper& mapUV) + : U(U), V(V), T(T), absDen(absDen), Ng(Ng), mapUV(mapUV) {} __forceinline std::tuple,vfloat,vfloat,Vec3vf> operator() () const { const vfloat rcpAbsDen = rcp(absDen); const vfloat t = T * rcpAbsDen; - const vfloat u = U * rcpAbsDen; - const vfloat v = V * rcpAbsDen; - return std::make_tuple(u,v,t,Ng); + vfloat u = U * rcpAbsDen; + vfloat v = V * rcpAbsDen; + Vec3vf vNg = Ng; + mapUV(u,v,vNg); + return std::make_tuple(u,v,t,vNg); } - private: - const vfloat U; - const vfloat V; + vfloat U; + vfloat V; const vfloat T; const vfloat absDen; const Vec3vf Ng; + const UVMapper& mapUV; }; template struct MoellerTrumboreIntersectorK { + __forceinline MoellerTrumboreIntersectorK() {} __forceinline MoellerTrumboreIntersectorK(const vbool& valid, const RayK& ray) {} /*! Intersects K rays with one of M triangles. */ - template + template __forceinline vbool intersectK(const vbool& valid0, //RayK& ray, const Vec3vf& ray_org, @@ -214,7 +260,8 @@ namespace embree const Vec3vf& tri_e1, const Vec3vf& tri_e2, const Vec3vf& tri_Ng, - const Epilog& epilog) const + const UVMapper& mapUV, + MoellerTrumboreHitK &hit) const { /* calculate denominator */ vbool valid = valid0; @@ -254,11 +301,47 @@ namespace embree #endif /* calculate hit information */ - MoellerTrumboreHitK hit(U,V,T,absDen,tri_Ng); - return epilog(valid,hit); + new (&hit) MoellerTrumboreHitK(U,V,T,absDen,tri_Ng,mapUV); + return valid; + } + + /*! Intersects K rays with one of M triangles. */ + template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + MoellerTrumboreHitK &hit) const + { + const Vec3vf e1 = tri_v0-tri_v1; + const Vec3vf e2 = tri_v2-tri_v0; + const Vec3vf Ng = cross(e2,e1); + return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit); } + /*! Intersects K rays with one of M triangles. */ + template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + MoellerTrumboreHitK> hit(mapUV); + const Vec3vf e1 = tri_v0-tri_v1; + const Vec3vf e2 = tri_v2-tri_v0; + const Vec3vf Ng = cross(e2,e1); + const vbool valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit); + return epilog(valid,hit); + } + + + template __forceinline vbool intersectK(const vbool& valid0, RayK& ray, @@ -267,32 +350,40 @@ namespace embree const Vec3vf& tri_v2, const Epilog& epilog) const { + UVIdentity mapUV; + MoellerTrumboreHitK> hit(mapUV); const Vec3vf e1 = tri_v0-tri_v1; const Vec3vf e2 = tri_v2-tri_v0; const Vec3vf Ng = cross(e2,e1); - return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,epilog); + const vbool valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit); + return epilog(valid,hit); } /*! Intersects K rays with one of M triangles. */ - template + template __forceinline vbool intersectEdgeK(const vbool& valid0, RayK& ray, const Vec3vf& tri_v0, const Vec3vf& tri_e1, - const Vec3vf& tri_e2, + const Vec3vf& tri_e2, + const UVMapper& mapUV, const Epilog& epilog) const { + MoellerTrumboreHitK> hit(mapUV); const Vec3vf tri_Ng = cross(tri_e2,tri_e1); - return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,epilog); + const vbool valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit); + return epilog(valid,hit); } /*! Intersect k'th ray from ray packet of size K with M triangles. */ + template __forceinline bool intersectEdge(RayK& ray, size_t k, const Vec3vf& tri_v0, const Vec3vf& tri_e1, const Vec3vf& tri_e2, - MoellerTrumboreHitM& hit) const + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const { /* calculate denominator */ typedef Vec3vf Vec3vfM; @@ -324,19 +415,21 @@ namespace embree if (likely(none(valid))) return false; /* calculate hit information */ - new (&hit) MoellerTrumboreHitM(valid,U,V,T,absDen,tri_Ng); + new (&hit) MoellerTrumboreHitM(valid,U,V,T,absDen,tri_Ng,mapUV); return true; } + template __forceinline bool intersectEdge(RayK& ray, size_t k, const BBox>& time_range, const Vec3vf& tri_v0, const Vec3vf& tri_e1, - const Vec3vf& tri_e2, - MoellerTrumboreHitM& hit) const + const Vec3vf& tri_e2, + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const { - if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,hit))) + if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,mapUV,hit))) { hit.valid &= time_range.lower <= vfloat(ray.time[k]); hit.valid &= vfloat(ray.time[k]) < time_range.upper; @@ -345,58 +438,87 @@ namespace embree return false; } - template + template + __forceinline bool intersect(RayK& ray, + size_t k, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const UVMapper& mapUV, + MoellerTrumboreHitM& hit) const + { + const Vec3vf e1 = v0-v1; + const Vec3vf e2 = v2-v0; + return intersectEdge(ray,k,v0,e1,e2,mapUV,hit); + } + + template __forceinline bool intersectEdge(RayK& ray, size_t k, const Vec3vf& tri_v0, const Vec3vf& tri_e1, - const Vec3vf& tri_e2, + const Vec3vf& tri_e2, + const UVMapper& mapUV, const Epilog& epilog) const { - MoellerTrumboreHitM hit; - if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit); + MoellerTrumboreHitM hit(mapUV); + if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,mapUV,hit))) return epilog(hit.valid,hit); return false; } - template + template __forceinline bool intersectEdge(RayK& ray, size_t k, const BBox>& time_range, const Vec3vf& tri_v0, const Vec3vf& tri_e1, - const Vec3vf& tri_e2, + const Vec3vf& tri_e2, + const UVMapper& mapUV, const Epilog& epilog) const { - MoellerTrumboreHitM hit; - if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,hit))) return epilog(hit.valid,hit); + MoellerTrumboreHitM hit(mapUV); + if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,mapUV,hit))) return epilog(hit.valid,hit); return false; } - template + template __forceinline bool intersect(RayK& ray, size_t k, const Vec3vf& v0, const Vec3vf& v1, - const Vec3vf& v2, + const Vec3vf& v2, + const UVMapper& mapUV, const Epilog& epilog) const { const Vec3vf e1 = v0-v1; const Vec3vf e2 = v2-v0; - return intersectEdge(ray,k,v0,e1,e2,epilog); + return intersectEdge(ray,k,v0,e1,e2,mapUV,epilog); } template + __forceinline bool intersect(RayK& ray, + size_t k, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const Epilog& epilog) const + { + return intersect(ray,k,v0,v1,v2,UVIdentity(),epilog); + } + + template __forceinline bool intersect(RayK& ray, size_t k, const BBox>& time_range, const Vec3vf& v0, const Vec3vf& v1, const Vec3vf& v2, + const UVMapper& mapUV, const Epilog& epilog) const { const Vec3vf e1 = v0-v1; const Vec3vf e2 = v2-v0; - return intersectEdge(ray,k,time_range,v0,e1,e2,epilog); + return intersectEdge(ray,k,time_range,v0,e1,e2,mapUV,epilog); } }; } diff --git a/kernels/geometry/triangle_intersector_pluecker.h b/kernels/geometry/triangle_intersector_pluecker.h index f1de99d208..8fbefcea88 100644 --- a/kernels/geometry/triangle_intersector_pluecker.h +++ b/kernels/geometry/triangle_intersector_pluecker.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -22,50 +22,60 @@ namespace embree template struct PlueckerHitM { - __forceinline PlueckerHitM(const vfloat& U, const vfloat& V, const vfloat& UVW, const vfloat& t, const Vec3vf& Ng, const UVMapper& mapUV) - : U(U), V(V), UVW(UVW), mapUV(mapUV), vt(t), vNg(Ng) {} + __forceinline PlueckerHitM(const UVMapper& mapUV) : mapUV(mapUV) {} + + __forceinline PlueckerHitM(const vbool& valid, const vfloat& U, const vfloat& V, const vfloat& UVW, const vfloat& t, const Vec3vf& Ng, const UVMapper& mapUV) + : U(U), V(V), UVW(UVW), mapUV(mapUV), valid(valid), vt(t), vNg(Ng) {} __forceinline void finalize() { const vbool invalid = abs(UVW) < min_rcp_input; const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); - vu = U * rcpUVW; - vv = V * rcpUVW; - mapUV(vu,vv); + vu = min(U * rcpUVW,1.0f); + vv = min(V * rcpUVW,1.0f); + mapUV(vu,vv,vNg); } - + + __forceinline Vec2vf uv() const { return Vec2vf(vu,vv); } + __forceinline vfloat t () const { return vt; } + __forceinline Vec3vf Ng() const { return vNg; } + __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } __forceinline float t (const size_t i) const { return vt[i]; } __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } - private: - const vfloat U; - const vfloat V; - const vfloat UVW; + public: + vfloat U; + vfloat V; + vfloat UVW; const UVMapper& mapUV; public: + vbool valid; vfloat vu; vfloat vv; vfloat vt; Vec3vf vNg; }; - template + template struct PlueckerIntersector1 { __forceinline PlueckerIntersector1() {} __forceinline PlueckerIntersector1(const Ray& ray, const void* ptr) {} - template - __forceinline bool intersect(Ray& ray, + template + __forceinline bool intersect(const vbool& valid0, + Ray& ray, const Vec3vf& tri_v0, const Vec3vf& tri_v1, const Vec3vf& tri_v2, const UVMapper& mapUV, - const Epilog& epilog) const + PlueckerHitM& hit) const { + vbool valid = valid0; + /* calculate vertices relative to ray origin */ const Vec3vf O = Vec3vf((Vec3fa)ray.org); const Vec3vf D = Vec3vf((Vec3fa)ray.dir); @@ -85,11 +95,11 @@ namespace embree const vfloat UVW = U+V+W; const vfloat eps = float(ulp)*abs(UVW); #if defined(EMBREE_BACKFACE_CULLING) - vbool valid = max(U,V,W) <= eps; + valid &= max(U,V,W) <= eps; #else - vbool valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); + valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); #endif - if (unlikely(none(valid))) return false; + if (unlikely(early_out && none(valid))) return false; /* calculate geometry normal and denominator */ const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); @@ -100,33 +110,123 @@ namespace embree const vfloat t = rcp(den)*T; valid &= vfloat(ray.tnear()) <= t & t <= vfloat(ray.tfar); valid &= den != vfloat(zero); - if (unlikely(none(valid))) return false; + if (unlikely(early_out && none(valid))) return false; /* update hit information */ - PlueckerHitM hit(U,V,UVW,t,Ng,mapUV); - return epilog(valid,hit); + new (&hit) PlueckerHitM(valid,U,V,UVW,t,Ng,mapUV); + return true; + } + + template + __forceinline bool intersectEdge(const vbool& valid, + Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + } + + template + __forceinline bool intersectEdge(Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + vbool valid = true; + return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + } + + template + __forceinline bool intersect(Ray& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitM& hit) const + { + return intersectEdge(ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + } + + template + __forceinline bool intersectEdge(Ray& ray, + const Vec3vf& v0, + const Vec3vf& e1, + const Vec3vf& e2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; } + + template + __forceinline bool intersect(Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const Epilog& epilog) const + { + auto mapUV = UVIdentity(); + PlueckerHitM> hit(mapUV); + if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(const vbool& valid, + Ray& ray, + const Vec3vf& v0, + const Vec3vf& v1, + const Vec3vf& v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); + return false; + } + }; template struct PlueckerHitK { + __forceinline PlueckerHitK(const UVMapper& mapUV) : mapUV(mapUV) {} + __forceinline PlueckerHitK(const vfloat& U, const vfloat& V, const vfloat& UVW, const vfloat& t, const Vec3vf& Ng, const UVMapper& mapUV) - : U(U), V(V), UVW(UVW), t(t), Ng(Ng), mapUV(mapUV) {} + : U(U), V(V), UVW(UVW), t(t), Ng(Ng), mapUV(mapUV) {} __forceinline std::tuple,vfloat,vfloat,Vec3vf> operator() () const { const vbool invalid = abs(UVW) < min_rcp_input; const vfloat rcpUVW = select(invalid,vfloat(0.0f),rcp(UVW)); - vfloat u = U * rcpUVW; - vfloat v = V * rcpUVW; - mapUV(u,v); - return std::make_tuple(u,v,t,Ng); + vfloat u = min(U * rcpUVW,1.0f); + vfloat v = min(V * rcpUVW,1.0f); + Vec3vf vNg = Ng; + mapUV(u,v,vNg); + return std::make_tuple(u,v,t,vNg); } - - private: - const vfloat U; - const vfloat V; + vfloat U; + vfloat V; const vfloat UVW; const vfloat t; const Vec3vf Ng; @@ -136,17 +236,18 @@ namespace embree template struct PlueckerIntersectorK { + __forceinline PlueckerIntersectorK() {} __forceinline PlueckerIntersectorK(const vbool& valid, const RayK& ray) {} /*! Intersects K rays with one of M triangles. */ - template + template __forceinline vbool intersectK(const vbool& valid0, - RayK& ray, - const Vec3vf& tri_v0, - const Vec3vf& tri_v1, - const Vec3vf& tri_v2, - const UVMapper& mapUV, - const Epilog& epilog) const + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + PlueckerHitK &hit) const { /* calculate vertices relative to ray origin */ vbool valid = valid0; @@ -172,7 +273,7 @@ namespace embree #else valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps); #endif - if (unlikely(none(valid))) return false; + if (unlikely(none(valid))) return valid; /* calculate geometry normal and denominator */ const Vec3vf Ng = stable_triangle_normal(e0,e1,e2); @@ -183,21 +284,49 @@ namespace embree const vfloat t = rcp(den)*T; valid &= ray.tnear() <= t & t <= ray.tfar; valid &= den != vfloat(zero); - if (unlikely(none(valid))) return false; + if (unlikely(none(valid))) return valid; /* calculate hit information */ - PlueckerHitK hit(U,V,UVW,t,Ng,mapUV); - return epilog(valid,hit); + new (&hit) PlueckerHitK(U,V,UVW,t,Ng,mapUV); + return valid; + } + + template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const Epilog& epilog) const + { + UVIdentity mapUV; + PlueckerHitK> hit(mapUV); + const vbool valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + return epilog(valid,hit); } - /*! Intersect k'th ray from ray packet of size K with M triangles. */ template + __forceinline vbool intersectK(const vbool& valid0, + RayK& ray, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitK hit(mapUV); + const vbool valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit); + return epilog(valid,hit); + } + + /*! Intersect k'th ray from ray packet of size K with M triangles. */ + template __forceinline bool intersect(RayK& ray, size_t k, const Vec3vf& tri_v0, const Vec3vf& tri_v1, const Vec3vf& tri_v2, const UVMapper& mapUV, - const Epilog& epilog) const + PlueckerHitM &hit) const { /* calculate vertices relative to ray origin */ const Vec3vf O = broadcast>(ray.org,k); @@ -211,10 +340,12 @@ namespace embree const Vec3vf e1 = v0-v1; const Vec3vf e2 = v1-v2; + /* perform edge tests */ const vfloat U = dot(cross(e0,v2+v0),D); const vfloat V = dot(cross(e1,v0+v1),D); const vfloat W = dot(cross(e2,v1+v2),D); + const vfloat UVW = U+V+W; const vfloat eps = float(ulp)*abs(UVW); #if defined(EMBREE_BACKFACE_CULLING) @@ -239,9 +370,38 @@ namespace embree if (unlikely(none(valid))) return false; /* update hit information */ - PlueckerHitM hit(U,V,UVW,t,Ng,mapUV); - return epilog(valid,hit); + new (&hit) PlueckerHitM(valid,U,V,UVW,t,Ng,mapUV); + return true; } + + template + __forceinline bool intersect(RayK& ray, size_t k, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const UVMapper& mapUV, + const Epilog& epilog) const + { + PlueckerHitM hit(mapUV); + if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit)) + return epilog(hit.valid,hit); + return false; + } + + template + __forceinline bool intersect(RayK& ray, size_t k, + const Vec3vf& tri_v0, + const Vec3vf& tri_v1, + const Vec3vf& tri_v2, + const Epilog& epilog) const + { + UVIdentity mapUV; + PlueckerHitM> hit(mapUV); + if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit)) + return epilog(hit.valid,hit); + return false; + } + }; } } diff --git a/kernels/geometry/triangle_intersector_woop.h b/kernels/geometry/triangle_intersector_woop.h index 63e649d8fb..f05dcc4537 100644 --- a/kernels/geometry/triangle_intersector_woop.h +++ b/kernels/geometry/triangle_intersector_woop.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/triangle_triangle_intersector.h b/kernels/geometry/triangle_triangle_intersector.h index 91b35c36f3..50106bcc16 100644 --- a/kernels/geometry/triangle_triangle_intersector.h +++ b/kernels/geometry/triangle_triangle_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "primitive.h" diff --git a/kernels/geometry/trianglei.h b/kernels/geometry/trianglei.h index 4f3118cc0c..6aad48a5ef 100644 --- a/kernels/geometry/trianglei.h +++ b/kernels/geometry/trianglei.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -343,7 +343,7 @@ namespace embree const TriangleMesh* mesh = scene->get(geomID(index)); vfloat ftime; - const vint itime = mesh->timeSegment(time, ftime); + const vint itime = mesh->timeSegment(time, ftime); const size_t first = bsf(movemask(valid)); if (likely(all(valid,itime[first] == itime))) @@ -352,9 +352,9 @@ namespace embree p1 = getVertex<1>(index, scene, itime[first], ftime); p2 = getVertex<2>(index, scene, itime[first], ftime); } else { - p0 = getVertex<0>(valid, index, scene, itime, ftime); - p1 = getVertex<1>(valid, index, scene, itime, ftime); - p2 = getVertex<2>(valid, index, scene, itime, ftime); + p0 = getVertex<0,K>(valid, index, scene, itime, ftime); + p1 = getVertex<1,K>(valid, index, scene, itime, ftime); + p2 = getVertex<2,K>(valid, index, scene, itime, ftime); } } diff --git a/kernels/geometry/trianglei_intersector.h b/kernels/geometry/trianglei_intersector.h index e2f106a62c..f7deb9e72d 100644 --- a/kernels/geometry/trianglei_intersector.h +++ b/kernels/geometry/trianglei_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -12,24 +12,24 @@ namespace embree namespace isa { /*! Intersects M triangles with 1 ray */ - template + template struct TriangleMiIntersector1Moeller { typedef TriangleMi Primitive; - typedef MoellerTrumboreIntersector1 Precalculations; + typedef MoellerTrumboreIntersector1 Precalculations; static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - pre.intersect(ray,v0,v1,v2,/*UVIdentity(),*/Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersect(ray,v0,v1,v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - return pre.intersect(ray,v0,v1,v2,/*UVIdentity(),*/Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -39,11 +39,11 @@ namespace embree }; /*! Intersects M triangles with K rays */ - template + template struct TriangleMiIntersectorKMoeller { typedef TriangleMi Primitive; - typedef MoellerTrumboreIntersectorK Precalculations; + typedef MoellerTrumboreIntersectorK Precalculations; static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const Primitive& tri) { @@ -55,7 +55,7 @@ namespace embree const Vec3vf v0 = tri.template getVertex<0>(i,scene); const Vec3vf v1 = tri.template getVertex<1>(i,scene); const Vec3vf v2 = tri.template getVertex<2>(i,scene); - pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity(),*/IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); + pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); } } @@ -71,7 +71,7 @@ namespace embree const Vec3vf v0 = tri.template getVertex<0>(i,scene); const Vec3vf v1 = tri.template getVertex<1>(i,scene); const Vec3vf v2 = tri.template getVertex<2>(i,scene); - pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity(),*/OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); + pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); if (none(valid0)) break; } return !valid0; @@ -81,36 +81,36 @@ namespace embree { STAT3(normal.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - pre.intersect(ray,k,v0,v1,v2,/*UVIdentity(),*/Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - return pre.intersect(ray,k,v0,v1,v2,/*UVIdentity(),*/Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; /*! Intersects M triangles with 1 ray */ - template + template struct TriangleMiIntersector1Pluecker { typedef TriangleMi Primitive; - typedef PlueckerIntersector1 Precalculations; + typedef PlueckerIntersector1 Precalculations; static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - pre.intersect(ray,v0,v1,v2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersect(ray,v0,v1,v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - return pre.intersect(ray,v0,v1,v2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -120,11 +120,11 @@ namespace embree }; /*! Intersects M triangles with K rays */ - template + template struct TriangleMiIntersectorKPluecker { typedef TriangleMi Primitive; - typedef PlueckerIntersectorK Precalculations; + typedef PlueckerIntersectorK Precalculations; static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const Primitive& tri) { @@ -136,7 +136,7 @@ namespace embree const Vec3vf v0 = tri.template getVertex<0>(i,scene); const Vec3vf v1 = tri.template getVertex<1>(i,scene); const Vec3vf v2 = tri.template getVertex<2>(i,scene); - pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity(),IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); + pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); } } @@ -152,7 +152,7 @@ namespace embree const Vec3vf v0 = tri.template getVertex<0>(i,scene); const Vec3vf v1 = tri.template getVertex<1>(i,scene); const Vec3vf v2 = tri.template getVertex<2>(i,scene); - pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity(),OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); + pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); if (none(valid0)) break; } return !valid0; @@ -162,30 +162,30 @@ namespace embree { STAT3(normal.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0, v1, v2; tri.gather(v0,v1,v2,context->scene); - return pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; /*! Intersects M motion blur triangles with 1 ray */ - template + template struct TriangleMiMBIntersector1Moeller { typedef TriangleMi Primitive; - typedef MoellerTrumboreIntersector1 Precalculations; + typedef MoellerTrumboreIntersector1 Precalculations; /*! Intersect a ray with the M triangles and updates the hit. */ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); - pre.intersect(ray,v0,v1,v2,/*UVIdentity(),*/Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersect(ray,v0,v1,v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of M triangles. */ @@ -193,7 +193,7 @@ namespace embree { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); - return pre.intersect(ray,v0,v1,v2,/*UVIdentity(),*/Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -203,11 +203,11 @@ namespace embree }; /*! Intersects M motion blur triangles with K rays. */ - template + template struct TriangleMiMBIntersectorKMoeller { typedef TriangleMi Primitive; - typedef MoellerTrumboreIntersectorK Precalculations; + typedef MoellerTrumboreIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const TriangleMi& tri) @@ -216,8 +216,8 @@ namespace embree { if (!tri.valid(i)) break; STAT3(normal.trav_prims,1,popcnt(valid_i),K); - Vec3vf v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); - pre.intersectK(valid_i,ray,v0,v1,v2,/*UVIdentity(),*/IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); + Vec3vf v0,v1,v2; tri.template gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); + pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); } } @@ -229,8 +229,8 @@ namespace embree { if (!tri.valid(i)) break; STAT3(shadow.trav_prims,1,popcnt(valid0),K); - Vec3vf v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); - pre.intersectK(valid0,ray,v0,v1,v2,/*UVIdentity(),*/OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); + Vec3vf v0,v1,v2; tri.template gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); + pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); if (none(valid0)) break; } return !valid0; @@ -241,7 +241,7 @@ namespace embree { STAT3(normal.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); - pre.intersect(ray,k,v0,v1,v2,/*UVIdentity(),*/Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ @@ -249,23 +249,23 @@ namespace embree { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); - return pre.intersect(ray,k,v0,v1,v2,/*UVIdentity(),*/Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; /*! Intersects M motion blur triangles with 1 ray */ - template + template struct TriangleMiMBIntersector1Pluecker { typedef TriangleMi Primitive; - typedef PlueckerIntersector1 Precalculations; + typedef PlueckerIntersector1 Precalculations; /*! Intersect a ray with the M triangles and updates the hit. */ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); - pre.intersect(ray,v0,v1,v2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersect(ray,v0,v1,v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of M triangles. */ @@ -273,7 +273,7 @@ namespace embree { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); - return pre.intersect(ray,v0,v1,v2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -283,11 +283,11 @@ namespace embree }; /*! Intersects M motion blur triangles with K rays. */ - template + template struct TriangleMiMBIntersectorKPluecker { typedef TriangleMi Primitive; - typedef PlueckerIntersectorK Precalculations; + typedef PlueckerIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const TriangleMi& tri) @@ -296,8 +296,8 @@ namespace embree { if (!tri.valid(i)) break; STAT3(normal.trav_prims,1,popcnt(valid_i),K); - Vec3vf v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); - pre.intersectK(valid_i,ray,v0,v1,v2,UVIdentity(),IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); + Vec3vf v0,v1,v2; tri.template gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); + pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM(ray,context,tri.geomID(),tri.primID(),i)); } } @@ -309,8 +309,8 @@ namespace embree { if (!tri.valid(i)) break; STAT3(shadow.trav_prims,1,popcnt(valid0),K); - Vec3vf v0,v1,v2; tri.gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); - pre.intersectK(valid0,ray,v0,v1,v2,UVIdentity(),OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); + Vec3vf v0,v1,v2; tri.template gather(valid_i,v0,v1,v2,i,context->scene,ray.time()); + pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM(valid0,ray,context,tri.geomID(),tri.primID(),i)); if (none(valid0)) break; } return !valid0; @@ -321,7 +321,7 @@ namespace embree { STAT3(normal.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); - pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ @@ -329,7 +329,7 @@ namespace embree { STAT3(shadow.trav_prims,1,1,1); Vec3vf v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); - return pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; } diff --git a/kernels/geometry/trianglev.h b/kernels/geometry/trianglev.h index 19af389e73..cd94756b9e 100644 --- a/kernels/geometry/trianglev.h +++ b/kernels/geometry/trianglev.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/trianglev_intersector.h b/kernels/geometry/trianglev_intersector.h index 6af0d5a11c..3abb7f8e32 100644 --- a/kernels/geometry/trianglev_intersector.h +++ b/kernels/geometry/trianglev_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -13,24 +13,24 @@ namespace embree namespace isa { /*! Intersects M triangles with 1 ray */ - template + template struct TriangleMvIntersector1Moeller { typedef TriangleMv Primitive; - typedef MoellerTrumboreIntersector1 Precalculations; + typedef MoellerTrumboreIntersector1 Precalculations; /*! Intersect a ray with M triangles and updates the hit. */ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); - pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); - return pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -40,25 +40,25 @@ namespace embree }; - template + template struct TriangleMvIntersector1Woop { typedef TriangleMv Primitive; - typedef WoopIntersector1 intersec; + typedef WoopIntersector1 intersec; typedef WoopPrecalculations1 Precalculations; /*! Intersect a ray with M triangles and updates the hit. */ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); - intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); - return intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return intersec::intersect(ray,pre,tri.v0,tri.v1,tri.v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -69,11 +69,11 @@ namespace embree /*! Intersects M triangles with K rays */ - template + template struct TriangleMvIntersectorKMoeller { typedef TriangleMv Primitive; - typedef MoellerTrumboreIntersectorK Precalculations; + typedef MoellerTrumboreIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const Primitive& tri) @@ -111,36 +111,36 @@ namespace embree static __forceinline void intersect(Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); - pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx + pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); - return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx + return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,/*UVIdentity(),*/Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M } }; /*! Intersects M triangles with 1 ray */ - template + template struct TriangleMvIntersector1Pluecker { typedef TriangleMv Primitive; - typedef PlueckerIntersector1 Precalculations; + typedef PlueckerIntersector1 Precalculations; /*! Intersect a ray with M triangles and updates the hit. */ static __forceinline void intersect(Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); - pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); - return pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + return pre.intersect(ray,tri.v0,tri.v1,tri.v2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -150,11 +150,11 @@ namespace embree }; /*! Intersects M triangles with K rays */ - template + template struct TriangleMvIntersectorKPluecker { typedef TriangleMv Primitive; - typedef PlueckerIntersectorK Precalculations; + typedef PlueckerIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const Primitive& tri) @@ -192,14 +192,14 @@ namespace embree static __forceinline void intersect(Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const Primitive& tri) { STAT3(normal.trav_prims,1,1,1); - pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx + pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const Primitive& tri) { STAT3(shadow.trav_prims,1,1,1); - return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); //FIXME: M,Mx + return pre.intersect(ray,k,tri.v0,tri.v1,tri.v2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; } diff --git a/kernels/geometry/trianglev_mb.h b/kernels/geometry/trianglev_mb.h index 63137aee16..b550a29fd5 100644 --- a/kernels/geometry/trianglev_mb.h +++ b/kernels/geometry/trianglev_mb.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/geometry/trianglev_mb_intersector.h b/kernels/geometry/trianglev_mb_intersector.h index 35a260d826..38cd52e85d 100644 --- a/kernels/geometry/trianglev_mb_intersector.h +++ b/kernels/geometry/trianglev_mb_intersector.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,32 +11,32 @@ namespace embree namespace isa { /*! Intersects M motion blur triangles with 1 ray */ - template + template struct TriangleMvMBIntersector1Moeller { typedef TriangleMvMB Primitive; - typedef MoellerTrumboreIntersector1 Precalculations; + typedef MoellerTrumboreIntersector1 Precalculations; /*! Intersect a ray with the M triangles and updates the hit. */ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB& tri) { STAT3(normal.trav_prims,1,1,1); - const Vec3vf time(ray.time()); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - pre.intersect(ray,v0,v1,v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + pre.intersect(ray,v0,v1,v2,Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of M triangles. */ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB& tri) { STAT3(shadow.trav_prims,1,1,1); - const Vec3vf time(ray.time()); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -46,11 +46,11 @@ namespace embree }; /*! Intersects M motion blur triangles with K rays. */ - template + template struct TriangleMvMBIntersectorKMoeller { typedef TriangleMvMB Primitive; - typedef MoellerTrumboreIntersectorK Precalculations; + typedef MoellerTrumboreIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const TriangleMvMB& tri) @@ -90,52 +90,52 @@ namespace embree static __forceinline void intersect(Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const TriangleMvMB& tri) { STAT3(normal.trav_prims,1,1,1); - const Vec3vf time(ray.time()[k]); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()[k]); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const TriangleMvMB& tri) { STAT3(shadow.trav_prims,1,1,1); - const Vec3vf time(ray.time()[k]); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()[k]); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; /*! Intersects M motion blur triangles with 1 ray */ - template + template struct TriangleMvMBIntersector1Pluecker { typedef TriangleMvMB Primitive; - typedef PlueckerIntersector1 Precalculations; + typedef PlueckerIntersector1 Precalculations; /*! Intersect a ray with the M triangles and updates the hit. */ static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const TriangleMvMB& tri) { STAT3(normal.trav_prims,1,1,1); - const Vec3vf time(ray.time()); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - pre.intersect(ray,v0,v1,v2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + pre.intersect(ray,v0,v1,v2,UVIdentity(),Intersect1EpilogM(ray,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of M triangles. */ static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const TriangleMvMB& tri) { STAT3(shadow.trav_prims,1,1,1); - const Vec3vf time(ray.time()); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - return pre.intersect(ray,v0,v1,v2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + return pre.intersect(ray,v0,v1,v2,UVIdentity(),Occluded1EpilogM(ray,context,tri.geomID(),tri.primID())); } static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) @@ -145,11 +145,11 @@ namespace embree }; /*! Intersects M motion blur triangles with K rays. */ - template + template struct TriangleMvMBIntersectorKPluecker { typedef TriangleMvMB Primitive; - typedef PlueckerIntersectorK Precalculations; + typedef PlueckerIntersectorK Precalculations; /*! Intersects K rays with M triangles. */ static __forceinline void intersect(const vbool& valid_i, Precalculations& pre, RayHitK& ray, IntersectContext* context, const TriangleMvMB& tri) @@ -189,22 +189,22 @@ namespace embree static __forceinline void intersect(Precalculations& pre, RayHitK& ray, size_t k, IntersectContext* context, const TriangleMvMB& tri) { STAT3(normal.trav_prims,1,1,1); - const Vec3vf time(ray.time()[k]); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()[k]); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Intersect1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } /*! Test if the ray is occluded by one of the M triangles. */ static __forceinline bool occluded(Precalculations& pre, RayK& ray, size_t k, IntersectContext* context, const TriangleMvMB& tri) { STAT3(shadow.trav_prims,1,1,1); - const Vec3vf time(ray.time()[k]); - const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); - const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); - const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); - return pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); + const Vec3vf time(ray.time()[k]); + const Vec3vf v0 = madd(time,Vec3vf(tri.dv0),Vec3vf(tri.v0)); + const Vec3vf v1 = madd(time,Vec3vf(tri.dv1),Vec3vf(tri.v1)); + const Vec3vf v2 = madd(time,Vec3vf(tri.dv2),Vec3vf(tri.v2)); + return pre.intersect(ray,k,v0,v1,v2,UVIdentity(),Occluded1KEpilogM(ray,k,context,tri.geomID(),tri.primID())); } }; } diff --git a/kernels/hash.h.in b/kernels/hash.h.in index 754da5e780..75fc565f58 100644 --- a/kernels/hash.h.in +++ b/kernels/hash.h.in @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define RTC_HASH "@EMBREE_HASH@" diff --git a/kernels/rtcore_config.h.in b/kernels/rtcore_config.h.in index c896322165..d94b4b2bf5 100644 --- a/kernels/rtcore_config.h.in +++ b/kernels/rtcore_config.h.in @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,20 +14,19 @@ #cmakedefine01 EMBREE_MIN_WIDTH #define RTC_MIN_WIDTH EMBREE_MIN_WIDTH -#cmakedefine EMBREE_STATIC_LIB #cmakedefine EMBREE_API_NAMESPACE #if defined(EMBREE_API_NAMESPACE) # define RTC_NAMESPACE @EMBREE_API_NAMESPACE@ # define RTC_NAMESPACE_BEGIN namespace @EMBREE_API_NAMESPACE@ { # define RTC_NAMESPACE_END } -# define RTC_NAMESPACE_OPEN using namespace @EMBREE_API_NAMESPACE@; +# define RTC_NAMESPACE_USE using namespace @EMBREE_API_NAMESPACE@; # define RTC_API_EXTERN_C # undef EMBREE_API_NAMESPACE #else # define RTC_NAMESPACE_BEGIN # define RTC_NAMESPACE_END -# define RTC_NAMESPACE_OPEN +# define RTC_NAMESPACE_USE # if defined(__cplusplus) # define RTC_API_EXTERN_C extern "C" # else diff --git a/kernels/subdiv/bezier_curve.cpp b/kernels/subdiv/bezier_curve.cpp index d635b8972d..ab652e52f1 100644 --- a/kernels/subdiv/bezier_curve.cpp +++ b/kernels/subdiv/bezier_curve.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bezier_curve.h" diff --git a/kernels/subdiv/bezier_curve.h b/kernels/subdiv/bezier_curve.h index c0e78820f8..4f20a5abbb 100644 --- a/kernels/subdiv/bezier_curve.h +++ b/kernels/subdiv/bezier_curve.h @@ -1,10 +1,11 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/default.h" -#include "../common/scene_curves.h" +//#include "../common/scene_curves.h" +#include "../common/context.h" namespace embree { @@ -134,7 +135,7 @@ namespace embree } friend embree_ostream operator<<(embree_ostream cout, const QuadraticBezierCurve& a) { - return cout << "QuadraticBezierCurve ( (" << a.u.lower << ", " << a.u.upper << "), " << a.v0 << ", " << a.v1 << ", " << a.v2 << ")"; + return cout << "QuadraticBezierCurve (" << a.v0 << ", " << a.v1 << ", " << a.v2 << ")"; } }; @@ -659,6 +660,7 @@ namespace embree return numRoots(v0,v1) + numRoots(v1,v2) + numRoots(v2,v3); } + template __forceinline CubicBezierCurve enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const CubicBezierCurve& curve) { return CubicBezierCurve(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0), diff --git a/kernels/subdiv/bezier_patch.h b/kernels/subdiv/bezier_patch.h index d87ed41ccb..0a2aef321f 100644 --- a/kernels/subdiv/bezier_patch.h +++ b/kernels/subdiv/bezier_patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -94,7 +94,7 @@ namespace embree matrix[0][1] = computeRightEdgeBezierControlPoint(source.v,1,1); matrix[0][2] = computeLeftEdgeBezierControlPoint(source.v,1,2); - /* compute buttom edge control points */ + /* compute bottom edge control points */ matrix[3][1] = computeRightEdgeBezierControlPoint(source.v,2,1); matrix[3][2] = computeLeftEdgeBezierControlPoint(source.v,2,2); diff --git a/kernels/subdiv/bilinear_patch.h b/kernels/subdiv/bilinear_patch.h index 35748754bd..cade104a6c 100644 --- a/kernels/subdiv/bilinear_patch.h +++ b/kernels/subdiv/bilinear_patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/bspline_curve.cpp b/kernels/subdiv/bspline_curve.cpp index 56ed08f4b8..c0716a360d 100644 --- a/kernels/subdiv/bspline_curve.cpp +++ b/kernels/subdiv/bspline_curve.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "bspline_curve.h" diff --git a/kernels/subdiv/bspline_curve.h b/kernels/subdiv/bspline_curve.h index a325667328..51489ef37c 100644 --- a/kernels/subdiv/bspline_curve.h +++ b/kernels/subdiv/bspline_curve.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -161,8 +161,8 @@ namespace embree template __forceinline void veval(const vfloat& t, Vec4vf& p, Vec4vf& dp) const { - p = veval(t); - dp = veval_du(t); + p = veval(t); + dp = veval_du(t); } template @@ -306,6 +306,7 @@ namespace embree ocurve = BezierCurveT(v0,v1,v2,v3); } + template __forceinline BSplineCurveT enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const BSplineCurveT& curve) { return BSplineCurveT(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0), diff --git a/kernels/subdiv/bspline_patch.h b/kernels/subdiv/bspline_patch.h index 9769bc17bd..ff47f01c7a 100644 --- a/kernels/subdiv/bspline_patch.h +++ b/kernels/subdiv/bspline_patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/catmullclark_coefficients.cpp b/kernels/subdiv/catmullclark_coefficients.cpp index 23d824b5f5..fa6797e430 100644 --- a/kernels/subdiv/catmullclark_coefficients.cpp +++ b/kernels/subdiv/catmullclark_coefficients.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "catmullclark_coefficients.h" diff --git a/kernels/subdiv/catmullclark_coefficients.h b/kernels/subdiv/catmullclark_coefficients.h index 05031cf6b9..46959797bf 100644 --- a/kernels/subdiv/catmullclark_coefficients.h +++ b/kernels/subdiv/catmullclark_coefficients.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/catmullclark_patch.h b/kernels/subdiv/catmullclark_patch.h index ab1d63594a..91772d94ed 100644 --- a/kernels/subdiv/catmullclark_patch.h +++ b/kernels/subdiv/catmullclark_patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/catmullclark_ring.h b/kernels/subdiv/catmullclark_ring.h index 73b41fd4ff..eab91d9ee6 100644 --- a/kernels/subdiv/catmullclark_ring.h +++ b/kernels/subdiv/catmullclark_ring.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -388,7 +388,7 @@ namespace embree return (Vertex_t)(n*n*vtx+4.0f*E+F) / ((n+5.0f)*n); } - /* gets limit tangent in the direction of egde vtx -> ring[0] */ + /* gets limit tangent in the direction of edge vtx -> ring[0] */ __forceinline Vertex getLimitTangent() const { if (unlikely(std::isinf(vertex_crease_weight))) @@ -429,7 +429,7 @@ namespace embree return sigma * (alpha + beta); } - /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */ + /* gets limit tangent in the direction of edge vtx -> ring[edge_valence-2] */ __forceinline Vertex getSecondLimitTangent() const { if (unlikely(std::isinf(vertex_crease_weight))) @@ -763,7 +763,7 @@ namespace embree } - /* gets limit tangent in the direction of egde vtx -> ring[0] */ + /* gets limit tangent in the direction of edge vtx -> ring[0] */ __forceinline Vertex getLimitTangent() const { CatmullClark1Ring cc_vtx; @@ -779,7 +779,7 @@ namespace embree return 2.0f * cc_vtx.getLimitTangent(); } - /* gets limit tangent in the direction of egde vtx -> ring[edge_valence-2] */ + /* gets limit tangent in the direction of edge vtx -> ring[edge_valence-2] */ __forceinline Vertex getSecondLimitTangent() const { CatmullClark1Ring cc_vtx; diff --git a/kernels/subdiv/catmullrom_curve.cpp b/kernels/subdiv/catmullrom_curve.cpp index 0d79f6f3b0..c6453395da 100644 --- a/kernels/subdiv/catmullrom_curve.cpp +++ b/kernels/subdiv/catmullrom_curve.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "catmullrom_curve.h" diff --git a/kernels/subdiv/catmullrom_curve.h b/kernels/subdiv/catmullrom_curve.h index b244af481c..74fc4c1230 100644 --- a/kernels/subdiv/catmullrom_curve.h +++ b/kernels/subdiv/catmullrom_curve.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -168,8 +168,8 @@ namespace embree template __forceinline void veval(const vfloat& t, Vec4vf& p, Vec4vf& dp) const { - p = veval(t); - dp = veval_du(t); + p = veval(t); + dp = veval_du(t); } template @@ -283,6 +283,7 @@ namespace embree } }; + template __forceinline CatmullRomCurveT enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const CatmullRomCurveT& curve) { return CatmullRomCurveT(enlargeRadiusToMinWidth(context,geom,ray_org,curve.v0), diff --git a/kernels/subdiv/feature_adaptive_eval.h b/kernels/subdiv/feature_adaptive_eval.h index 23f24c360c..58c0b63e62 100644 --- a/kernels/subdiv/feature_adaptive_eval.h +++ b/kernels/subdiv/feature_adaptive_eval.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/feature_adaptive_eval_grid.h b/kernels/subdiv/feature_adaptive_eval_grid.h index 76583b2e5d..4755aba28d 100644 --- a/kernels/subdiv/feature_adaptive_eval_grid.h +++ b/kernels/subdiv/feature_adaptive_eval_grid.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/feature_adaptive_eval_simd.h b/kernels/subdiv/feature_adaptive_eval_simd.h index fa3216730f..edab0db12f 100644 --- a/kernels/subdiv/feature_adaptive_eval_simd.h +++ b/kernels/subdiv/feature_adaptive_eval_simd.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/gregory_patch.h b/kernels/subdiv/gregory_patch.h index 2a7c4b1f2c..9026d5c407 100644 --- a/kernels/subdiv/gregory_patch.h +++ b/kernels/subdiv/gregory_patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/gregory_patch_dense.h b/kernels/subdiv/gregory_patch_dense.h index 85effd02cf..4cf9a7e98f 100644 --- a/kernels/subdiv/gregory_patch_dense.h +++ b/kernels/subdiv/gregory_patch_dense.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/gridrange.h b/kernels/subdiv/gridrange.h index 4fd741c879..4f2b90d7bd 100644 --- a/kernels/subdiv/gridrange.h +++ b/kernels/subdiv/gridrange.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/half_edge.h b/kernels/subdiv/half_edge.h index fb350ca71f..baf019cd79 100644 --- a/kernels/subdiv/half_edge.h +++ b/kernels/subdiv/half_edge.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -186,7 +186,7 @@ namespace embree { const HalfEdge* p = this; do { - if (p->vertexHasBorder()) return true; + if (p->vertexHasBorder() && (p->vertex_type != HalfEdge::NON_MANIFOLD_EDGE_VERTEX)) return true; p = p->next(); } while (p != this); return false; diff --git a/kernels/subdiv/hermite_curve.h b/kernels/subdiv/hermite_curve.h index 9fab79cf0c..ffef5a4315 100644 --- a/kernels/subdiv/hermite_curve.h +++ b/kernels/subdiv/hermite_curve.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -29,6 +29,7 @@ namespace embree } }; + template __forceinline HermiteCurveT enlargeRadiusToMinWidth(const IntersectContext* context, const CurveGeometry* geom, const Vec3fa& ray_org, const HermiteCurveT& curve) { return HermiteCurveT(enlargeRadiusToMinWidth(context,geom,ray_org,BezierCurveT(curve))); } diff --git a/kernels/subdiv/linear_bezier_patch.h b/kernels/subdiv/linear_bezier_patch.h index f4a854af7f..dcdb101d7c 100644 --- a/kernels/subdiv/linear_bezier_patch.h +++ b/kernels/subdiv/linear_bezier_patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -81,29 +81,29 @@ namespace embree { SourceCurve vcurve = center; SourceCurve ncurve = normal; - + /* here we construct a patch which follows the curve l(t) = * p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */ const Vec3ff p0 = vcurve.eval(0.0f); const Vec3ff dp0 = vcurve.eval_du(0.0f); - const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); + //const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); // ddp0 is assumed to be 0 const Vec3fa n0 = ncurve.eval(0.0f); const Vec3fa dn0 = ncurve.eval_du(0.0f); const Vec3ff p1 = vcurve.eval(1.0f); const Vec3ff dp1 = vcurve.eval_du(1.0f); - const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); + //const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); // ddp1 is assumed to be 0 const Vec3fa n1 = ncurve.eval(1.0f); const Vec3fa dn1 = ncurve.eval_du(1.0f); const Vec3fa bt0 = cross(n0,dp0); - const Vec3fa dbt0 = cross(dn0,dp0) + cross(n0,ddp0); + const Vec3fa dbt0 = cross(dn0,dp0);// + cross(n0,ddp0); const Vec3fa bt1 = cross(n1,dp1); - const Vec3fa dbt1 = cross(dn1,dp1) + cross(n1,ddp1); + const Vec3fa dbt1 = cross(dn1,dp1);// + cross(n1,ddp1); const Vec3fa k0 = normalize(bt0); const Vec3fa dk0 = dnormalize(bt0,dbt0); diff --git a/kernels/subdiv/patch.h b/kernels/subdiv/patch.h index d58241b96d..c4340ea9b6 100644 --- a/kernels/subdiv/patch.h +++ b/kernels/subdiv/patch.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/patch_eval.h b/kernels/subdiv/patch_eval.h index 482d015fa3..a3fafa72f4 100644 --- a/kernels/subdiv/patch_eval.h +++ b/kernels/subdiv/patch_eval.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/patch_eval_grid.h b/kernels/subdiv/patch_eval_grid.h index c05db55f4c..167e1ebe1c 100644 --- a/kernels/subdiv/patch_eval_grid.h +++ b/kernels/subdiv/patch_eval_grid.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/patch_eval_simd.h b/kernels/subdiv/patch_eval_simd.h index 28016d9e20..fef88a4492 100644 --- a/kernels/subdiv/patch_eval_simd.h +++ b/kernels/subdiv/patch_eval_simd.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/subdivpatch1base.cpp b/kernels/subdiv/subdivpatch1base.cpp index 58a71cf78d..aa135b2469 100644 --- a/kernels/subdiv/subdivpatch1base.cpp +++ b/kernels/subdiv/subdivpatch1base.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "subdivpatch1base.h" diff --git a/kernels/subdiv/subdivpatch1base.h b/kernels/subdiv/subdivpatch1base.h index d5bc403cca..c3069dadee 100644 --- a/kernels/subdiv/subdivpatch1base.h +++ b/kernels/subdiv/subdivpatch1base.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/subdivpatch1base_eval.cpp b/kernels/subdiv/subdivpatch1base_eval.cpp index 990ba8303e..243525d77a 100644 --- a/kernels/subdiv/subdivpatch1base_eval.cpp +++ b/kernels/subdiv/subdivpatch1base_eval.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "subdivpatch1base.h" diff --git a/kernels/subdiv/tessellation.h b/kernels/subdiv/tessellation.h index bda1e2d559..abde4f2bde 100644 --- a/kernels/subdiv/tessellation.h +++ b/kernels/subdiv/tessellation.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/kernels/subdiv/tessellation_cache.cpp b/kernels/subdiv/tessellation_cache.cpp index 48d840ad38..e48baf5d96 100644 --- a/kernels/subdiv/tessellation_cache.cpp +++ b/kernels/subdiv/tessellation_cache.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "tessellation_cache.h" diff --git a/kernels/subdiv/tessellation_cache.h b/kernels/subdiv/tessellation_cache.h index 116b4db88b..99edf49be4 100644 --- a/kernels/subdiv/tessellation_cache.h +++ b/kernels/subdiv/tessellation_cache.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -63,7 +63,7 @@ namespace embree static const size_t NUM_CACHE_SEGMENTS = 8; static const size_t NUM_PREALLOC_THREAD_WORK_STATES = 512; static const size_t COMMIT_INDEX_SHIFT = 32+8; -#if defined(__X86_64__) +#if defined(__64BIT__) static const size_t REF_TAG_MASK = 0xffffffffff; #else static const size_t REF_TAG_MASK = 0x7FFFFFFF; diff --git a/man/man3/RTCBufferType.3embree3 b/man/man3/RTCBufferType.3embree3 index a238350aac..4bb0edf874 100644 --- a/man/man3/RTCBufferType.3embree3 +++ b/man/man3/RTCBufferType.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCBufferType" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,69 +6,69 @@ .IP .nf \f[C] -RTCFormat\ \-\ specifies\ format\ of\ data\ in\ buffers -\f[] +RTCFormat \- specifies format of data in buffers +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -enum\ RTCBufferType +enum RTCBufferType { -\ \ RTC_BUFFER_TYPE_INDEX\ \ \ \ \ \ \ \ \ \ \ \ =\ 0, -\ \ RTC_BUFFER_TYPE_VERTEX\ \ \ \ \ \ \ \ \ \ \ =\ 1, -\ \ RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\ =\ 2, -\ \ RTC_BUFFER_TYPE_NORMAL\ \ \ \ \ \ \ \ \ \ \ =\ 3, -\ \ RTC_BUFFER_TYPE_TANGENT\ \ \ \ \ \ \ \ \ \ =\ 4, -\ \ RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\ =\ 5, + RTC_BUFFER_TYPE_INDEX = 0, + RTC_BUFFER_TYPE_VERTEX = 1, + RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE = 2, + RTC_BUFFER_TYPE_NORMAL = 3, + RTC_BUFFER_TYPE_TANGENT = 4, + RTC_BUFFER_TYPE_NORMAL_DERIVATIVE = 5, -\ \ RTC_BUFFER_TYPE_GRID\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\ 8, + RTC_BUFFER_TYPE_GRID = 8, -\ \ RTC_BUFFER_TYPE_FACE\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\ 16, -\ \ RTC_BUFFER_TYPE_LEVEL\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\ 17, -\ \ RTC_BUFFER_TYPE_EDGE_CREASE_INDEX\ \ \ \ =\ 18, -\ \ RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT\ \ \ =\ 19, -\ \ RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX\ \ =\ 20, -\ \ RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT\ =\ 21, -\ \ RTC_BUFFER_TYPE_HOLE\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\ 22, + RTC_BUFFER_TYPE_FACE = 16, + RTC_BUFFER_TYPE_LEVEL = 17, + RTC_BUFFER_TYPE_EDGE_CREASE_INDEX = 18, + RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT = 19, + RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX = 20, + RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT = 21, + RTC_BUFFER_TYPE_HOLE = 22, -\ \ RTC_BUFFER_TYPE_FLAGS\ =\ 32 + RTC_BUFFER_TYPE_FLAGS = 32 }; -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]RTBufferType\f[] structure defines slots to assign data buffers -to using the [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], and -[rtcSetNewGeometryBuffer] API calls. +The \f[C]RTBufferType\f[R] structure defines slots to assign data +buffers to using the [rtcSetGeometryBuffer], +[rtcSetSharedGeometryBuffer], and [rtcSetNewGeometryBuffer] API calls. .PP -For most geometry types the \f[C]RTC_BUFFER_TYPE_INDEX\f[] slot is used -to assign an index buffer, while the \f[C]RTC_BUFFER_TYPE_VERTEX\f[] is +For most geometry types the \f[C]RTC_BUFFER_TYPE_INDEX\f[R] slot is used +to assign an index buffer, while the \f[C]RTC_BUFFER_TYPE_VERTEX\f[R] is used to assign the corresponding vertex buffer. .PP -The \f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[] slot can get used to +The \f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[R] slot can get used to assign arbitrary additional vertex data which can get interpolated using the [rtcInterpolate] API call. .PP -The \f[C]RTC_BUFFER_TYPE_NORMAL\f[], \f[C]RTC_BUFFER_TYPE_TANGENT\f[], -and \f[C]RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\f[] are special buffers +The \f[C]RTC_BUFFER_TYPE_NORMAL\f[R], \f[C]RTC_BUFFER_TYPE_TANGENT\f[R], +and \f[C]RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\f[R] are special buffers required to assign per vertex normals, tangents, and normal derivatives for some curve types. .PP -The \f[C]RTC_BUFFER_TYPE_GRID\f[] buffer is used to assign the grid +The \f[C]RTC_BUFFER_TYPE_GRID\f[R] buffer is used to assign the grid primitive buffer for grid geometries (see [RTC_GEOMETRY_TYPE_GRID]). .PP -The \f[C]RTC_BUFFER_TYPE_FACE\f[], \f[C]RTC_BUFFER_TYPE_LEVEL\f[], -\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_INDEX\f[], -\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT\f[], -\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX\f[], -\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT\f[], and -\f[C]RTC_BUFFER_TYPE_HOLE\f[] are special buffers required to create +The \f[C]RTC_BUFFER_TYPE_FACE\f[R], \f[C]RTC_BUFFER_TYPE_LEVEL\f[R], +\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_INDEX\f[R], +\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT\f[R], +\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX\f[R], +\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT\f[R], and +\f[C]RTC_BUFFER_TYPE_HOLE\f[R] are special buffers required to create subdivision meshes (see [RTC_GEOMETRY_TYPE_SUBDIVISION]). .PP -The \f[C]RTC_BUFFER_TYPE_FLAGS\f[] can get used to add additional flag +The \f[C]RTC_BUFFER_TYPE_FLAGS\f[R] can get used to add additional flag per primitive of a geometry, and is currently only used for linear curves. .SS EXIT STATUS diff --git a/man/man3/RTCCurveFlags.3embree3 b/man/man3/RTCCurveFlags.3embree3 index 53b4e4ac48..32a6c62525 100644 --- a/man/man3/RTCCurveFlags.3embree3 +++ b/man/man3/RTCCurveFlags.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCCurveFlags" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,15 +6,15 @@ .IP .nf \f[C] -RTCCurveFlags\ \-\ per\ segment\ flags\ for\ curve\ geometry -\f[] +RTCCurveFlags \- per segment flags for curve geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ -\f[] +#include +\f[R] .fi .PP enum RTCCurveFlags { RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0), diff --git a/man/man3/RTCFormat.3embree3 b/man/man3/RTCFormat.3embree3 index 179f09253f..b210b39904 100644 --- a/man/man3/RTCFormat.3embree3 +++ b/man/man3/RTCFormat.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCFormat" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,81 +6,79 @@ .IP .nf \f[C] -RTCFormat\ \-\ specifies\ format\ of\ data\ in\ buffers -\f[] +RTCFormat \- specifies format of data in buffers +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -enum\ RTCFormat +enum RTCFormat { -\ \ RTC_FORMAT_UINT, -\ \ RTC_FORMAT_UINT2, -\ \ RTC_FORMAT_UINT3, -\ \ RTC_FORMAT_UINT4, + RTC_FORMAT_UINT, + RTC_FORMAT_UINT2, + RTC_FORMAT_UINT3, + RTC_FORMAT_UINT4, -\ \ RTC_FORMAT_FLOAT, -\ \ RTC_FORMAT_FLOAT2, -\ \ RTC_FORMAT_FLOAT3, -\ \ RTC_FORMAT_FLOAT4, -\ \ RTC_FORMAT_FLOAT5, -\ \ RTC_FORMAT_FLOAT6, -\ \ RTC_FORMAT_FLOAT7, -\ \ RTC_FORMAT_FLOAT8, -\ \ RTC_FORMAT_FLOAT9, -\ \ RTC_FORMAT_FLOAT10, -\ \ RTC_FORMAT_FLOAT11, -\ \ RTC_FORMAT_FLOAT12, -\ \ RTC_FORMAT_FLOAT13, -\ \ RTC_FORMAT_FLOAT14, -\ \ RTC_FORMAT_FLOAT15, -\ \ RTC_FORMAT_FLOAT16, + RTC_FORMAT_FLOAT, + RTC_FORMAT_FLOAT2, + RTC_FORMAT_FLOAT3, + RTC_FORMAT_FLOAT4, + RTC_FORMAT_FLOAT5, + RTC_FORMAT_FLOAT6, + RTC_FORMAT_FLOAT7, + RTC_FORMAT_FLOAT8, + RTC_FORMAT_FLOAT9, + RTC_FORMAT_FLOAT10, + RTC_FORMAT_FLOAT11, + RTC_FORMAT_FLOAT12, + RTC_FORMAT_FLOAT13, + RTC_FORMAT_FLOAT14, + RTC_FORMAT_FLOAT15, + RTC_FORMAT_FLOAT16, -\ \ RTC_FORMAT_FLOAT3X4_ROW_MAJOR, -\ \ RTC_FORMAT_FLOAT4X4_ROW_MAJOR, + RTC_FORMAT_FLOAT3X4_ROW_MAJOR, + RTC_FORMAT_FLOAT4X4_ROW_MAJOR, -\ \ RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, -\ \ RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, + RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, + RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, -\ \ RTC_FORMAT_GRID, -\f[] + RTC_FORMAT_GRID, +\f[R] .fi .PP }; .SS DESCRIPTION .PP -The \f[C]RTFormat\f[] structure defines the data format stored in data +The \f[C]RTFormat\f[R] structure defines the data format stored in data buffers provided to Embree using the [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], and [rtcSetNewGeometryBuffer] API calls. .PP -The \f[C]RTC_FORMAT_UINT/2/3/4\f[] format are used to specify that data +The \f[C]RTC_FORMAT_UINT/2/3/4\f[R] format are used to specify that data buffers store unsigned integers, or unsigned integer vectors of size 2,3 or 4. This format has typically to get used when specifying index buffers, -e.g. -\f[C]RTC_FORMAT_UINT3\f[] for triangle meshes. +e.g.\ \f[C]RTC_FORMAT_UINT3\f[R] for triangle meshes. .PP -The \f[C]RTC_FORMAT_FLOAT/2/3/4...\f[] format are used to specify that +The \f[C]RTC_FORMAT_FLOAT/2/3/4...\f[R] format are used to specify that data buffers store single precision floating point values, or vectors there of (size 2,3,4, etc.). This format is typcally used to specify to format of vertex buffers, -e.g. -the \f[C]RTC_FORMAT_FLOAT3\f[] type for vertex buffers of triangle -meshes. +e.g.\ the \f[C]RTC_FORMAT_FLOAT3\f[R] type for vertex buffers of +triangle meshes. .PP -The \f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[] and -\f[C]RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR\f[] formats, specify a 3x4 +The \f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[R] and +\f[C]RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR\f[R] formats, specify a 3x4 floating point matrix layed out either row major or column major. -The \f[C]RTC_FORMAT_FLOAT4X4_ROW_MAJOR\f[] and -\f[C]RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR\f[] formats, specify a 4x4 +The \f[C]RTC_FORMAT_FLOAT4X4_ROW_MAJOR\f[R] and +\f[C]RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR\f[R] formats, specify a 4x4 floating point matrix layed out either row major or column major. These matrix formats are used in the [rtcSetGeometryTransform] function in order to set a transformation matrix for geometries. .PP -The \f[C]RTC_FORMAT_GRID\f[] is a special data format used to specify +The \f[C]RTC_FORMAT_GRID\f[R] is a special data format used to specify grid primitives of layout RTCGrid when creating grid geometries (see [RTC_GEOMETRY_TYPE_GRID]). .SS EXIT STATUS diff --git a/man/man3/RTCHit.3embree3 b/man/man3/RTCHit.3embree3 index ad018578ca..68d55317f1 100644 --- a/man/man3/RTCHit.3embree3 +++ b/man/man3/RTCHit.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCHit" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,48 +6,48 @@ .IP .nf \f[C] -RTCHit\ \-\ single\ hit\ structure -\f[] +RTCHit \- single hit structure +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCHit +struct RTCHit { -\ \ float\ Ng_x;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ x\ coordinate\ of\ geometry\ normal -\ \ float\ Ng_y;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ y\ coordinate\ of\ geometry\ normal -\ \ float\ Ng_z;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ z\ coordinate\ of\ geometry\ normal + float Ng_x; // x coordinate of geometry normal + float Ng_y; // y coordinate of geometry normal + float Ng_z; // z coordinate of geometry normal -\ \ float\ u;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ barycentric\ u\ coordinate\ of\ hit -\ \ float\ v;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ barycentric\ v\ coordinate\ of\ hit + float u; // barycentric u coordinate of hit + float v; // barycentric v coordinate of hit -\ \ unsigned\ int\ primID;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ geometry\ ID -\ \ unsigned\ int\ geomID;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ //\ primitive\ ID -\ \ unsigned\ int\ instID[RTC_MAX_INSTANCE_LEVEL_COUNT];\ //\ instance\ ID + unsigned int primID; // geometry ID + unsigned int geomID; // primitive ID + unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; // instance ID }; -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]RTCHit\f[] type defines the type of a ray/primitive +The \f[C]RTCHit\f[R] type defines the type of a ray/primitive intersection result. The hit contains the unnormalized geometric normal in object space at -the hit location (\f[C]Ng_x\f[], \f[C]Ng_y\f[], \f[C]Ng_z\f[] members), -the barycentric u/v coordinates of the hit (\f[C]u\f[] and \f[C]v\f[] -members), as well as the primitive ID (\f[C]primID\f[] member), geometry -ID (\f[C]geomID\f[] member), and instance ID stack (\f[C]instID\f[] -member) of the hit. +the hit location (\f[C]Ng_x\f[R], \f[C]Ng_y\f[R], \f[C]Ng_z\f[R] +members), the barycentric u/v coordinates of the hit (\f[C]u\f[R] and +\f[C]v\f[R] members), as well as the primitive ID (\f[C]primID\f[R] +member), geometry ID (\f[C]geomID\f[R] member), and instance ID stack +(\f[C]instID\f[R] member) of the hit. The parametric intersection distance is not stored inside the hit, but -stored inside the \f[C]tfar\f[] member of the ray. +stored inside the \f[C]tfar\f[R] member of the ray. .PP -The \f[C]embree3/rtcore_ray.h\f[] header additionally defines the same +The \f[C]embree3/rtcore_ray.h\f[R] header additionally defines the same hit structure in structure of array (SOA) layout for hit packets of size -4 (\f[C]RTCHit4\f[] type), size 8 (\f[C]RTCHit8\f[] type), and size 16 -(\f[C]RTCHit16\f[] type). -The header additionally defines an \f[C]RTCHitNt\f[] template for hit +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. .SS EXIT STATUS .SS SEE ALSO diff --git a/man/man3/RTCHitN.3embree3 b/man/man3/RTCHitN.3embree3 index ca11d16b13..bc1e0e54b2 100644 --- a/man/man3/RTCHitN.3embree3 +++ b/man/man3/RTCHitN.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCHitN" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,47 +6,46 @@ .IP .nf \f[C] -RTCHitN\ \-\ hit\ packet\ of\ runtime\ size -\f[] +RTCHitN \- hit packet of runtime size +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ HitN; +struct HitN; -float&\ RTCHitN_Ng_x(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCHitN_Ng_y(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCHitN_Ng_z(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); +float& RTCHitN_Ng_x(RTCHitN* hit, unsigned int N, unsigned int i); +float& RTCHitN_Ng_y(RTCHitN* hit, unsigned int N, unsigned int i); +float& RTCHitN_Ng_z(RTCHitN* hit, unsigned int N, unsigned int i); -float&\ RTCHitN_u(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCHitN_v(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); +float& RTCHitN_u(RTCHitN* hit, unsigned int N, unsigned int i); +float& RTCHitN_v(RTCHitN* hit, unsigned int N, unsigned int i); -unsigned&\ RTCHitN_primID(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); -unsigned&\ RTCHitN_geomID(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i); -unsigned&\ RTCHitN_instID(RTCHitN*\ hit,\ unsigned\ int\ N,\ unsigned\ int\ i,\ unsigned\ int\ level); -\f[] +unsigned& RTCHitN_primID(RTCHitN* hit, unsigned int N, unsigned int i); +unsigned& RTCHitN_geomID(RTCHitN* hit, unsigned int N, unsigned int i); +unsigned& RTCHitN_instID(RTCHitN* hit, unsigned int N, unsigned int i, unsigned int level); +\f[R] .fi .SS DESCRIPTION .PP -When the hit packet size is not known at compile time (e.g. -when Embree returns a hit packet in the \f[C]RTCFilterFuncN\f[] callback -function), Embree uses the \f[C]RTCHitN\f[] type for hit packets. +When the hit packet size is not known at compile time (e.g.\ when Embree +returns a hit packet in the \f[C]RTCFilterFuncN\f[R] callback function), +Embree uses the \f[C]RTCHitN\f[R] type for hit packets. These hit packets can only have sizes of 1, 4, 8, or 16. No other packet size will be used. .PP You can either implement different special code paths for each of these possible packet sizes and cast the hit to the appropriate hit packet type, or implement one general code path that uses the -\f[C]RTCHitN_XXX\f[] helper functions to access hit packet components. +\f[C]RTCHitN_XXX\f[R] helper functions to access hit packet components. .PP -These helper functions get a pointer to the hit packet (\f[C]hit\f[] -argument), the packet size (\f[C]N\f[] argument), and returns a -reference to a component (e.g. -x component of \f[C]Ng\f[]) of the the i\-th hit of the packet -(\f[C]i\f[] argument). +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). .SS EXIT STATUS .SS SEE ALSO .PP diff --git a/man/man3/RTCQuaternionDecomposition.3embree3 b/man/man3/RTCQuaternionDecomposition.3embree3 index a233ec1e4a..2a52e9049a 100644 --- a/man/man3/RTCQuaternionDecomposition.3embree3 +++ b/man/man3/RTCQuaternionDecomposition.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCQuaternionDecomposition" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,38 +6,38 @@ .IP .nf \f[C] -RTCQuaternionDecomposition\ \-\ structure\ that\ represents\ a\ quaternion -\ \ decomposition\ of\ an\ affine\ transformation -\f[] +RTCQuaternionDecomposition \- structure that represents a quaternion + decomposition of an affine transformation +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -struct\ RTCQuaternionDecomposition +struct RTCQuaternionDecomposition { -\ \ float\ scale_x,\ scale_y,\ scale_z; -\ \ float\ skew_xy,\ skew_xz,\ skew_yz; -\ \ float\ shift_x,\ shift_y,\ shift_z; -\ \ float\ quaternion_r,\ quaternion_i,\ quaternion_j,\ quaternion_k; -\ \ float\ translation_x,\ translation_y,\ translation_z; + float scale_x, scale_y, scale_z; + float skew_xy, skew_xz, skew_yz; + float shift_x, shift_y, shift_z; + float quaternion_r, quaternion_i, quaternion_j, quaternion_k; + float translation_x, translation_y, translation_z; }; -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The struct \f[C]RTCQuaternionDecomposition\f[] represents an affine +The struct \f[C]RTCQuaternionDecomposition\f[R] represents an affine transformation decomposed into three parts. An upper triangular scaling/skew/shift matrix .PP .RS $$ -S = \\left( \\begin{array}{cccc} -scale_x & skew_{xy} & skew_{xz} & shift_x \\\\ -0 & scale_y & skew_{yz} & shift_y \\\\ -0 & 0 & scale_z & shift_z \\\\ -0 & 0 & 0 & 1 \\\\ -\\end{array} \\right), +S = \[rs]left( \[rs]begin{array}{cccc} +scale_x & skew_{xy} & skew_{xz} & shift_x \[rs]\[rs] +0 & scale_y & skew_{yz} & shift_y \[rs]\[rs] +0 & 0 & scale_z & shift_z \[rs]\[rs] +0 & 0 & 0 & 1 \[rs]\[rs] +\[rs]end{array} \[rs]right), $$ .RE .PP @@ -45,38 +45,38 @@ a translation matrix .PP .RS $$ -T = \\left( \\begin{array}{cccc} -1 & 0 & 0 & translation_x \\\\ -0 & 1 & 0 & translation_y \\\\ -0 & 0 & 1 & translation_z \\\\ -0 & 0 & 0 & 1 \\\\ -\\end{array} \\right), +T = \[rs]left( \[rs]begin{array}{cccc} +1 & 0 & 0 & translation_x \[rs]\[rs] +0 & 1 & 0 & translation_y \[rs]\[rs] +0 & 0 & 1 & translation_z \[rs]\[rs] +0 & 0 & 0 & 1 \[rs]\[rs] +\[rs]end{array} \[rs]right), $$ .RE .PP -and a rotation matrix \f[I]R\f[], represented as a quaternion +and a rotation matrix \f[I]R\f[R], represented as a quaternion .PP -\f[I]q\f[]\f[I]u\f[]\f[I]a\f[]\f[I]t\f[]\f[I]e\f[]\f[I]r\f[]\f[I]n\f[]\f[I]i\f[]\f[I]o\f[]\f[I]n\f[]~\f[I]r\f[]~ + \f[I]q\f[]\f[I]u\f[]\f[I]a\f[]\f[I]t\f[]\f[I]e\f[]\f[I]r\f[]\f[I]n\f[]\f[I]i\f[]\f[I]o\f[]\f[I]n\f[]~\f[I]i\f[]~\ \f[B]i\f[] + \f[I]q\f[]\f[I]u\f[]\f[I]a\f[]\f[I]t\f[]\f[I]e\f[]\f[I]r\f[]\f[I]n\f[]\f[I]i\f[]\f[I]o\f[]\f[I]n\f[]~\f[I]j\f[]~\ \f[B]i\f[] + \f[I]q\f[]\f[I]u\f[]\f[I]a\f[]\f[I]t\f[]\f[I]e\f[]\f[I]r\f[]\f[I]n\f[]\f[I]i\f[]\f[I]o\f[]\f[I]n\f[]~\f[I]k\f[]~\ \f[B]k\f[] +\f[I]q\f[R]\f[I]u\f[R]\f[I]a\f[R]\f[I]t\f[R]\f[I]e\f[R]\f[I]r\f[R]\f[I]n\f[R]\f[I]i\f[R]\f[I]o\f[R]\f[I]n\f[R]~\f[I]r\f[R]~\[u2005]+\[u2005]\f[I]q\f[R]\f[I]u\f[R]\f[I]a\f[R]\f[I]t\f[R]\f[I]e\f[R]\f[I]r\f[R]\f[I]n\f[R]\f[I]i\f[R]\f[I]o\f[R]\f[I]n\f[R]~\f[I]i\f[R]~\ \f[B]i\f[R]\[u2005]+\[u2005]\f[I]q\f[R]\f[I]u\f[R]\f[I]a\f[R]\f[I]t\f[R]\f[I]e\f[R]\f[I]r\f[R]\f[I]n\f[R]\f[I]i\f[R]\f[I]o\f[R]\f[I]n\f[R]~\f[I]j\f[R]~\ \f[B]i\f[R]\[u2005]+\[u2005]\f[I]q\f[R]\f[I]u\f[R]\f[I]a\f[R]\f[I]t\f[R]\f[I]e\f[R]\f[I]r\f[R]\f[I]n\f[R]\f[I]i\f[R]\f[I]o\f[R]\f[I]n\f[R]~\f[I]k\f[R]~\ \f[B]k\f[R] .PP -where \f[B]i\f[], \f[B]j\f[] \f[B]k\f[] are the imaginary quaternion +where \f[B]i\f[R], \f[B]j\f[R] \f[B]k\f[R] are the imaginary quaternion units. The passed quaternion will be normalized internally. .PP The affine transformation matrix corresponding to a -\f[C]RTCQuaternionDecomposition\f[] is \f[I]T\f[]\f[I]R\f[]\f[I]S\f[] -and a point -\f[I]p\f[] = (\f[I]p\f[]~\f[I]x\f[]~, \f[I]p\f[]~\f[I]y\f[]~, \f[I]p\f[]~\f[I]z\f[]~, 1)^\f[I]T\f[]^ +\f[C]RTCQuaternionDecomposition\f[R] is +\f[I]T\f[R]\f[I]R\f[R]\f[I]S\f[R] and a point +\f[I]p\f[R]\[u2004]=\[u2004](\f[I]p\f[R]~\f[I]x\f[R]~,\[u2006]\f[I]p\f[R]~\f[I]y\f[R]~,\[u2006]\f[I]p\f[R]~\f[I]z\f[R]~,\[u2006]1)^\f[I]T\f[R]^ will be transformed as .RS -\f[I]p\f[]′=\f[I]T\f[]\ \f[I]R\f[]\ \f[I]S\f[]\ \f[I]p\f[]. +\f[I]p\f[R]\[fm]\[u2004]=\[u2004]\f[I]T\f[R]\ \f[I]R\f[R]\ \f[I]S\f[R]\ \f[I]p\f[R]. .RE .PP -The functions \f[C]rtcInitQuaternionDecomposition\f[], -\f[C]rtcQuaternionDecompositionSetQuaternion\f[], -\f[C]rtcQuaternionDecompositionSetScale\f[], -\f[C]rtcQuaternionDecompositionSetSkew\f[], -\f[C]rtcQuaternionDecompositionSetShift\f[], and -\f[C]rtcQuaternionDecompositionSetTranslation\f[] allow to set the +The functions \f[C]rtcInitQuaternionDecomposition\f[R], +\f[C]rtcQuaternionDecompositionSetQuaternion\f[R], +\f[C]rtcQuaternionDecompositionSetScale\f[R], +\f[C]rtcQuaternionDecompositionSetSkew\f[R], +\f[C]rtcQuaternionDecompositionSetShift\f[R], and +\f[C]rtcQuaternionDecompositionSetTranslation\f[R] allow to set the fields of the structure more conveniently. .SS EXIT STATUS .PP diff --git a/man/man3/RTCRay.3embree3 b/man/man3/RTCRay.3embree3 index 68bc6355fa..a703bca6fa 100644 --- a/man/man3/RTCRay.3embree3 +++ b/man/man3/RTCRay.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCRay" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,64 +6,65 @@ .IP .nf \f[C] -RTCRay\ \-\ single\ ray\ structure -\f[] +RTCRay \- single ray structure +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTC_ALIGN(16)\ RTCRay +struct RTC_ALIGN(16) RTCRay { -\ \ float\ org_x;\ \ \ \ \ \ \ \ //\ x\ coordinate\ of\ ray\ origin -\ \ float\ org_y;\ \ \ \ \ \ \ \ //\ y\ coordinate\ of\ ray\ origin -\ \ float\ org_z;\ \ \ \ \ \ \ \ //\ z\ coordinate\ of\ ray\ origin -\ \ float\ tnear;\ \ \ \ \ \ \ \ //\ start\ of\ ray\ segment + float org_x; // x coordinate of ray origin + float org_y; // y coordinate of ray origin + float org_z; // z coordinate of ray origin + float tnear; // start of ray segment -\ \ float\ dir_x;\ \ \ \ \ \ \ \ //\ x\ coordinate\ of\ ray\ direction -\ \ float\ dir_y;\ \ \ \ \ \ \ \ //\ y\ coordinate\ of\ ray\ direction -\ \ float\ dir_z;\ \ \ \ \ \ \ \ //\ z\ coordinate\ of\ ray\ direction -\ \ float\ time;\ \ \ \ \ \ \ \ \ //\ time\ of\ this\ ray\ for\ motion\ blur + float dir_x; // x coordinate of ray direction + float dir_y; // y coordinate of ray direction + float dir_z; // z coordinate of ray direction + float time; // time of this ray for motion blur -\ \ float\ tfar;\ \ \ \ \ \ \ \ \ //\ end\ of\ ray\ segment\ (set\ to\ hit\ distance) -\ \ unsigned\ int\ mask;\ \ //\ ray\ mask -\ \ unsigned\ int\ id;\ \ \ \ //\ ray\ ID -\ \ unsigned\ int\ flags;\ //\ ray\ flags + float tfar; // end of ray segment (set to hit distance) + unsigned int mask; // ray mask + unsigned int id; // ray ID + unsigned int flags; // ray flags }; -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]RTCRay\f[] structure defines the ray layout for a single ray. -The ray contains the origin (\f[C]org_x\f[], \f[C]org_y\f[], -\f[C]org_z\f[] members), direction vector (\f[C]dir_x\f[], -\f[C]dir_y\f[], \f[C]dir_z\f[] members), and ray segment (\f[C]tnear\f[] -and \f[C]tfar\f[] members). +The \f[C]RTCRay\f[R] structure defines the ray layout for a single ray. +The ray contains the origin (\f[C]org_x\f[R], \f[C]org_y\f[R], +\f[C]org_z\f[R] members), direction vector (\f[C]dir_x\f[R], +\f[C]dir_y\f[R], \f[C]dir_z\f[R] members), and ray segment +(\f[C]tnear\f[R] and \f[C]tfar\f[R] members). The ray direction does not have to be normalized, and only the parameter -range specified by the \f[C]tnear\f[]/\f[C]tfar\f[] interval is +range specified by the \f[C]tnear\f[R]/\f[C]tfar\f[R] interval is considered valid. .PP -The ray segment must be in the range [0, ∞], 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[] < \f[C]tnear\f[] identifies -an inactive ray. +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, 1] -(\f[C]time\f[] member), a ray mask (\f[C]mask\f[] member), a ray ID -(\f[C]id\f[] member), and ray flags (\f[C]flags\f[] member). +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 +(\f[C]id\f[R] member), and ray flags (\f[C]flags\f[R] member). The ray mask can be used to mask out some geometries for some rays (see -\f[C]rtcSetGeometryMask\f[] for more details). +\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. .PP -The \f[C]embree3/rtcore_ray.h\f[] header additionally defines the same +The \f[C]embree3/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[] type), size 8 -(\f[C]RTCRay8\f[] type), and size 16 (\f[C]RTCRay16\f[] type). -The header additionally defines an \f[C]RTCRayNt\f[] template for ray +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. .SS EXIT STATUS .SS SEE ALSO diff --git a/man/man3/RTCRayHit.3embree3 b/man/man3/RTCRayHit.3embree3 index 57e89a3ab7..86d0d68aae 100644 --- a/man/man3/RTCRayHit.3embree3 +++ b/man/man3/RTCRayHit.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCRay" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,33 +6,33 @@ .IP .nf \f[C] -RTCRayHit\ \-\ combined\ single\ ray/hit\ structure -\f[] +RTCRayHit \- combined single ray/hit structure +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCORE_ALIGN(16)\ RTCRayHit +struct RTCORE_ALIGN(16) RTCRayHit { -\ \ struct\ RTCRay\ ray; -\ \ struct\ RTCHit\ hit; + struct RTCRay ray; + struct RTCHit hit; }; -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]RTCRayHit\f[] structure is used as input for the -\f[C]rtcIntersect\f[]\-type functions and stores the ray to intersect +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 and some hit fields that hold the intersection result afterwards. .PP -The \f[C]embree3/rtcore_ray.h\f[] header additionally defines the same +The \f[C]embree3/rtcore_ray.h\f[R] header additionally defines the same ray/hit structure in structure of array (SOA) layout for API functions -accepting ray packets of size 4 (\f[C]RTCRayHit4\f[] type), size 8 -(\f[C]RTCRayHit8\f[] type), and size 16 (\f[C]RTCRayHit16\f[] type). -The header additionally defines an \f[C]RTCRayHitNt\f[] template to +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. .SS EXIT STATUS .SS SEE ALSO diff --git a/man/man3/RTCRayHitN.3embree3 b/man/man3/RTCRayHitN.3embree3 index 6df1b281f4..dc2fced3cf 100644 --- a/man/man3/RTCRayHitN.3embree3 +++ b/man/man3/RTCRayHitN.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCRayHitN" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,37 +6,37 @@ .IP .nf \f[C] -RTCRayHitN\ \-\ combined\ ray/hit\ packet\ of\ runtime\ size -\f[] +RTCRayHitN \- combined ray/hit packet of runtime size +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCRayHitN; +struct RTCRayHitN; -struct\ RTCRayN*\ RTCRayHitN_RayN(struct\ RTCRayHitN*\ rayhit,\ unsigned\ int\ N); -struct\ RTCHitN*\ RTCRayHitN_HitN(struct\ RTCRayHitN*\ rayhit,\ unsigned\ int\ N); -\f[] +struct RTCRayN* RTCRayHitN_RayN(struct RTCRayHitN* rayhit, unsigned int N); +struct RTCHitN* RTCRayHitN_HitN(struct RTCRayHitN* rayhit, unsigned int N); +\f[R] .fi .SS DESCRIPTION .PP When the packet size of a ray/hit structure is not known at compile time -(e.g. -when Embree returns a ray/hit packet in the -\f[C]RTCIntersectFunctionN\f[] callback function), Embree uses the -\f[C]RTCRayHitN\f[] type for ray packets. +(e.g.\ when Embree returns a ray/hit packet in the +\f[C]RTCIntersectFunctionN\f[R] callback function), Embree uses the +\f[C]RTCRayHitN\f[R] type for ray packets. These ray/hit packets can only have sizes of 1, 4, 8, or 16. No other packet size will be used. .PP You can either implement different special code paths for each of these possible packet sizes and cast the ray/hit to the appropriate ray/hit -packet type, or extract the \f[C]RTCRayN\f[] and \f[C]RTCHitN\f[] -components using the \f[C]rtcGetRayN\f[] and \f[C]rtcGetHitN\f[] helper -functions and use the \f[C]RTCRayN_XXX\f[] and \f[C]RTCHitN_XXX\f[] -functions to access the ray and hit parts of the structure. +packet type, or extract the \f[C]RTCRayN\f[R] and \f[C]RTCHitN\f[R] +components using the \f[C]rtcGetRayN\f[R] and \f[C]rtcGetHitN\f[R] +helper functions and use the \f[C]RTCRayN_XXX\f[R] and +\f[C]RTCHitN_XXX\f[R] functions to access the ray and hit parts of the +structure. .SS EXIT STATUS .SS SEE ALSO .PP diff --git a/man/man3/RTCRayN.3embree3 b/man/man3/RTCRayN.3embree3 index ec3bc8d79f..fee56dbe98 100644 --- a/man/man3/RTCRayN.3embree3 +++ b/man/man3/RTCRayN.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTCRayN" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,52 +6,51 @@ .IP .nf \f[C] -RTCRayN\ \-\ ray\ packet\ of\ runtime\ size -\f[] +RTCRayN \- ray packet of runtime size +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCRayN; +struct RTCRayN; -float&\ RTCRayN_org_x(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCRayN_org_y(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCRayN_org_z(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCRayN_tnear(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); +float& RTCRayN_org_x(RTCRayN* ray, unsigned int N, unsigned int i); +float& RTCRayN_org_y(RTCRayN* ray, unsigned int N, unsigned int i); +float& RTCRayN_org_z(RTCRayN* ray, unsigned int N, unsigned int i); +float& RTCRayN_tnear(RTCRayN* ray, unsigned int N, unsigned int i); -float&\ RTCRayN_dir_x(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCRayN_dir_y(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCRayN_dir_z(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -float&\ RTCRayN_time\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); +float& RTCRayN_dir_x(RTCRayN* ray, unsigned int N, unsigned int i); +float& RTCRayN_dir_y(RTCRayN* ray, unsigned int N, unsigned int i); +float& RTCRayN_dir_z(RTCRayN* ray, unsigned int N, unsigned int i); +float& RTCRayN_time (RTCRayN* ray, unsigned int N, unsigned int i); -float&\ \ \ \ \ \ \ \ RTCRayN_tfar\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -unsigned\ int&\ RTCRayN_mask\ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -unsigned\ int&\ RTCRayN_id\ \ \ (RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -unsigned\ int&\ RTCRayN_flags(RTCRayN*\ ray,\ unsigned\ int\ N,\ unsigned\ int\ i); -\f[] +float& RTCRayN_tfar (RTCRayN* ray, unsigned int N, unsigned int i); +unsigned int& RTCRayN_mask (RTCRayN* ray, unsigned int N, unsigned int i); +unsigned int& RTCRayN_id (RTCRayN* ray, unsigned int N, unsigned int i); +unsigned int& RTCRayN_flags(RTCRayN* ray, unsigned int N, unsigned int i); +\f[R] .fi .SS DESCRIPTION .PP -When the ray packet size is not known at compile time (e.g. -when Embree returns a ray packet in the \f[C]RTCFilterFuncN\f[] callback -function), Embree uses the \f[C]RTCRayN\f[] type for ray packets. +When the ray packet size is not known at compile time (e.g.\ when Embree +returns a ray packet in the \f[C]RTCFilterFuncN\f[R] callback function), +Embree uses the \f[C]RTCRayN\f[R] type for ray packets. These ray packets can only have sizes of 1, 4, 8, or 16. No other packet size will be used. .PP You can either implement different special code paths for each of these possible packet sizes and cast the ray to the appropriate ray packet type, or implement one general code path that uses the -\f[C]RTCRayN_XXX\f[] helper functions to access the ray packet +\f[C]RTCRayN_XXX\f[R] helper functions to access the ray packet components. .PP -These helper functions get a pointer to the ray packet (\f[C]ray\f[] -argument), the packet size (\f[C]N\f[] argument), and returns a -reference to a component (e.g. -x\-component of origin) of the the i\-th ray of the packet (\f[C]i\f[] -argument). +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 +ray of the packet (\f[C]i\f[R] argument). .SS EXIT STATUS .SS SEE ALSO .PP diff --git a/man/man3/RTC_GEOMETRY_TYPE_CURVE.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_CURVE.3embree3 index 57c1a41536..1b41322a56 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_CURVE.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_CURVE.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_*_CURVE" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,122 +6,127 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\ \- -\ \ flat\ curve\ geometry\ with\ linear\ basis +RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE \- + flat curve geometry with linear basis -RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\ \- -\ \ flat\ curve\ geometry\ with\ cubic\ Bézier\ basis +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\ \-\ -\ \ flat\ curve\ geometry\ with\ cubic\ Hermite\ basis +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\ \- -\ \ flat\ normal\ oriented\ curve\ geometry\ with\ cubic\ Bézier\ basis +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\ \-\ -\ \ flat\ normal\ oriented\ curve\ geometry\ with\ cubic\ Hermite\ basis +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_ROUND_LINEAR_CURVE\ \- -\ \ capped\ cone\ curve\ geometry\ with\ linear\ basis\ and\ spherical\ ending +RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE \- + capped cone curve geometry with linear basis \- discontinuous at edge boundaries -RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\ \- -\ \ swept\ surface\ curve\ geometry\ with\ cubic\ Bézier\ basis +RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE \- + capped cone curve geometry with linear basis and spherical ending -RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\ \- -\ \ swept\ surface\ curve\ geometry\ with\ cubic\ B\-spline\ basis +RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE \- + swept surface curve geometry with cubic B\['e]zier basis -RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\ \- -\ \ swept\ surface\ curve\ geometry\ with\ cubic\ Hermite\ basis +RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE \- + swept surface curve geometry with cubic B\-spline basis -RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\ \- -\ \ swept\ surface\ curve\ geometry\ with\ Catmull\-Rom\ basis -\f[] +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 +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); -\f[] +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); +\f[R] .fi .SS DESCRIPTION .PP -Curves with per vertex radii are supported with linear, cubic Bézier, -cubic B\-spline, and cubic Hermite bases. +Curves with per vertex radii are supported with linear, cubic +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[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BSPLINE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_HERMITE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_CATMULL_ROM_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\f[], or -\f[C]RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\f[] to the -\f[C]rtcNewGeometry\f[] function. +\f[C]RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BSPLINE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_HERMITE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_CATMULL_ROM_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\f[R], or +\f[C]RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\f[R] to the +\f[C]rtcNewGeometry\f[R] function. The curve indices can be specified through an index buffer -(\f[C]RTC_BUFFER_TYPE_INDEX\f[]) and the curve vertices through a vertex -buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[]). +(\f[C]RTC_BUFFER_TYPE_INDEX\f[R]) and the curve vertices through a +vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[R]). For the Hermite basis a tangent buffer -(\f[C]RTC_BUFFER_TYPE_TANGENT\f[]), normal oriented curves a normal -buffer (\f[C]RTC_BUFFER_TYPE_NORMAL\f[]), and for normal oriented +(\f[C]RTC_BUFFER_TYPE_TANGENT\f[R]), normal oriented curves a normal +buffer (\f[C]RTC_BUFFER_TYPE_NORMAL\f[R]), and for normal oriented Hermite curves a normal derivative buffer -(\f[C]RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\f[]) has to get specified +(\f[C]RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\f[R]) has to get specified additionally. -See \f[C]rtcSetGeometryBuffer\f[] and -\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set +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 -(\f[C]RTC_FORMAT_UINT\f[] format), each pointing to the first control +(\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 are present. .PP The vertex buffer stores each control vertex in the form of a single -precision position and radius stored in (\f[C]x\f[], \f[C]y\f[], -\f[C]z\f[], \f[C]r\f[]) order in memory (\f[C]RTC_FORMAT_FLOAT4\f[] +precision position and radius stored in (\f[C]x\f[R], \f[C]y\f[R], +\f[C]z\f[R], \f[C]r\f[R]) order in memory (\f[C]RTC_FORMAT_FLOAT4\f[R] format). The number of vertices is inferred from the size of this buffer. The radii may be smaller than zero but the interpolated radii should always be greater or equal to zero. Similarly, the tangent buffer stores the derivative of each control -vertex (\f[C]x\f[], \f[C]y\f[], \f[C]z\f[], \f[C]r\f[] order and -\f[C]RTC_FORMAT_FLOAT4\f[] format) and the normal buffer stores a single -precision normal per control vertex (\f[C]x\f[], \f[C]y\f[], \f[C]z\f[] -order and \f[C]RTC_FORMAT_FLOAT3\f[] format). +vertex (\f[C]x\f[R], \f[C]y\f[R], \f[C]z\f[R], \f[C]r\f[R] order and +\f[C]RTC_FORMAT_FLOAT4\f[R] format) and the normal buffer stores a +single precision normal per control vertex (\f[C]x\f[R], \f[C]y\f[R], +\f[C]z\f[R] order and \f[C]RTC_FORMAT_FLOAT3\f[R] format). .SS Linear Basis .PP For the linear basis the indices point to the first of 2 consecutive @@ -132,9 +137,9 @@ 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 -type \f[C]RTC_BUFFER_TYPE_FLAGS\f[] which contains bytes that encode if -the left neighbor segment (\f[C]RTC_CURVE_FLAG_NEIGHBOR_LEFT\f[] flag) -and/or right neighbor segment (\f[C]RTC_CURVE_FLAG_NEIGHBOR_RIGHT\f[] +type \f[C]RTC_BUFFER_TYPE_FLAGS\f[R] which contains bytes that encode if +the left neighbor segment (\f[C]RTC_CURVE_FLAG_NEIGHBOR_LEFT\f[R] flag) +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 @@ -142,7 +147,7 @@ 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 segement, and to start at the previous vertex in the vertex +current segment, and to start at the previous vertex in the vertex buffer. Similarly, the right neighbor segment is assumed to start at the end vertex of the current segment, and to end at the next vertex in the @@ -150,15 +155,15 @@ vertex buffer. .PP Only when the left and right bits are properly specified the current segment can properly attach to the left and/or right neighbor, otherwise -the touching area may not get rendererd properly. -.SS Bézier Basis +the touching area may not get rendered properly. +.SS B\['e]zier Basis .PP -For the cubic Bézier basis the indices point to the first of 4 +For the cubic B\['e]zier basis the indices point to the first of 4 consecutive control points in the vertex buffer. -These control points use the cubic Bézier basis, where the first control -point represents the start point of the curve, and the 4th control point -the end point of the curve. -The Bézier basis is interpolating, thus the curve does go exactly +These control points use the cubic B\['e]zier basis, where the first +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 .PP @@ -169,9 +174,9 @@ equidistant knot vector). This basis is not interpolating, thus the curve does in general not go through any of the control points directly. 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 make this basis a good choise to construct continuous +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. .SS Hermite Basis .PP @@ -185,7 +190,7 @@ 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 -usig the Hermite basis, by calculating a proper tangent buffer from the +using the Hermite basis, by calculating a proper tangent buffer from the control points. .SS Catmull\-Rom Basis .PP @@ -195,23 +200,23 @@ 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[] flat mode is a fast mode designed +The \f[C]RTC_GEOMETRY_TYPE_FLAT_*\f[R] flat mode is a fast mode designed to render distant hair. In this mode the curve is rendered as a connected sequence of ray facing quads. Individual quads are considered to have subpixel size, and zooming onto the curve might show geometric artifacts. The number of quads to subdivide into can be specified through the -\f[C]rtcSetGeometryTessellationRate\f[] function. +\f[C]rtcSetGeometryTessellationRate\f[R] function. By default the tessellation rate is 4. .SS Normal Oriented Curves .PP -The \f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_*\f[] mode is a mode designed -to render blades of grass. +The \f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_*\f[R] mode is a mode +designed to render blades of grass. In this mode a vertex spline has to get specified as for the previous modes, but additionally a normal spline is required. -If the Hermite basis is used, the \f[C]RTC_BUFFER_TYPE_NORMAL\f[] and -\f[C]RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\f[] buffers have both to be set. +If the Hermite basis is used, the \f[C]RTC_BUFFER_TYPE_NORMAL\f[R] and +\f[C]RTC_BUFFER_TYPE_NORMAL_DERIVATIVE\f[R] buffers have both to be set. .PP The curve is rendered as a flat band whose center approximately follows the provided vertex spline, whose half width approximately follows the @@ -220,7 +225,7 @@ follows the provided normal spline. .PP 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ézier basis (along the +basis (perpendicular to the curve) and cubic B\['e]zier basis (along the curve). We use a guide curve and its derivatives to construct the control points of that surface. @@ -233,9 +238,12 @@ Note that this construction does not work when the provided normals are parallel to the curve direction. For this reason the provided normals should best be kept as perpendicular to the curve direction as possible. +We further assume second order derivatives of the center curve to be +zero for this construction, as otherwise very large curvatures occurring +in corner cases, can thicken the constructed curve significantly. .SS Round Curves .PP -In the \f[C]RTC_GEOMETRY_TYPE_ROUND_*\f[] round mode, a real geometric +In the \f[C]RTC_GEOMETRY_TYPE_ROUND_*\f[R] round mode, a real geometric surface is rendered for the curve, which is more expensive but allows closeup views. .PP @@ -245,7 +253,7 @@ 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 segment are clipped away (if that next segment exists). -This way a curve is closed on both ends and the interiour will render +This way a curve is closed on both ends and the interior will render properly as long as only neighboring segments penetrate into a segment. For this to work properly it is important that the flags buffer is properly populated with neighbor information. @@ -263,14 +271,14 @@ 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[] is set to the tangent of +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[] 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 -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call. +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. For the Hermite basis also a tangent buffer has to be set for each time @@ -281,8 +289,8 @@ Also see tutorials [Hair] and [Curves] for examples of how to create and use curve geometries. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [RTCCurveFlags] diff --git a/man/man3/RTC_GEOMETRY_TYPE_GRID.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_GRID.3embree3 index fba2b5f084..b77aa32943 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_GRID.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_GRID.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_GRID" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,80 +6,79 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_GRID\ \-\ grid\ geometry\ type -\f[] +RTC_GEOMETRY_TYPE_GRID \- grid geometry type +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ geometry\ = -\ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_GRID); -\f[] +RTCGeometry geometry = + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_GRID); +\f[R] .fi .SS DESCRIPTION .PP -Grid meshes are created by passing \f[C]RTC_GEOMETRY_TYPE_GRID\f[] to -the \f[C]rtcNewGeometry\f[] function call, and contain an array of grid +Grid meshes are created by passing \f[C]RTC_GEOMETRY_TYPE_GRID\f[R] to +the \f[C]rtcNewGeometry\f[R] function call, and contain an array of grid primitives. This array of grids can be specified by setting up a grid buffer (with -\f[C]RTC_BUFFER_TYPE_GRID\f[] type and \f[C]RTC_FORMAT_GRID\f[] format) -and the grid mesh vertices by setting a vertex buffer -(\f[C]RTC_BUFFER_TYPE_VERTEX\f[] type). -See \f[C]rtcSetGeometryBuffer\f[] and -\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set +\f[C]RTC_BUFFER_TYPE_GRID\f[R] type and \f[C]RTC_FORMAT_GRID\f[R] +format) and the grid mesh vertices by 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 number of grid primitives in the grid mesh is inferred from the size of the grid buffer. .PP -The vertex buffer contains an array of single precision \f[C]x\f[], -\f[C]y\f[], \f[C]z\f[] floating point coordinates -(\f[C]RTC_FORMAT_FLOAT3\f[] format), and the number of vertices is +The vertex buffer contains an array of single precision \f[C]x\f[R], +\f[C]y\f[R], \f[C]z\f[R] floating point coordinates +(\f[C]RTC_FORMAT_FLOAT3\f[R] format), and the number of vertices is inferred from the size of that buffer. .PP -Each grid in the grid buffer is of the type \f[C]RTCGrid\f[]: +Each grid in the grid buffer is of the type \f[C]RTCGrid\f[R]: .IP .nf \f[C] -struct\ RTCGrid +struct RTCGrid { -\ \ unsigned\ int\ startVertexID; -\ \ unsigned\ int\ stride; -\ \ unsigned\ short\ width,height;\ + unsigned int startVertexID; + unsigned int stride; + unsigned short width,height; }; -\f[] +\f[R] .fi .PP -The \f[C]RTCGrid\f[] structure describes a 2D grid of vertices (with +The \f[C]RTCGrid\f[R] structure describes a 2D grid of vertices (with respect to the vertex buffer of the grid mesh). -The \f[C]width\f[] and \f[C]height\f[] members specify the number of -vertices in u and v direction, e.g. -setting both \f[C]width\f[] and \f[C]height\f[] to 3 sets up a 3×3 -vertex grid. -The maximum allowed \f[C]width\f[] and \f[C]height\f[] is 32767. -The \f[C]startVertexID\f[] specifies the ID of the top\-left vertex in -the vertex grid, while the \f[C]stride\f[] parameter specifies a stride +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 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[] and \f[C]height\f[] is -treated as a \f[C](width\-1)\f[] x \f[C](height\-1)\f[] grid of -\f[C]quads\f[] (triangle\-pairs), with the same shared edge handling as +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 for regular quad meshes. -However, the \f[C]u\f[]/\f[C]v\f[] coordinates have the uniform range -\f[C][0..1]\f[] for an entire vertex grid. -The \f[C]u\f[] direction follows the \f[C]width\f[] of the grid while -the \f[C]v\f[] direction the \f[C]height\f[]. +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 -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call. +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. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry] diff --git a/man/man3/RTC_GEOMETRY_TYPE_INSTANCE.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_INSTANCE.3embree3 index 363294055d..68fc6676a4 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_INSTANCE.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_INSTANCE.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_INSTANCE" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,23 +6,23 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_INSTANCE\ \-\ instance\ geometry\ type -\f[] +RTC_GEOMETRY_TYPE_INSTANCE \- instance geometry type +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ geometry\ = -\ \ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_INSTANCE); -\f[] +RTCGeometry geometry = + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE); +\f[R] .fi .SS DESCRIPTION .PP -Embree supports instancing of scenes using affine transformations (3×3 -matrix plus translation). +Embree supports instancing of scenes using affine transformations +(3\[tmu]3 matrix plus translation). 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. @@ -30,52 +30,52 @@ scenes with small memory footprint. Embree supports both single\-level instancing and multi\-level instancing. The maximum instance nesting depth is -\f[C]RTC_MAX_INSTANCE_LEVEL_COUNT\f[]; it can be configured at +\f[C]RTC_MAX_INSTANCE_LEVEL_COUNT\f[R]; it can be configured at compile\-time using the constant -\f[C]EMBREE_MAX_INSTANCE_LEVEL_COUNT\f[]. +\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 debug mode. .PP -Instances are created by passing \f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[] to -the \f[C]rtcNewGeometry\f[] function call. +Instances are created by passing \f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[R] to +the \f[C]rtcNewGeometry\f[R] function call. The instanced scene can be set using the -\f[C]rtcSetGeometryInstancedScene\f[] call, and the affine -transformation can be set using the \f[C]rtcSetGeometryTransform\f[] +\f[C]rtcSetGeometryInstancedScene\f[R] call, and the affine +transformation can be set using the \f[C]rtcSetGeometryTransform\f[R] function. .PP -Please note that \f[C]rtcCommitScene\f[] on the instanced scene should -be called first, followed by \f[C]rtcCommitGeometry\f[] on the instance, -followed by \f[C]rtcCommitScene\f[] for the top\-level scene containing -the instance. +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 +containing the instance. .PP -If a ray hits the instance, the \f[C]geomID\f[] and \f[C]primID\f[] +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[] member of +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 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[] +To achieve this, the user geometry code should set the \f[C]instID\f[R] member of the intersection context to the geometry ID of the instance, -then trace the transformed ray, and finally set the \f[C]instID\f[] +then trace the transformed ray, and finally set the \f[C]instID\f[R] field of the intersection context again to \-1. -The \f[C]instID\f[] field is copied automatically by each primitive -intersector into the \f[C]instID\f[] field of the hit structure when the -primitive is hit. +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 -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] function. +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[] function. +\f[C]rtcSetGeometryTransform\f[R] function. .PP See tutorials [Instanced Geometry] and [Multi Level Instancing] for examples of how to use instances. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcSetGeometryInstancedScene], diff --git a/man/man3/RTC_GEOMETRY_TYPE_POINT.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_POINT.3embree3 index 52bb881d9d..1729cd4389 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_POINT.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_POINT.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_*_POINT" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,62 +6,62 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_SPHERE_POINT\ \- -\ \ point\ geometry\ spheres +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 -\f[] +RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT \- + point geometry with normal\-oriented discs +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_SPHERE_POINT); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_DISC_POINT); -rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT); -\f[] +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SPHERE_POINT); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_DISC_POINT); +rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT); +\f[R] .fi .SS DESCRIPTION .PP 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[], -\f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[], or -\f[C]RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT\f[] to the -\f[C]rtcNewGeometry\f[] function. +\f[C]RTC_GEOMETRY_TYPE_SPHERE_POINT\f[R], +\f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[R], or +\f[C]RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT\f[R] to the +\f[C]rtcNewGeometry\f[R] function. The point vertices can be specified t through a vertex buffer -(\f[C]RTC_BUFFER_TYPE_VERTEX\f[]). +(\f[C]RTC_BUFFER_TYPE_VERTEX\f[R]). For the normal oriented discs a normal buffer -(\f[C]RTC_BUFFER_TYPE_NORMAL\f[]) has to get specified additionally. -See \f[C]rtcSetGeometryBuffer\f[] and -\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set +(\f[C]RTC_BUFFER_TYPE_NORMAL\f[R]) has to get specified additionally. +See \f[C]rtcSetGeometryBuffer\f[R] and +\f[C]rtcSetSharedGeometryBuffer\f[R] for more details on how to set buffers. .PP The vertex buffer stores each control vertex in the form of a single -precision position and radius stored in (\f[C]x\f[], \f[C]y\f[], -\f[C]z\f[], \f[C]r\f[]) order in memory (\f[C]RTC_FORMAT_FLOAT4\f[] +precision position and radius stored in (\f[C]x\f[R], \f[C]y\f[R], +\f[C]z\f[R], \f[C]r\f[R]) order in memory (\f[C]RTC_FORMAT_FLOAT4\f[R] format). The number of vertices is inferred from the size of this buffer. Similarly, the normal buffer stores a single precision normal per -control vertex (\f[C]x\f[], \f[C]y\f[], \f[C]z\f[] order and -\f[C]RTC_FORMAT_FLOAT3\f[] format). +control vertex (\f[C]x\f[R], \f[C]y\f[R], \f[C]z\f[R] order and +\f[C]RTC_FORMAT_FLOAT3\f[R] format). .PP -In the \f[C]RTC_GEOMETRY_TYPE_SPHERE_POINT\f[] mode, a real geometric +In the \f[C]RTC_GEOMETRY_TYPE_SPHERE_POINT\f[R] mode, a real geometric surface is rendered for the curve, which is more expensive but allows closeup views. .PP -The \f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[] flat mode is a fast mode +The \f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[R] flat mode is a fast mode designed to render distant points. In this mode the point is rendered as a ray facing disc. .PP -The \f[C]RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT\f[] mode is a mode +The \f[C]RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT\f[R] mode is a mode designed as a midpoint geometrically between ray facing discs and spheres. In this mode the point is rendered as a normal oriented disc. @@ -70,7 +70,7 @@ 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 -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call. +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. .PP @@ -78,8 +78,8 @@ Also see tutorial [Points] for an example of how to create and use point geometries. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry] diff --git a/man/man3/RTC_GEOMETRY_TYPE_QUAD.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_QUAD.3embree3 index 332a251940..f78d415980 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_QUAD.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_QUAD.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_QUAD" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,59 +6,59 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_QUAD\ \-\ quad\ geometry\ type -\f[] +RTC_GEOMETRY_TYPE_QUAD \- quad geometry type +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ geometry\ = -\ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_QUAD); -\f[] +RTCGeometry geometry = + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_QUAD); +\f[R] .fi .SS DESCRIPTION .PP -Quad meshes are created by passing \f[C]RTC_GEOMETRY_TYPE_QUAD\f[] to -the \f[C]rtcNewGeometry\f[] function call. +Quad meshes are created by passing \f[C]RTC_GEOMETRY_TYPE_QUAD\f[R] to +the \f[C]rtcNewGeometry\f[R] function call. The quad indices can be specified by setting an index buffer -(\f[C]RTC_BUFFER_TYPE_INDEX\f[] type) and the quad vertices by setting a -vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[] type). -See \f[C]rtcSetGeometryBuffer\f[] and -\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set +(\f[C]RTC_BUFFER_TYPE_INDEX\f[R] type) and the quad vertices by 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 contains an array of four 32\-bit indices per quad -(\f[C]RTC_FORMAT_UINT4\f[] format), and the number of primitives is +(\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[], -\f[C]y\f[], \f[C]z\f[] floating point coordinates -(\f[C]RTC_FORMAT_FLOAT3\f[] format), and the number of vertices is +The vertex buffer contains an array of single precision \f[C]x\f[R], +\f[C]y\f[R], \f[C]z\f[R] floating point coordinates +(\f[C]RTC_FORMAT_FLOAT3\f[R] format), and the number of vertices is inferred from the size of that buffer. The vertex buffer can be at most 16 GB large. .PP A quad is internally handled as a pair of two triangles -\f[C]v0,v1,v3\f[] and \f[C]v2,v3,v1\f[], with the -\f[C]u\[aq]\f[]/\f[C]v\[aq]\f[] coordinates of the second triangle -corrected by \f[C]u\ =\ 1\-u\[aq]\f[] and \f[C]v\ =\ 1\-v\[aq]\f[] to -produce a quad parametrization where \f[C]u\f[] and \f[C]v\f[] are in +\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 +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[] as -base point, and the vector \f[C]p1\ \-\ p0\f[] as \f[C]u\f[]\-direction, -and \f[C]p3\ \-\ p0\f[] as v\-direction. -Thus vertex attributes \f[C]t0,t1,t2,t3\f[] can be bilinearly +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. +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) -\f[] +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[] \-> \f[C]v0,v1,v2,v2\f[]). +(\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. @@ -69,17 +69,17 @@ following picture. .IP .nf \f[C] -\f[] +\f[R] .fi .PP For multi\-segment motion blur, the number of time steps must be first -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call. +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. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry] diff --git a/man/man3/RTC_GEOMETRY_TYPE_SUBDIVISION.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_SUBDIVISION.3embree3 index 733048f4bd..f911ad3f51 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_SUBDIVISION.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_SUBDIVISION.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_SUBDIVISION" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,18 +6,18 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_SUBDIVISION\ \-\ subdivision\ geometry\ type -\f[] +RTC_GEOMETRY_TYPE_SUBDIVISION \- subdivision geometry type +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ geometry\ = -\ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_SUBDIVISION); -\f[] +RTCGeometry geometry = + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION); +\f[R] .fi .SS DESCRIPTION .PP @@ -28,47 +28,47 @@ The number of vertices per face can be in the range of 3 to 15 vertices (triangles, quadrilateral, pentagons, etc). .PP Subdivision meshes are created by passing -\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[] to the \f[C]rtcNewGeometry\f[] +\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[R] to the \f[C]rtcNewGeometry\f[R] function. Various buffers need to be set by the application to set up the subdivision mesh. -See \f[C]rtcSetGeometryBuffer\f[] and -\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set +See \f[C]rtcSetGeometryBuffer\f[R] and +\f[C]rtcSetSharedGeometryBuffer\f[R] for more details on how to set buffers. -The face buffer (\f[C]RTC_BUFFER_TYPE_FACE\f[] type and -\f[C]RTC_FORMAT_UINT\f[] format) contains the number of edges/indices of -each face (3 to 15), and the number of faces is inferred from the size +The face buffer (\f[C]RTC_BUFFER_TYPE_FACE\f[R] type and +\f[C]RTC_FORMAT_UINT\f[R] format) contains the number of edges/indices +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] +format) for each face, and the number of edges is inferred from the size of this buffer. -The index buffer (\f[C]RTC_BUFFER_TYPE_INDEX\f[] type) contains multiple -(3 to 15) 32\-bit vertex indices (\f[C]RTC_FORMAT_UINT\f[] 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[] type) stores an array -of single precision \f[C]x\f[], \f[C]y\f[], \f[C]z\f[] floating point -coordinates (\f[C]RTC_FORMAT_FLOAT3\f[] format), and the number of -vertices is inferred from the size of this buffer. +The vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[R] type) stores an +array of single precision \f[C]x\f[R], \f[C]y\f[R], \f[C]z\f[R] floating +point coordinates (\f[C]RTC_FORMAT_FLOAT3\f[R] format), and the number +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. -The standard vertex buffers (\f[C]RTC_BUFFER_TYPE_VERTEX\f[]) are always -bound to the geometry topology (topology 0) thus use -\f[C]RTC_BUFFER_TYPE_INDEX\f[] with buffer slot 0. +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. 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[]) which contains an array of 32\-bit -indices (\f[C]RTC_FORMAT_UINT\f[] format) of faces that should be +(\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. The number of holes is inferred from the size of this buffer. .PP Optionally, the application can fill the level buffer -(\f[C]RTC_BUFFER_TYPE_LEVEL\f[]) with a tessellation rate for each of +(\f[C]RTC_BUFFER_TYPE_LEVEL\f[R]) with a tessellation rate for each of the edges of each face. This buffer must have the same size as the index buffer. The tessellation level is a positive floating point value -(\f[C]RTC_FORMAT_FLOAT\f[] format) that specifies how many quads along +(\f[C]RTC_FORMAT_FLOAT\f[R] format) that specifies how many quads along the edge should be generated during tessellation. If no level buffer is specified, a level of 1 is used. The maximally supported edge level is 4096, and larger levels are @@ -77,20 +77,20 @@ Note that edges may be shared between (typically 2) faces. To guarantee a watertight tessellation, the level of these shared edges should be identical. A uniform tessellation rate for an entire subdivision mesh can be set by -using the \f[C]rtcSetGeometryTessellationRate\f[] function. +using the \f[C]rtcSetGeometryTessellationRate\f[R] function. The existence of a level buffer has precedence over the uniform tessellation rate. .PP 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[]) contains an array of pairs -of 32\-bit vertex indices (\f[C]RTC_FORMAT_UINT2\f[] format) that +(\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 specify unoriented edges in the geometry topology. The edge crease weight buffer -(\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT\f[]) stores for each of these -crease edges a positive floating point weight (\f[C]RTC_FORMAT_FLOAT\f[] -format). +(\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT\f[R]) stores for each of these +crease edges a positive floating point weight +(\f[C]RTC_FORMAT_FLOAT\f[R] format). The number of edge creases is inferred from the size of these buffers, which has to be identical. The larger a weight, the sharper the edge. @@ -107,13 +107,13 @@ Edge crease features are shared between all topologies. 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[]), contains an array of -32\-bit vertex indices (\f[C]RTC_FORMAT_UINT\f[] format) to specify a +(\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 set of vertices from the geometry topology. The vertex crease weight buffer -(\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT\f[]) specifies for each of +(\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT\f[R]) specifies for each of these vertices a positive floating point weight -(\f[C]RTC_FORMAT_FLOAT\f[] format). +(\f[C]RTC_FORMAT_FLOAT\f[R] format). The number of vertex creases is inferred from the size of these buffers, and has to be identical. The larger a weight, the sharper the vertex. @@ -126,11 +126,11 @@ undefined behavior. Vertex crease features are shared between all topologies. .PP Subdivision modes can be used to force linear interpolation for parts of -the subdivision mesh; see \f[C]rtcSetGeometrySubdivisionMode\f[] for +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 -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call. +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 size. @@ -143,39 +143,39 @@ The parametrization for subdivision faces is different for quadrilaterals and non\-quadrilateral faces. .PP The parametrization of a quadrilateral face uses the first vertex -\f[C]p0\f[] as base point, and the vector \f[C]p1\ \-\ p0\f[] as -u\-direction and \f[C]p3\ \-\ p0\f[] 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[] (of the \f[C]n\f[]\-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[] and local UVs +The following code extracts the sub\-patch ID \f[C]i\f[R] and local UVs of this subpatch: .IP .nf \f[C] -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; -\f[] +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; +\f[R] .fi .PP This encoding allows local subpatch UVs to be in the range -\f[C][\-0.5,1.5[\f[] thus negative subpatch UVs can be passed to -\f[C]rtcInterpolate\f[] to sample subpatches slightly out of bounds. +\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[] (or \f[C]v\f[]) on a subpatch by adding \f[C]du\f[] (or -\f[C]dv\f[]) to the special UV encoding as long as it does not fall out -of the \f[C][\-0.5,1.5[\f[] range. +\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. .PP To smoothly interpolate vertex attributes over the subdivision surface -we recommend using the \f[C]rtcInterpolate\f[] function, which will +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 @@ -187,24 +187,24 @@ This way, texture coordinates may use a different topology with additional boundaries to construct separate UV regions inside one subdivision mesh. .PP -Each such topology \f[C]i\f[] has a separate index buffer (specified -using \f[C]RTC_BUFFER_TYPE_INDEX\f[] with buffer slot \f[C]i\f[]) and +Each such topology \f[C]i\f[R] has a separate index buffer (specified +using \f[C]RTC_BUFFER_TYPE_INDEX\f[R] with buffer slot \f[C]i\f[R]) and separate subdivision mode that can be set using -\f[C]rtcSetGeometrySubdivisionMode\f[]. -A vertex attribute buffer \f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[] -bound to a buffer slot \f[C]j\f[] can be assigned to use a topology for -interpolation using the \f[C]rtcSetGeometryVertexAttributeTopology\f[] +\f[C]rtcSetGeometrySubdivisionMode\f[R]. +A vertex attribute buffer \f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[R] +bound to a buffer slot \f[C]j\f[R] can be assigned to use a topology for +interpolation using the \f[C]rtcSetGeometryVertexAttributeTopology\f[R] call. .PP -The face buffer (\f[C]RTC_BUFFER_TYPE_FACE\f[] type) is shared between -all topologies, which means that the \f[C]n\f[]\-th primitive always has -the same number of vertices (e.g. -being a triangle or a quad) for each topology. +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. However, the indices of the topologies themselves may be different. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry] diff --git a/man/man3/RTC_GEOMETRY_TYPE_TRIANGLE.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_TRIANGLE.3embree3 index 7e3c47c99e..716662b3e1 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_TRIANGLE.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_TRIANGLE.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_TRIANGLE" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,50 +6,50 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_TRIANGLE\ \-\ triangle\ geometry\ type -\f[] +RTC_GEOMETRY_TYPE_TRIANGLE \- triangle geometry type +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ geometry\ = -\ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_TRIANGLE); -\f[] +RTCGeometry geometry = + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE); +\f[R] .fi .SS DESCRIPTION .PP Triangle meshes are created by passing -\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[] to the \f[C]rtcNewGeometry\f[] +\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[R] to the \f[C]rtcNewGeometry\f[R] function call. The triangle indices can be specified by setting an index buffer -(\f[C]RTC_BUFFER_TYPE_INDEX\f[] type) and the triangle vertices by -setting a vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[] type). -See \f[C]rtcSetGeometryBuffer\f[] and -\f[C]rtcSetSharedGeometryBuffer\f[] for more details on how to set +(\f[C]RTC_BUFFER_TYPE_INDEX\f[R] type) and the triangle vertices by +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 -triangle (\f[C]RTC_FORMAT_UINT3\f[] 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[], -\f[C]y\f[], \f[C]z\f[] floating point coordinates -(\f[C]RTC_FORMAT_FLOAT3\f[] format), and the number of vertices are +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], +\f[C]y\f[R], \f[C]z\f[R] floating point coordinates +(\f[C]RTC_FORMAT_FLOAT3\f[R] format), and the number of vertices are 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[] as -base point, the vector \f[C]p1\ \-\ p0\f[] as u\-direction and the -vector \f[C]p2\ \-\ p0\f[] as v\-direction. -Thus vertex attributes \f[C]t0,t1,t2\f[] can be linearly interpolated +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. +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) -\f[] +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 @@ -58,11 +58,11 @@ illustrated in the following picture: .IP .nf \f[C] -\f[] +\f[R] .fi .PP For multi\-segment motion blur, the number of time steps must be first -specified using the \f[C]rtcSetGeometryTimeStepCount\f[] call. +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 size. @@ -71,8 +71,8 @@ Also see tutorial [Triangle Geometry] for an example of how to create triangle meshes. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that be -get queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that be +get queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry] diff --git a/man/man3/RTC_GEOMETRY_TYPE_USER.3embree3 b/man/man3/RTC_GEOMETRY_TYPE_USER.3embree3 index 7fe062b62b..24820b2dfe 100644 --- a/man/man3/RTC_GEOMETRY_TYPE_USER.3embree3 +++ b/man/man3/RTC_GEOMETRY_TYPE_USER.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "RTC_GEOMETRY_TYPE_USER" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,18 +6,18 @@ .IP .nf \f[C] -RTC_GEOMETRY_TYPE_USER\ \-\ user\ geometry\ type -\f[] +RTC_GEOMETRY_TYPE_USER \- user geometry type +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ geometry\ = -\ \ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_USER); -\f[] +RTCGeometry geometry = + rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER); +\f[R] .fi .SS DESCRIPTION .PP @@ -28,45 +28,49 @@ registered callback functions, which enable extending Embree with arbitrary types of primitives. .PP User\-defined geometries are created by passing -\f[C]RTC_GEOMETRY_TYPE_USER\f[] to the \f[C]rtcNewGeometry\f[] function -call. +\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[]), a user data pointer (see -\f[C]rtcSetGeometryUserData\f[]), a bounding function closure (see -\f[C]rtcSetGeometryBoundsFunction\f[]), as well as user\-defined -intersect (see \f[C]rtcSetGeometryIntersectFunction\f[]) and occluded -(see \f[C]rtcSetGeometryOccludedFunction\f[]) callback functions. +\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 +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 user primitive, while the intersect and occluded callback functions are called to intersect the primitive with a ray. The user data pointer is passed to each callback invocation and can be -used to point to the application\[aq]s representation of the user +used to point to the application\[cq]s representation of the user geometry. .PP The creation of a user geometry typically looks the following: .IP .nf \f[C] -RTCGeometry\ geometry\ =\ rtcNewGeometry(device,\ RTC_GEOMETRY_TYPE_USER); -rtcSetGeometryUserPrimitiveCount(geometry,\ numPrimitives); -rtcSetGeometryUserData(geometry,\ userGeometryRepresentation); -rtcSetGeometryBoundsFunction(geometry,\ boundsFunction); -rtcSetGeometryIntersectFunction(geometry,\ intersectFunction); -rtcSetGeometryOccludedFunction(geometry,\ occludedFunction); -\f[] +RTCGeometry geometry = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER); +rtcSetGeometryUserPrimitiveCount(geometry, numPrimitives); +rtcSetGeometryUserData(geometry, userGeometryRepresentation); +rtcSetGeometryBoundsFunction(geometry, boundsFunction); +rtcSetGeometryIntersectFunction(geometry, intersectFunction); +rtcSetGeometryOccludedFunction(geometry, occludedFunction); +\f[R] .fi .PP -Please have a look at the \f[C]rtcSetGeometryBoundsFunction\f[], -\f[C]rtcSetGeometryIntersectFunction\f[], and -\f[C]rtcSetGeometryOccludedFunction\f[] functions on the implementation +Please have a look at the \f[C]rtcSetGeometryBoundsFunction\f[R], +\f[C]rtcSetGeometryIntersectFunction\f[R], and +\f[C]rtcSetGeometryOccludedFunction\f[R] functions on the implementation of the callback functions. .PP +Primitives of a user geometry are ignored during rendering when their +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. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcSetGeometryUserPrimitiveCount], diff --git a/man/man3/rtcAttachGeometry.3embree3 b/man/man3/rtcAttachGeometry.3embree3 index f634e0ab7e..b6c9d7250d 100644 --- a/man/man3/rtcAttachGeometry.3embree3 +++ b/man/man3/rtcAttachGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcAttachGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,29 +6,29 @@ .IP .nf \f[C] -rtcAttachGeometry\ \-\ attaches\ a\ geometry\ to\ the\ scene -\f[] +rtcAttachGeometry \- attaches a geometry to the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -unsigned\ int\ rtcAttachGeometry( -\ \ RTCScene\ scene, -\ \ RTCGeometry\ geometry +unsigned int rtcAttachGeometry( + RTCScene scene, + RTCGeometry geometry ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcAttachGeometry\f[] function attaches a geometry -(\f[C]geometry\f[] argument) to a scene (\f[C]scene\f[] argument) and +The \f[C]rtcAttachGeometry\f[R] function attaches a geometry +(\f[C]geometry\f[R] argument) to a scene (\f[C]scene\f[R] argument) and assigns a geometry ID to that geometry. All geometries attached to a scene are defined to be included inside the scene. -A geometry can get attached to multiplee scene. +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 @@ -46,12 +46,12 @@ 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 map to its geometry representation. -See \f[C]rtcSetGeometryUserData\f[] and \f[C]rtcGetGeometryUserData\f[] -for more information. +See \f[C]rtcSetGeometryUserData\f[R] and +\f[C]rtcGetGeometryUserData\f[R] for more information. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryUserData], [rtcGetGeometryUserData] diff --git a/man/man3/rtcAttachGeometryByID.3embree3 b/man/man3/rtcAttachGeometryByID.3embree3 index 6bd86cbe6f..db1ccfe10c 100644 --- a/man/man3/rtcAttachGeometryByID.3embree3 +++ b/man/man3/rtcAttachGeometryByID.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcAttachGeometryByID" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,28 +6,28 @@ .IP .nf \f[C] -rtcAttachGeometryByID\ \-\ attaches\ a\ geometry\ to\ the\ scene -\ \ using\ a\ specified\ geometry\ ID -\f[] +rtcAttachGeometryByID \- attaches a geometry to the scene + using a specified geometry ID +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcAttachGeometryByID( -\ \ RTCScene\ scene, -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ geomID +void rtcAttachGeometryByID( + RTCScene scene, + RTCGeometry geometry, + unsigned int geomID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcAttachGeometryByID\f[] function attaches a geometry -(\f[C]geometry\f[] argument) to a scene (\f[C]scene\f[] argument) and -assigns a user provided geometry ID (\f[C]geomID\f[] argument) to that +The \f[C]rtcAttachGeometryByID\f[R] function attaches a geometry +(\f[C]geometry\f[R] argument) to a scene (\f[C]scene\f[R] argument) and +assigns a user provided geometry ID (\f[C]geomID\f[R] argument) to that geometry. All geometries attached to a scene are defined to be included inside the scene. @@ -50,7 +50,7 @@ memory consumption and performance overhead. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcAttachGeometry] diff --git a/man/man3/rtcBuildBVH.3embree3 b/man/man3/rtcBuildBVH.3embree3 index 6159256785..de7ce2a40f 100644 --- a/man/man3/rtcBuildBVH.3embree3 +++ b/man/man3/rtcBuildBVH.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcBuildBVH" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,210 +6,213 @@ .IP .nf \f[C] -rtcBuildBVH\ \-\ builds\ a\ BVH -\f[] +rtcBuildBVH \- builds a BVH +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTC_ALIGN(32)\ RTCBuildPrimitive +struct RTC_ALIGN(32) RTCBuildPrimitive { -\ \ float\ lower_x,\ lower_y,\ lower_z;\ -\ \ unsigned\ int\ geomID; -\ \ float\ upper_x,\ upper_y,\ upper_z; -\ \ unsigned\ int\ primID; + float lower_x, lower_y, lower_z; + unsigned int geomID; + float upper_x, upper_y, upper_z; + unsigned int primID; }; -typedef\ void*\ (*RTCCreateNodeFunction)\ ( -\ \ RTCThreadLocalAllocator\ allocator, -\ \ unsigned\ int\ childCount, -\ \ void*\ userPtr +typedef void* (*RTCCreateNodeFunction) ( + RTCThreadLocalAllocator allocator, + unsigned int childCount, + void* userPtr ); -typedef\ void\ (*RTCSetNodeChildrenFunction)\ ( -\ \ void*\ nodePtr, -\ \ void**\ children, -\ \ unsigned\ int\ childCount, -\ \ void*\ userPtr +typedef void (*RTCSetNodeChildrenFunction) ( + void* nodePtr, + void** children, + unsigned int childCount, + void* userPtr ); -typedef\ void\ (*RTCSetNodeBoundsFunction)\ ( -\ \ void*\ nodePtr, -\ \ const\ struct\ RTCBounds**\ bounds, -\ \ unsigned\ int\ childCount, -\ \ void*\ userPtr +typedef void (*RTCSetNodeBoundsFunction) ( + void* nodePtr, + const struct RTCBounds** bounds, + unsigned int childCount, + void* userPtr ); -typedef\ void*\ (*RTCCreateLeafFunction)\ ( -\ \ RTCThreadLocalAllocator\ allocator, -\ \ const\ struct\ RTCBuildPrimitive*\ primitives, -\ \ size_t\ primitiveCount, -\ \ void*\ userPtr +typedef void* (*RTCCreateLeafFunction) ( + RTCThreadLocalAllocator allocator, + const struct RTCBuildPrimitive* primitives, + size_t primitiveCount, + void* userPtr ); -typedef\ void\ (*RTCSplitPrimitiveFunction)\ ( -\ \ const\ struct\ RTCBuildPrimitive*\ primitive, -\ \ unsigned\ int\ dimension, -\ \ float\ position, -\ \ struct\ RTCBounds*\ leftBounds, -\ \ struct\ RTCBounds*\ rightBounds, -\ \ void*\ userPtr +typedef void (*RTCSplitPrimitiveFunction) ( + const struct RTCBuildPrimitive* primitive, + unsigned int dimension, + float position, + struct RTCBounds* leftBounds, + struct RTCBounds* rightBounds, + void* userPtr ); -typedef\ bool\ (*RTCProgressMonitorFunction)( -\ \ void*\ userPtr,\ double\ n +typedef bool (*RTCProgressMonitorFunction)( + void* userPtr, double n ); -enum\ RTCBuildFlags +enum RTCBuildFlags { -\ \ RTC_BUILD_FLAG_NONE, -\ \ RTC_BUILD_FLAG_DYNAMIC + RTC_BUILD_FLAG_NONE, + RTC_BUILD_FLAG_DYNAMIC }; -struct\ RTCBuildArguments +struct RTCBuildArguments { -\ \ size_t\ byteSize; + size_t byteSize; -\ \ enum\ RTCBuildQuality\ buildQuality; -\ \ enum\ RTCBuildFlags\ buildFlags; -\ \ unsigned\ int\ maxBranchingFactor; -\ \ unsigned\ int\ maxDepth; -\ \ unsigned\ int\ sahBlockSize; -\ \ unsigned\ int\ minLeafSize; -\ \ unsigned\ int\ maxLeafSize; -\ \ float\ traversalCost; -\ \ float\ intersectionCost; + enum RTCBuildQuality buildQuality; + enum RTCBuildFlags buildFlags; + unsigned int maxBranchingFactor; + unsigned int maxDepth; + unsigned int sahBlockSize; + unsigned int minLeafSize; + unsigned int maxLeafSize; + float traversalCost; + float intersectionCost; -\ \ RTCBVH\ bvh; -\ \ struct\ RTCBuildPrimitive*\ primitives; -\ \ size_t\ primitiveCount; -\ \ size_t\ primitiveArrayCapacity; -\ \ -\ \ RTCCreateNodeFunction\ createNode; -\ \ RTCSetNodeChildrenFunction\ setNodeChildren; -\ \ RTCSetNodeBoundsFunction\ setNodeBounds; -\ \ RTCCreateLeafFunction\ createLeaf; -\ \ RTCSplitPrimitiveFunction\ splitPrimitive; -\ \ RTCProgressMonitorFunction\ buildProgress; -\ \ void*\ userPtr; + RTCBVH bvh; + struct RTCBuildPrimitive* primitives; + size_t primitiveCount; + size_t primitiveArrayCapacity; + + RTCCreateNodeFunction createNode; + RTCSetNodeChildrenFunction setNodeChildren; + RTCSetNodeBoundsFunction setNodeBounds; + RTCCreateLeafFunction createLeaf; + RTCSplitPrimitiveFunction splitPrimitive; + RTCProgressMonitorFunction buildProgress; + void* userPtr; }; -struct\ RTCBuildArguments\ rtcDefaultBuildArguments(); +struct RTCBuildArguments rtcDefaultBuildArguments(); -void*\ rtcBuildBVH( -\ \ const\ struct\ RTCBuildArguments*\ args +void* rtcBuildBVH( + const struct RTCBuildArguments* args ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcBuildBVH\f[] function can be used to build a BVH in a +The \f[C]rtcBuildBVH\f[R] function can be used to build a BVH in a user\-defined format over arbitrary primitives. All arguments to the function are provided through the -\f[C]RTCBuildArguments\f[] structure. +\f[C]RTCBuildArguments\f[R] structure. The first member of that structure must be set to the size of the -structure in bytes (\f[C]bytesSize\f[] member) which allows future +structure in bytes (\f[C]bytesSize\f[R] member) which allows future extensions of the structure. It is recommended to initialize the build arguments structure using the -\f[C]rtcDefaultBuildArguments\f[] function. +\f[C]rtcDefaultBuildArguments\f[R] function. .PP -The \f[C]rtcBuildBVH\f[] function gets passed the BVH to build -(\f[C]bvh\f[] member), the array of primitives (\f[C]primitives\f[] -member), the capacity of that array (\f[C]primitiveArrayCapacity\f[] +The \f[C]rtcBuildBVH\f[R] function gets passed the BVH to build +(\f[C]bvh\f[R] member), the array of primitives (\f[C]primitives\f[R] +member), the capacity of that array (\f[C]primitiveArrayCapacity\f[R] member), the number of primitives stored inside the array -(\f[C]primitiveCount\f[] member), callback function pointers, and a -user\-defined pointer (\f[C]userPtr\f[] member) that is passed to all +(\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 callback functions when invoked. -The \f[C]primitives\f[] array can be freed by the application after the +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. .PP Four callback functions must be registered, which are invoked during -build to create BVH nodes (\f[C]createNode\f[] member), to set the -pointers to all children (\f[C]setNodeChildren\f[] member), to set the -bounding boxes of all children (\f[C]setNodeBounds\f[] member), and to -create a leaf node (\f[C]createLeaf\f[] member). +build to create BVH nodes (\f[C]createNode\f[R] member), to set the +pointers to all children (\f[C]setNodeChildren\f[R] member), to set the +bounding boxes of all children (\f[C]setNodeBounds\f[R] member), and to +create a leaf node (\f[C]createLeaf\f[R] member). .PP The function pointer to the primitive split function -(\f[C]splitPrimitive\f[] member) may be \f[C]NULL\f[], however, then no -spatial splitting in high quality mode is possible. +(\f[C]splitPrimitive\f[R] member) may be \f[C]NULL\f[R], however, then +no spatial splitting in high quality mode is possible. The function pointer used to report the build progress -(\f[C]buildProgress\f[] member) is optional and may also be -\f[C]NULL\f[]. +(\f[C]buildProgress\f[R] member) is optional and may also be +\f[C]NULL\f[R]. .PP Further, some build settings are passed to configure the BVH build. -Using the build quality settings (\f[C]buildQuality\f[] member), one can -select between a faster, low quality build which is good for dynamic +Using the build quality settings (\f[C]buildQuality\f[R] member), one +can select between a faster, low quality build which is good for dynamic scenes, and a standard quality build for static scenes. One can also specify the desired maximum branching factor of the BVH -(\f[C]maxBranchingFactor\f[] member), the maximum depth the BVH should -have (\f[C]maxDepth\f[] member), the block size for the SAH heuristic -(\f[C]sahBlockSize\f[] member), the minimum and maximum leaf size -(\f[C]minLeafSize\f[] and \f[C]maxLeafSize\f[] member), and the +(\f[C]maxBranchingFactor\f[R] member), the maximum depth the BVH should +have (\f[C]maxDepth\f[R] member), the block size for the SAH heuristic +(\f[C]sahBlockSize\f[R] member), the minimum and maximum leaf size +(\f[C]minLeafSize\f[R] and \f[C]maxLeafSize\f[R] member), and the estimated costs of one traversal step and one primitive intersection -(\f[C]traversalCost\f[] and \f[C]intersectionCost\f[] members). -When enabling the \f[C]RTC_BUILD_FLAG_DYNAMIC\f[] build flags -(\f[C]buildFlags\f[] member), re\-build performance for dynamic scenes +(\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 is improved at the cost of higher memory requirements. .PP To spatially split primitives in high quality mode, the builder needs -extra space at the end of the build primitive array to store splitted +extra space at the end of the build primitive array to store split primitives. The total capacity of the build primitive array is passed using the -\f[C]primitiveArrayCapacity\f[] member, and should be about twice the +\f[C]primitiveArrayCapacity\f[R] member, and should be about twice the number of primitives when using spatial splits. .PP -The \f[C]RTCCreateNodeFunc\f[] and \f[C]RTCCreateLeafFunc\f[] callbacks -are passed a thread local allocator object that should be used for fast -allocation of nodes using the \f[C]rtcThreadLocalAlloc\f[] function. +The \f[C]RTCCreateNodeFunc\f[R] and \f[C]RTCCreateLeafFunc\f[R] +callbacks are passed a thread local allocator object that should be used +for fast allocation of nodes using the \f[C]rtcThreadLocalAlloc\f[R] +function. We strongly recommend using this allocation mechanism, as alternative -approaches like standard \f[C]malloc\f[] can be over 10× slower. +approaches like standard \f[C]malloc\f[R] can be over 10\[tmu] slower. The allocator object passed to the create callbacks may be used only inside the current thread. -Memory allocated using \f[C]rtcThreadLocalAlloc\f[] is automatically -freed when the \f[C]RTCBVH\f[] object is deleted. +Memory allocated using \f[C]rtcThreadLocalAlloc\f[R] is automatically +freed when the \f[C]RTCBVH\f[R] object is deleted. If you use your own memory allocation scheme you have to free the memory -yourself when the \f[C]RTCBVH\f[] object is no longer used. +yourself when the \f[C]RTCBVH\f[R] object is no longer used. .PP -The \f[C]RTCCreateNodeFunc\f[] callback additionally gets the number of +The \f[C]RTCCreateNodeFunc\f[R] callback additionally gets the number of children for this node in the range from 2 to -\f[C]maxBranchingFactor\f[] (\f[C]childCount\f[] argument). +\f[C]maxBranchingFactor\f[R] (\f[C]childCount\f[R] argument). .PP -The \f[C]RTCSetNodeChildFunc\f[] callback function gets a pointer to the -node as input (\f[C]nodePtr\f[] argument), an array of pointers to the -children (\f[C]childPtrs\f[] argument), and the size of this array -(\f[C]childCount\f[] argument). +The \f[C]RTCSetNodeChildFunc\f[R] callback function gets a pointer to +the node as input (\f[C]nodePtr\f[R] argument), an array of pointers to +the children (\f[C]childPtrs\f[R] argument), and the size of this array +(\f[C]childCount\f[R] argument). .PP -The \f[C]RTCSetNodeBoundsFunc\f[] callback function gets a pointer to -the node as input (\f[C]nodePtr\f[] argument), an array of pointers to -the bounding boxes of the children (\f[C]bounds\f[] argument), and the -size of this array (\f[C]childCount\f[] argument). +The \f[C]RTCSetNodeBoundsFunc\f[R] callback function gets a pointer to +the node as input (\f[C]nodePtr\f[R] argument), an array of pointers to +the bounding boxes of the children (\f[C]bounds\f[R] argument), and the +size of this array (\f[C]childCount\f[R] argument). .PP -The \f[C]RTCCreateLeafFunc\f[] callback additionally gets an array of -primitives as input (\f[C]primitives\f[] argument), and the size of this -array (\f[C]primitiveCount\f[] argument). -The callback should read the \f[C]geomID\f[] and \f[C]primID\f[] members -from the passed primitives to construct the leaf. +The \f[C]RTCCreateLeafFunc\f[R] callback additionally gets an array of +primitives as input (\f[C]primitives\f[R] argument), and the size of +this array (\f[C]primitiveCount\f[R] argument). +The callback should read the \f[C]geomID\f[R] and \f[C]primID\f[R] +members from the passed primitives to construct the leaf. .PP -The \f[C]RTCSplitPrimitiveFunc\f[] callback is invoked in high quality -mode to split a primitive (\f[C]primitive\f[] argument) at the specified -position (\f[C]position\f[] argument) and dimension (\f[C]dimension\f[] -argument). +The \f[C]RTCSplitPrimitiveFunc\f[R] callback is invoked in high quality +mode to split a primitive (\f[C]primitive\f[R] argument) at the +specified position (\f[C]position\f[R] argument) and dimension +(\f[C]dimension\f[R] argument). The callback should return bounds of the clipped left and right parts of -the primitive (\f[C]leftBounds\f[] and \f[C]rightBounds\f[] arguments). +the primitive (\f[C]leftBounds\f[R] and \f[C]rightBounds\f[R] +arguments). .PP -The \f[C]RTCProgressMonitorFunction\f[] callback function is called with -the estimated completion rate \f[C]n\f[] in the range [0, 1]. -Returning \f[C]true\f[] from the callback lets the build continue; -returning \f[C]false\f[] cancels the build. +The \f[C]RTCProgressMonitorFunction\f[R] callback function is called +with the estimated completion rate \f[C]n\f[R] in the range +[0,\[u2006]1]. +Returning \f[C]true\f[R] from the callback lets the build continue; +returning \f[C]false\f[R] cancels the build. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewBVH] diff --git a/man/man3/rtcCollide.3embree3 b/man/man3/rtcCollide.3embree3 index 7bf8b42222..60d80fb1ec 100644 --- a/man/man3/rtcCollide.3embree3 +++ b/man/man3/rtcCollide.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcCollide" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,50 +6,50 @@ .IP .nf \f[C] -rtcCollide\ \-\ intersects\ one\ BVH\ with\ another -\f[] +rtcCollide \- intersects one BVH with another +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCCollision\ { -\ \ unsigned\ int\ geomID0,\ primID0; -\ \ unsigned\ int\ geomID1,\ primID1; +struct RTCCollision { + unsigned int geomID0, primID0; + unsigned int geomID1, primID1; }; -typedef\ void\ (*RTCCollideFunc)\ ( -\ \ void*\ userPtr, -\ \ RTCCollision*\ collisions, -\ \ size_t\ num_collisions); +typedef void (*RTCCollideFunc) ( + void* userPtr, + RTCCollision* collisions, + size_t num_collisions); -void\ rtcCollide\ ( -\ \ \ \ RTCScene\ hscene0,\ -\ \ \ \ RTCScene\ hscene1,\ -\ \ \ \ RTCCollideFunc\ callback,\ -\ \ \ \ void*\ userPtr +void rtcCollide ( + RTCScene hscene0, + RTCScene hscene1, + RTCCollideFunc callback, + void* userPtr ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcCollide\f[] function intersects the BVH of \f[C]hscene0\f[] -with the BVH of scene \f[C]hscene1\f[] and calls a user defined callback -function (e.g \f[C]callback\f[] argument) for each pair of intersecting -primitives between the two scenes. -A user defined data pointer (\f[C]userPtr\f[] argument) can also be +The \f[C]rtcCollide\f[R] function intersects the BVH of +\f[C]hscene0\f[R] with the BVH of scene \f[C]hscene1\f[R] and calls a +user defined callback function (e.g \f[C]callback\f[R] argument) for +each pair of intersecting primitives between the two scenes. +A user defined data pointer (\f[C]userPtr\f[R] argument) can also be passed in. .PP For every pair of primitives that may intersect each other, the callback -function (\f[C]callback\f[] argument) is called. -The user will be provided with the primID\[aq]s and geomID\[aq]s of +function (\f[C]callback\f[R] argument) is called. +The user will be provided with the primID\[cq]s and geomID\[cq]s of multiple potentially intersecting primitive pairs. Currently, only scene entirely composed of user geometries are supported, thus the user is expected to implement a primitive/primitive intersection to filter out false positives in the callback function. -The \f[C]userPtr\f[] argument can be used to input geometry data of the +The \f[C]userPtr\f[R] argument can be used to input geometry data of the scene or output results of the intersection query. .SS SUPPORTED PRIMITIVES .PP @@ -58,5 +58,5 @@ Currently, the only supported type is the user geometry type (see .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO diff --git a/man/man3/rtcCommitGeometry.3embree3 b/man/man3/rtcCommitGeometry.3embree3 index 7e6d3d1a2e..b92710d91b 100644 --- a/man/man3/rtcCommitGeometry.3embree3 +++ b/man/man3/rtcCommitGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcCommitGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcCommitGeometry\ \-\ commits\ geometry\ changes -\f[] +rtcCommitGeometry \- commits geometry changes +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcCommitGeometry(RTCGeometry\ geometry); -\f[] +void rtcCommitGeometry(RTCGeometry geometry); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcCommitGeometry\f[] function is used to commit all geometry -changes performed to a geometry (\f[C]geometry\f[] parameter). +The \f[C]rtcCommitGeometry\f[R] function is used to commit all geometry +changes performed to a geometry (\f[C]geometry\f[R] parameter). After a geometry gets modified, this function must be called to properly update the internal state of the geometry to perform interpolations -using \f[C]rtcInterpolate\f[] or to commit a scene containing the -geometry using \f[C]rtcCommitScene\f[]. +using \f[C]rtcInterpolate\f[R] or to commit a scene containing the +geometry using \f[C]rtcCommitScene\f[R]. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcInterpolate], [rtcCommitScene] diff --git a/man/man3/rtcCommitScene.3embree3 b/man/man3/rtcCommitScene.3embree3 index 5777c78915..f33dfabed4 100644 --- a/man/man3/rtcCommitScene.3embree3 +++ b/man/man3/rtcCommitScene.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcCommitScene" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,60 +6,60 @@ .IP .nf \f[C] -rtcCommitScene\ \-\ commits\ scene\ changes -\f[] +rtcCommitScene \- commits scene changes +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcCommitScene(RTCScene\ scene); -\f[] +void rtcCommitScene(RTCScene scene); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcCommitScene\f[] function commits all changes for the -specified scene (\f[C]scene\f[] argument). +The \f[C]rtcCommitScene\f[R] function commits all changes for the +specified scene (\f[C]scene\f[R] argument). This internally triggers building of a spatial acceleration structure for the scene using all available worker threads. Ray queries can be performed only after committing all scene changes. .PP If the application uses TBB 2019 Update 9 or later for parallelization of rendering, lazy scene construction during rendering is supported by -\f[C]rtcCommitScene\f[]. -Therefore \f[C]rtcCommitScene\f[] can get called from multiple TBB +\f[C]rtcCommitScene\f[R]. +Therefore \f[C]rtcCommitScene\f[R] can get called from multiple TBB worker threads concurrently for the same scene. -The \f[C]rtcCommitScene\f[] function will then internally isolate the +The \f[C]rtcCommitScene\f[R] function will then internally isolate the scene construction using a tbb::isolated_task_group. -The alternative approach of using \f[C]rtcJoinCommitScene\f[] which uses -an tbb:task_arena internally, is not recommended due to it\[aq]s high -runtime overhead. +The alternative approach of using \f[C]rtcJoinCommitScene\f[R] which +uses an tbb:task_arena internally, is not recommended due to it\[cq]s +high runtime overhead. .PP If scene geometries get modified or attached or detached, the -\f[C]rtcCommitScene\f[] call must be invoked before performing any +\f[C]rtcCommitScene\f[R] call must be invoked before performing any further ray queries for the scene; otherwise the effect of the ray query is undefined. The modification of a geometry, committing the scene, and tracing of rays must always happen sequentially, and never at the same time. Any API call that sets a property of the scene or geometries contained -in the scene count as scene modification, e.g. -including setting of intersection filter functions. +in the scene count as scene modification, e.g.\ including setting of +intersection filter functions. .PP The kind of acceleration structure built can be influenced using scene -flags (see \f[C]rtcSetSceneFlags\f[]), and the quality can be specified -using the \f[C]rtcSetSceneBuildQuality\f[] function. +flags (see \f[C]rtcSetSceneFlags\f[R]), and the quality can be specified +using the \f[C]rtcSetSceneBuildQuality\f[R] function. .PP Embree silently ignores primitives during spatial acceleration structure -construction that would cause numerical issues, e.g. -primitives containing NaNs, INFs, or values greater than 1.844E18f (as -no reasonable calculations can be performed with such values without +construction that would cause numerical issues, e.g.\ primitives +containing NaNs, INFs, or values greater than 1.844E18f (as no +reasonable calculations can be performed with such values without causing overflows). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcJoinCommitScene] diff --git a/man/man3/rtcDetachGeometry.3embree3 b/man/man3/rtcDetachGeometry.3embree3 index 8bd88b77ea..23b0c793e9 100644 --- a/man/man3/rtcDetachGeometry.3embree3 +++ b/man/man3/rtcDetachGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcDetachGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,22 +6,22 @@ .IP .nf \f[C] -rtcDetachGeometry\ \-\ detaches\ a\ geometry\ from\ the\ scene -\f[] +rtcDetachGeometry \- detaches a geometry from the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcDetachGeometry(RTCScene\ scene,\ unsigned\ int\ geomID); -\f[] +void rtcDetachGeometry(RTCScene scene, unsigned int geomID); +\f[R] .fi .SS DESCRIPTION .PP This function detaches a geometry identified by its geometry ID -(\f[C]geomID\f[] argument) from a scene (\f[C]scene\f[] argument). +(\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 @@ -29,7 +29,7 @@ geometries from a scene at the same time. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcAttachGeometry], [rtcAttachGeometryByID] diff --git a/man/man3/rtcDisableGeometry.3embree3 b/man/man3/rtcDisableGeometry.3embree3 index 7075a04087..852674e248 100644 --- a/man/man3/rtcDisableGeometry.3embree3 +++ b/man/man3/rtcDisableGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcDisableGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcDisableGeometry\ \-\ disables\ the\ geometry -\f[] +rtcDisableGeometry \- disables the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcDisableGeometry(RTCGeometry\ geometry); -\f[] +void rtcDisableGeometry(RTCGeometry geometry); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcDisableGeometry\f[] function disables the specified geometry -(\f[C]geometry\f[] argument). +The \f[C]rtcDisableGeometry\f[R] function disables the specified +geometry (\f[C]geometry\f[R] argument). A disabled geometry is not rendered. Each geometry is enabled by default at construction time. .PP After disabling a geometry, the scene containing that geometry must be -committed using \f[C]rtcCommitScene\f[] for the change to have effect. +committed using \f[C]rtcCommitScene\f[R] for the change to have effect. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcEnableGeometry], [rtcCommitScene] diff --git a/man/man3/rtcEnableGeometry.3embree3 b/man/man3/rtcEnableGeometry.3embree3 index 96aea925a0..3a1ebd271f 100644 --- a/man/man3/rtcEnableGeometry.3embree3 +++ b/man/man3/rtcEnableGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcEnableGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcEnableGeometry\ \-\ enables\ the\ geometry -\f[] +rtcEnableGeometry \- enables the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcEnableGeometry(RTCGeometry\ geometry); -\f[] +void rtcEnableGeometry(RTCGeometry geometry); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcEnableGeometry\f[] function enables the specified geometry -(\f[C]geometry\f[] argument). +The \f[C]rtcEnableGeometry\f[R] function enables the specified geometry +(\f[C]geometry\f[R] argument). Only enabled geometries are rendered. Each geometry is enabled by default at construction time. .PP After enabling a geometry, the scene containing that geometry must be -committed using \f[C]rtcCommitScene\f[] for the change to have effect. +committed using \f[C]rtcCommitScene\f[R] for the change to have effect. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcDisableGeometry], [rtcCommitScene] diff --git a/man/man3/rtcFilterIntersection.3embree3 b/man/man3/rtcFilterIntersection.3embree3 index 2edc08d43a..e741ea3395 100644 --- a/man/man3/rtcFilterIntersection.3embree3 +++ b/man/man3/rtcFilterIntersection.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcFilterIntersection" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,32 +6,32 @@ .IP .nf \f[C] -rtcFilterIntersection\ \-\ invokes\ the\ intersection\ filter\ function -\f[] +rtcFilterIntersection \- invokes the intersection filter function +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcFilterIntersection( -\ \ const\ struct\ RTCIntersectFunctionNArguments*\ args, -\ \ const\ struct\ RTCFilterFunctionNArguments*\ filterArgs +void rtcFilterIntersection( + const struct RTCIntersectFunctionNArguments* args, + const struct RTCFilterFunctionNArguments* filterArgs ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcFilterIntersection\f[] function can be called inside an -\f[C]RTCIntersectFunctionN\f[] callback function to invoke the +The \f[C]rtcFilterIntersection\f[R] function can be called inside an +\f[C]RTCIntersectFunctionN\f[R] callback function to invoke the intersection filter registered to the geometry and stored inside the context. -For this an \f[C]RTCFilterFunctionNArguments\f[] structure must be -created (see \f[C]rtcSetGeometryIntersectFilterFunction\f[]) which +For this an \f[C]RTCFilterFunctionNArguments\f[R] structure must be +created (see \f[C]rtcSetGeometryIntersectFilterFunction\f[R]) which basically consists of a valid mask, a hit packet to filter, the corresponding ray packet, and the packet size. -After the invocation of \f[C]rtcFilterIntersection\f[], only rays that +After the invocation of \f[C]rtcFilterIntersection\f[R], only rays that are still valid (valid mask set to \-1) should update a hit. .SS EXIT STATUS .PP diff --git a/man/man3/rtcFilterOcclusion.3embree3 b/man/man3/rtcFilterOcclusion.3embree3 index 5cc780df66..0d47d03bdc 100644 --- a/man/man3/rtcFilterOcclusion.3embree3 +++ b/man/man3/rtcFilterOcclusion.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcFilterOcclusion" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcFilterOcclusion\ \-\ invokes\ the\ occlusion\ filter\ function -\f[] +rtcFilterOcclusion \- invokes the occlusion filter function +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcFilterOcclusion( -\ \ const\ struct\ RTCOccludedFunctionNArguments*\ args, -\ \ const\ struct\ RTCFilterFunctionNArguments*\ filterArgs +void rtcFilterOcclusion( + const struct RTCOccludedFunctionNArguments* args, + const struct RTCFilterFunctionNArguments* filterArgs ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcFilterOcclusion\f[] function can be called inside an -\f[C]RTCOccludedFunctionN\f[] callback function to invoke the occlusion +The \f[C]rtcFilterOcclusion\f[R] function can be called inside an +\f[C]RTCOccludedFunctionN\f[R] callback function to invoke the occlusion filter registered to the geometry and stored inside the context. -For this an \f[C]RTCFilterFunctionNArguments\f[] structure must be -created (see \f[C]rtcSetGeometryIntersectFilterFunction\f[]) which +For this an \f[C]RTCFilterFunctionNArguments\f[R] structure must be +created (see \f[C]rtcSetGeometryIntersectFilterFunction\f[R]) which basically consists of a valid mask, a hit packet to filter, the corresponding ray packet, and the packet size. -After the invocation of \f[C]rtcFilterOcclusion\f[] only rays that are +After the invocation of \f[C]rtcFilterOcclusion\f[R] only rays that are still valid (valid mask set to \-1) should signal an occlusion. .SS EXIT STATUS .PP diff --git a/man/man3/rtcGetBufferData.3embree3 b/man/man3/rtcGetBufferData.3embree3 index 6c2d04986b..a87b8af407 100644 --- a/man/man3/rtcGetBufferData.3embree3 +++ b/man/man3/rtcGetBufferData.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetBufferData" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,26 +6,26 @@ .IP .nf \f[C] -rtcGetBufferData\ \-\ gets\ a\ pointer\ to\ the\ buffer\ data -\f[] +rtcGetBufferData \- gets a pointer to the buffer data +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void*\ rtcGetBufferData(RTCBuffer\ buffer); -\f[] +void* rtcGetBufferData(RTCBuffer buffer); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetBufferData\f[] function returns a pointer to the buffer -data of the specified buffer object (\f[C]buffer\f[] argument). +The \f[C]rtcGetBufferData\f[R] function returns a pointer to the buffer +data of the specified buffer object (\f[C]buffer\f[R] argument). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewBuffer] diff --git a/man/man3/rtcGetDeviceError.3embree3 b/man/man3/rtcGetDeviceError.3embree3 index 13304c8130..0f0f9aad4e 100644 --- a/man/man3/rtcGetDeviceError.3embree3 +++ b/man/man3/rtcGetDeviceError.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetDeviceError" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,54 +6,54 @@ .IP .nf \f[C] -rtcGetDeviceError\ \-\ returns\ the\ error\ code\ of\ the\ device -\f[] +rtcGetDeviceError \- returns the error code of the device +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCError\ rtcGetDeviceError(RTCDevice\ device); -\f[] +RTCError rtcGetDeviceError(RTCDevice device); +\f[R] .fi .SS DESCRIPTION .PP Each thread has its own error code per device. If an error occurs when calling an API function, this error code is set to the occurred error if it stores no previous error. -The \f[C]rtcGetDeviceError\f[] function reads and returns the currently +The \f[C]rtcGetDeviceError\f[R] function reads and returns the currently stored error and clears the error code. This assures that the returned error code is always the first error -occurred since the last invocation of \f[C]rtcGetDeviceError\f[]. +occurred since the last invocation of \f[C]rtcGetDeviceError\f[R]. .PP -Possible error codes returned by \f[C]rtcGetDeviceError\f[] are: +Possible error codes returned by \f[C]rtcGetDeviceError\f[R] are: .IP \[bu] 2 -\f[C]RTC_ERROR_NONE\f[]: No error occurred. +\f[C]RTC_ERROR_NONE\f[R]: No error occurred. .IP \[bu] 2 -\f[C]RTC_ERROR_UNKNOWN\f[]: An unknown error has occurred. +\f[C]RTC_ERROR_UNKNOWN\f[R]: An unknown error has occurred. .IP \[bu] 2 -\f[C]RTC_ERROR_INVALID_ARGUMENT\f[]: An invalid argument was specified. +\f[C]RTC_ERROR_INVALID_ARGUMENT\f[R]: An invalid argument was specified. .IP \[bu] 2 -\f[C]RTC_ERROR_INVALID_OPERATION\f[]: The operation is not allowed for +\f[C]RTC_ERROR_INVALID_OPERATION\f[R]: The operation is not allowed for the specified object. .IP \[bu] 2 -\f[C]RTC_ERROR_OUT_OF_MEMORY\f[]: There is not enough memory left to +\f[C]RTC_ERROR_OUT_OF_MEMORY\f[R]: There is not enough memory left to complete the operation. .IP \[bu] 2 -\f[C]RTC_ERROR_UNSUPPORTED_CPU\f[]: The CPU is not supported as it does +\f[C]RTC_ERROR_UNSUPPORTED_CPU\f[R]: The CPU is not supported as it does not support the lowest ISA Embree is compiled for. .IP \[bu] 2 -\f[C]RTC_ERROR_CANCELLED\f[]: The operation got canceled by a memory +\f[C]RTC_ERROR_CANCELLED\f[R]: The operation got canceled by a memory monitor callback or progress monitor callback function. .PP -When the device construction fails, \f[C]rtcNewDevice\f[] returns -\f[C]NULL\f[] as device. +When the device construction fails, \f[C]rtcNewDevice\f[R] returns +\f[C]NULL\f[R] as device. To detect the error code of a such a failed device construction, pass -\f[C]NULL\f[] as device to the \f[C]rtcGetDeviceError\f[] function. -For all other invocations of \f[C]rtcGetDeviceError\f[], a proper device -pointer must be specified. +\f[C]NULL\f[R] as device to the \f[C]rtcGetDeviceError\f[R] function. +For all other invocations of \f[C]rtcGetDeviceError\f[R], a proper +device pointer must be specified. .SS EXIT STATUS .PP Returns the error code for the device. diff --git a/man/man3/rtcGetDeviceProperty.3embree3 b/man/man3/rtcGetDeviceProperty.3embree3 index 4fdd74f9c7..e5264eb90c 100644 --- a/man/man3/rtcGetDeviceProperty.3embree3 +++ b/man/man3/rtcGetDeviceProperty.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetDeviceProperty" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,124 +6,123 @@ .IP .nf \f[C] -rtcGetDeviceProperty\ \-\ queries\ properties\ of\ the\ device -\f[] +rtcGetDeviceProperty \- queries properties of the device +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -ssize_t\ rtcGetDeviceProperty( -\ \ RTCDevice\ device, -\ \ enum\ RTCDeviceProperty\ prop +ssize_t rtcGetDeviceProperty( + RTCDevice device, + enum RTCDeviceProperty prop ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetDeviceProperty\f[] function can be used to query -properties (\f[C]prop\f[] argument) of a device object (\f[C]device\f[] -argument). -The returned property is an integer of type \f[C]ssize_t\f[]. +The \f[C]rtcGetDeviceProperty\f[R] function can be used to query +properties (\f[C]prop\f[R] argument) of a device object +(\f[C]device\f[R] argument). +The returned property is an integer of type \f[C]ssize_t\f[R]. .PP Possible properties to query are: .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_VERSION\f[]: Queries the combined version +\f[C]RTC_DEVICE_PROPERTY_VERSION\f[R]: Queries the combined version number (MAJOR.MINOR.PATCH) with two decimal digits per component. E.g. for Embree 2.8.3 the integer 208003 is returned. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_VERSION_MAJOR\f[]: Queries the major version +\f[C]RTC_DEVICE_PROPERTY_VERSION_MAJOR\f[R]: Queries the major version number of Embree. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_VERSION_MINOR\f[]: Queries the minor version +\f[C]RTC_DEVICE_PROPERTY_VERSION_MINOR\f[R]: Queries the minor version number of Embree. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_VERSION_PATCH\f[]: Queries the patch version +\f[C]RTC_DEVICE_PROPERTY_VERSION_PATCH\f[R]: Queries the patch version number of Embree. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[]: Queries whether the -\f[C]rtcIntersect4\f[] and \f[C]rtcOccluded4\f[] functions preserve +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[R]: Queries whether the +\f[C]rtcIntersect4\f[R] and \f[C]rtcOccluded4\f[R] functions preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with -\f[C]EMBREE_RAY_PACKETS\f[] and \f[C]SSE2\f[] (or \f[C]SSE4.2\f[]) -enabled, and if the machine it is running on supports \f[C]SSE2\f[] (or -\f[C]SSE4.2\f[]). +\f[C]EMBREE_RAY_PACKETS\f[R] and \f[C]SSE2\f[R] (or \f[C]SSE4.2\f[R]) +enabled, and if the machine it is running on supports \f[C]SSE2\f[R] (or +\f[C]SSE4.2\f[R]). .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[]: Queries whether the -\f[C]rtcIntersect8\f[] and \f[C]rtcOccluded8\f[] functions preserve +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[R]: Queries whether the +\f[C]rtcIntersect8\f[R] and \f[C]rtcOccluded8\f[R] functions preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with -\f[C]EMBREE_RAY_PACKETS\f[] and \f[C]AVX\f[] (or \f[C]AVX2\f[]) enabled, -and if the machine it is running on supports \f[C]AVX\f[] (or -\f[C]AVX2\f[]). +\f[C]EMBREE_RAY_PACKETS\f[R] and \f[C]AVX\f[R] (or \f[C]AVX2\f[R]) +enabled, and if the machine it is running on supports \f[C]AVX\f[R] (or +\f[C]AVX2\f[R]). .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[]: Queries whether the -\f[C]rtcIntersect16\f[] and \f[C]rtcOccluded16\f[] functions preserve -packet size and ray order when invoking callback functions. +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[R]: Queries whether +the \f[C]rtcIntersect16\f[R] and \f[C]rtcOccluded16\f[R] functions +preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with -\f[C]EMBREE_RAY_PACKETS\f[] and \f[C]AVX512SKX\f[] (or -\f[C]AVX512KNL\f[]) enabled, and if the machine it is running on -supports \f[C]AVX512SKX\f[] (or \f[C]AVX512KNL\f[]). -.IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED\f[]: Queries whether -\f[C]rtcIntersect1M\f[], \f[C]rtcIntersect1Mp\f[], -\f[C]rtcIntersectNM\f[], \f[C]rtcIntersectNp\f[], -\f[C]rtcOccluded1M\f[], \f[C]rtcOccluded1Mp\f[], \f[C]rtcOccludedNM\f[], -and \f[C]rtcOccludedNp\f[] are supported. +\f[C]EMBREE_RAY_PACKETS\f[R] and \f[C]AVX512\f[R] enabled, and if the +machine it is running on supports \f[C]AVX512\f[R]. +.IP \[bu] 2 +\f[C]RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED\f[R]: Queries whether +\f[C]rtcIntersect1M\f[R], \f[C]rtcIntersect1Mp\f[R], +\f[C]rtcIntersectNM\f[R], \f[C]rtcIntersectNp\f[R], +\f[C]rtcOccluded1M\f[R], \f[C]rtcOccluded1Mp\f[R], +\f[C]rtcOccludedNM\f[R], and \f[C]rtcOccludedNp\f[R] are supported. This is only the case if Embree is compiled with -\f[C]EMBREE_RAY_PACKETS\f[] enabled. +\f[C]EMBREE_RAY_PACKETS\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED\f[]: Queries whether ray +\f[C]RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED\f[R]: Queries whether ray masks are supported. This is only the case if Embree is compiled with -\f[C]EMBREE_RAY_MASK\f[] enabled. +\f[C]EMBREE_RAY_MASK\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED\f[R]: Queries whether back face culling is enabled. This is only the case if Embree is compiled with -\f[C]EMBREE_BACKFACE_CULLING\f[] enabled. +\f[C]EMBREE_BACKFACE_CULLING\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED\f[R]: Queries whether compact polys is enabled. This is only the case if Embree is compiled with -\f[C]EMBREE_COMPACT_POLYS\f[] enabled. +\f[C]EMBREE_COMPACT_POLYS\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED\f[R]: Queries whether filter functions are supported, which is the case if Embree is compiled -with \f[C]EMBREE_FILTER_FUNCTION\f[] enabled. +with \f[C]EMBREE_FILTER_FUNCTION\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED\f[]: Queries +\f[C]RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED\f[R]: Queries whether invalid rays are ignored, which is the case if Embree is -compiled with \f[C]EMBREE_IGNORE_INVALID_RAYS\f[] enabled. +compiled with \f[C]EMBREE_IGNORE_INVALID_RAYS\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED\f[]: Queries +\f[C]RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED\f[R]: Queries whether triangles are supported, which is the case if Embree is compiled -with \f[C]EMBREE_GEOMETRY_TRIANGLE\f[] enabled. +with \f[C]EMBREE_GEOMETRY_TRIANGLE\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED\f[R]: Queries whether quads are supported, which is the case if Embree is compiled with -\f[C]EMBREE_GEOMETRY_QUAD\f[] enabled. +\f[C]EMBREE_GEOMETRY_QUAD\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED\f[]: Queries +\f[C]RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED\f[R]: Queries whether subdivision meshes are supported, which is the case if Embree is -compiled with \f[C]EMBREE_GEOMETRY_SUBDIVISION\f[] enabled. +compiled with \f[C]EMBREE_GEOMETRY_SUBDIVISION\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED\f[R]: Queries whether curves are supported, which is the case if Embree is compiled with -\f[C]EMBREE_GEOMETRY_CURVE\f[] enabled. +\f[C]EMBREE_GEOMETRY_CURVE\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED\f[R]: Queries whether points are supported, which is the case if Embree is compiled with -\f[C]EMBREE_GEOMETRY_POINT\f[] enabled. +\f[C]EMBREE_GEOMETRY_POINT\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED\f[]: Queries whether +\f[C]RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED\f[R]: Queries whether user geometries are supported, which is the case if Embree is compiled -with \f[C]EMBREE_GEOMETRY_USER\f[] enabled. +with \f[C]EMBREE_GEOMETRY_USER\f[R] enabled. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_TASKING_SYSTEM\f[]: Queries the tasking system +\f[C]RTC_DEVICE_PROPERTY_TASKING_SYSTEM\f[R]: Queries the tasking system Embree is compiled with. Possible return values are: .RS 2 @@ -135,20 +134,20 @@ Intel Threading Building Blocks (TBB) Parallel Patterns Library (PPL) .RE .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_COMMIT_JOIN_SUPPORTED\f[]: Queries whether -\f[C]rtcJoinCommitScene\f[] is supported. +\f[C]RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED\f[R]: Queries whether +\f[C]rtcJoinCommitScene\f[R] is supported. This is not the case when Embree is compiled with PPL or older versions of TBB. .IP \[bu] 2 -\f[C]RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED\f[]: Queries whether -\f[C]rtcCommitScene\f[] can get invoked from multiple TBB worker threads -concurrently. +\f[C]RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED\f[R]: Queries whether +\f[C]rtcCommitScene\f[R] can get invoked from multiple TBB worker +threads concurrently. This feature is only supported starting with TBB 2019 Update 9. .SS EXIT STATUS .PP On success returns the value of the queried property. For properties returning a boolean value, the return value 0 denotes -\f[C]false\f[] and 1 denotes \f[C]true\f[]. +\f[C]false\f[R] and 1 denotes \f[C]true\f[R]. .PP On failure zero is returned and an error code is set that can be queried -using \f[C]rtcGetDeviceError\f[]. +using \f[C]rtcGetDeviceError\f[R]. diff --git a/man/man3/rtcGetGeometry.3embree3 b/man/man3/rtcGetGeometry.3embree3 index 08db391938..c310fd64ef 100644 --- a/man/man3/rtcGetGeometry.3embree3 +++ b/man/man3/rtcGetGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,36 +6,40 @@ .IP .nf \f[C] -rtcGetGeometry\ \-\ returns\ the\ geometry\ bound\ to -\ \ the\ specified\ geometry\ ID -\f[] +rtcGetGeometry \- returns the geometry bound to + the specified geometry ID +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCGeometry\ rtcGetGeometry(RTCScene\ scene,\ unsigned\ int\ geomID); -\f[] +RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometry\f[] function returns the geometry that is bound -to the specified geometry ID (\f[C]geomID\f[] argument) for the -specified scene (\f[C]scene\f[] argument). -This function just looks up the handle and does \f[I]not\f[] increment +The \f[C]rtcGetGeometry\f[R] function returns the geometry that is bound +to the specified geometry ID (\f[C]geomID\f[R] argument) for the +specified scene (\f[C]scene\f[R] argument). +This function just looks up the handle and does \f[I]not\f[R] increment the reference count. If you want to get ownership of the handle, you need to additionally -call \f[C]rtcRetainGeometry\f[]. -For this reason, this function is fast and can be used during rendering. +call \f[C]rtcRetainGeometry\f[R]. +.PP +This function is not thread safe and thus can be used during rendering. However, it is generally recommended to store the geometry handle inside -the application\[aq]s geometry representation and look up the geometry +the application\[cq]s geometry representation and look up the geometry handle from that representation directly. +.PP +If you need a thread safe version of this function please use +[rtcGetGeometryThreadSafe]. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP -[rtcAttachGeometry], [rtcAttachGeometryByID] +[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometryThreadSafe] diff --git a/man/man3/rtcGetGeometryBufferData.3embree3 b/man/man3/rtcGetGeometryBufferData.3embree3 index 2c23105956..fa11fd237d 100644 --- a/man/man3/rtcGetGeometryBufferData.3embree3 +++ b/man/man3/rtcGetGeometryBufferData.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryBufferData" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,33 +6,33 @@ .IP .nf \f[C] -rtcGetGeometryBufferData\ \-\ gets\ pointer\ to -\ \ the\ first\ buffer\ view\ element -\f[] +rtcGetGeometryBufferData \- gets pointer to + the first buffer view element +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void*\ rtcGetGeometryBufferData( -\ \ RTCGeometry\ geometry, -\ \ enum\ RTCBufferType\ type, -\ \ unsigned\ int\ slot +void* rtcGetGeometryBufferData( + RTCGeometry geometry, + enum RTCBufferType type, + unsigned int slot ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryBufferData\f[] function returns a pointer to the +The \f[C]rtcGetGeometryBufferData\f[R] function returns a pointer to the first element of the buffer view attached to the specified buffer type -and slot (\f[C]type\f[] and \f[C]slot\f[] argument) of the geometry -(\f[C]geometry\f[] argument). +and slot (\f[C]type\f[R] and \f[C]slot\f[R] argument) of the geometry +(\f[C]geometry\f[R] argument). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], diff --git a/man/man3/rtcGetGeometryFace.3embree3 b/man/man3/rtcGetGeometryFace.3embree3 index c1f21f715e..1370705168 100644 --- a/man/man3/rtcGetGeometryFace.3embree3 +++ b/man/man3/rtcGetGeometryFace.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryFace" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcGetGeometryFace\ \-\ returns\ the\ face\ of\ some\ half\ edge -\f[] +rtcGetGeometryFace \- returns the face of some half edge +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -unsigned\ int\ rtcGetGeometryFace( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ edgeID +unsigned int rtcGetGeometryFace( + RTCGeometry geometry, + unsigned int edgeID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryFace\f[] function returns the ID of the face the -specified half edge (\f[C]edgeID\f[] argument) belongs to. -For instance in the following example the face \f[C]f1\f[] is returned -for edges \f[C]e4\f[], \f[C]e5\f[], \f[C]e6\f[], and \f[C]e7\f[]. +The \f[C]rtcGetGeometryFace\f[R] function returns the ID of the face the +specified half edge (\f[C]edgeID\f[R] argument) belongs to. +For instance in the following example the face \f[C]f1\f[R] is returned +for edges \f[C]e4\f[R], \f[C]e5\f[R], \f[C]e6\f[R], and \f[C]e7\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .PP This function can only be used for subdivision geometries. @@ -39,7 +39,7 @@ the function does not depend on the topology ID. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace], diff --git a/man/man3/rtcGetGeometryFirstHalfEdge.3embree3 b/man/man3/rtcGetGeometryFirstHalfEdge.3embree3 index 3e461fb0a3..8574d59d46 100644 --- a/man/man3/rtcGetGeometryFirstHalfEdge.3embree3 +++ b/man/man3/rtcGetGeometryFirstHalfEdge.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryFirstHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,32 +6,32 @@ .IP .nf \f[C] -rtcGetGeometryFirstHalfEdge\ \-\ returns\ the\ first\ half\ edge\ of\ a\ face -\f[] +rtcGetGeometryFirstHalfEdge \- returns the first half edge of a face +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -unsigned\ int\ rtcGetGeometryFirstHalfEdge( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ faceID +unsigned int rtcGetGeometryFirstHalfEdge( + RTCGeometry geometry, + unsigned int faceID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryFirstHalfEdge\f[] function returns the ID of the -first half edge belonging to the specified face (\f[C]faceID\f[] +The \f[C]rtcGetGeometryFirstHalfEdge\f[R] function returns the ID of the +first half edge belonging to the specified face (\f[C]faceID\f[R] argument). For instance in the following example the first half edge of face -\f[C]f1\f[] is \f[C]e4\f[]. +\f[C]f1\f[R] is \f[C]e4\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .PP This function can only be used for subdivision geometries. @@ -48,7 +48,7 @@ first edge is edge e4, the next edge e5, etc. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace], diff --git a/man/man3/rtcGetGeometryNextHalfEdge.3embree3 b/man/man3/rtcGetGeometryNextHalfEdge.3embree3 index 5fa4528c50..d1f4f2739d 100644 --- a/man/man3/rtcGetGeometryNextHalfEdge.3embree3 +++ b/man/man3/rtcGetGeometryNextHalfEdge.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryNextHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcGetGeometryNextHalfEdge\ \-\ returns\ the\ next\ half\ edge -\f[] +rtcGetGeometryNextHalfEdge \- returns the next half edge +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -unsigned\ int\ rtcGetGeometryNextHalfEdge( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ edgeID +unsigned int rtcGetGeometryNextHalfEdge( + RTCGeometry geometry, + unsigned int edgeID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryNextHalfEdge\f[] function returns the ID of the -next half edge of the specified half edge (\f[C]edgeID\f[] argument). -For instance in the following example the next half edge of \f[C]e10\f[] -is \f[C]e11\f[]. +The \f[C]rtcGetGeometryNextHalfEdge\f[R] function returns the ID of the +next half edge of the specified half edge (\f[C]edgeID\f[R] argument). +For instance in the following example the next half edge of +\f[C]e10\f[R] is \f[C]e11\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .PP This function can only be used for subdivision geometries. @@ -39,7 +39,7 @@ the function does not depend on the topology ID. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace], diff --git a/man/man3/rtcGetGeometryOppositeHalfEdge.3embree3 b/man/man3/rtcGetGeometryOppositeHalfEdge.3embree3 index b8b6efc8bd..2e36501b1e 100644 --- a/man/man3/rtcGetGeometryOppositeHalfEdge.3embree3 +++ b/man/man3/rtcGetGeometryOppositeHalfEdge.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryOppositeHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,38 +6,38 @@ .IP .nf \f[C] -rtcGetGeometryOppositeHalfEdge\ \-\ returns\ the\ opposite\ half\ edge -\f[] +rtcGetGeometryOppositeHalfEdge \- returns the opposite half edge +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -unsigned\ int\ rtcGetGeometryOppositeHalfEdge( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ topologyID, -\ \ unsigned\ int\ edgeID +unsigned int rtcGetGeometryOppositeHalfEdge( + RTCGeometry geometry, + unsigned int topologyID, + unsigned int edgeID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryOppositeHalfEdge\f[] function returns the ID of -the opposite half edge of the specified half edge (\f[C]edgeID\f[] -argument) in the specified topology (\f[C]topologyID\f[] argument). +The \f[C]rtcGetGeometryOppositeHalfEdge\f[R] function returns the ID of +the opposite half edge of the specified half edge (\f[C]edgeID\f[R] +argument) in the specified topology (\f[C]topologyID\f[R] argument). For instance in the following example the opposite half edge of -\f[C]e6\f[] is \f[C]e16\f[]. +\f[C]e6\f[R] is \f[C]e16\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .PP An opposite half edge does not exist if the specified half edge has either no neighboring face, or more than 2 neighboring faces. -In these cases the function just returns the same edge \f[C]edgeID\f[] +In these cases the function just returns the same edge \f[C]edgeID\f[R] again. .PP This function can only be used for subdivision geometries. @@ -46,7 +46,7 @@ geometry have different index buffers assigned. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace], diff --git a/man/man3/rtcGetGeometryPreviousHalfEdge.3embree3 b/man/man3/rtcGetGeometryPreviousHalfEdge.3embree3 index 2fb5deb2ff..c62526e375 100644 --- a/man/man3/rtcGetGeometryPreviousHalfEdge.3embree3 +++ b/man/man3/rtcGetGeometryPreviousHalfEdge.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryPreviousHalfEdge" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,32 +6,32 @@ .IP .nf \f[C] -rtcGetGeometryPreviousHalfEdge\ \-\ returns\ the\ previous\ half\ edge -\f[] +rtcGetGeometryPreviousHalfEdge \- returns the previous half edge +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -unsigned\ int\ rtcGetGeometryPreviousHalfEdge( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ edgeID +unsigned int rtcGetGeometryPreviousHalfEdge( + RTCGeometry geometry, + unsigned int edgeID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryPreviousHalfEdge\f[] function returns the ID of -the previous half edge of the specified half edge (\f[C]edgeID\f[] +The \f[C]rtcGetGeometryPreviousHalfEdge\f[R] function returns the ID of +the previous half edge of the specified half edge (\f[C]edgeID\f[R] argument). For instance in the following example the previous half edge of -\f[C]e6\f[] is \f[C]e5\f[]. +\f[C]e6\f[R] is \f[C]e5\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .PP This function can only be used for subdivision geometries. @@ -40,7 +40,7 @@ the function does not depend on the topology ID. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetGeometryFirstHalfEdge], [rtcGetGeometryFace], diff --git a/man/man3/rtcGetGeometryThreadSafe.3embree3 b/man/man3/rtcGetGeometryThreadSafe.3embree3 new file mode 100644 index 0000000000..4e2854058d --- /dev/null +++ b/man/man3/rtcGetGeometryThreadSafe.3embree3 @@ -0,0 +1,41 @@ +.\" Automatically generated by Pandoc 2.5 +.\" +.TH "rtcGetGeometryThreadSafe" "3" "" "" "Embree Ray Tracing Kernels 3" +.hy +.SS NAME +.IP +.nf +\f[C] +rtcGetGeometryThreadSafe \- returns the geometry bound to + the specified geometry ID +\f[R] +.fi +.SS SYNOPSIS +.IP +.nf +\f[C] +#include + +RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID); +\f[R] +.fi +.SS DESCRIPTION +.PP +The \f[C]rtcGetGeometryThreadSafe\f[R] function returns the geometry +that is bound to the specified geometry ID (\f[C]geomID\f[R] argument) +for the specified scene (\f[C]scene\f[R] argument). +This function just looks up the handle and does \f[I]not\f[R] increment +the reference count. +If you want to get ownership of the handle, you need to additionally +call \f[C]rtcRetainGeometry\f[R]. +.PP +This function is thread safe and should NOT get used during rendering. +If you need a fast non\-thread safe version during rendering please use +the [rtcGetGeometry] function. +.SS EXIT STATUS +.PP +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. +.SS SEE ALSO +.PP +[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometry] diff --git a/man/man3/rtcGetGeometryTransform.3embree3 b/man/man3/rtcGetGeometryTransform.3embree3 index 870e16b400..6603d613a9 100644 --- a/man/man3/rtcGetGeometryTransform.3embree3 +++ b/man/man3/rtcGetGeometryTransform.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryTransform" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,47 +6,47 @@ .IP .nf \f[C] -rtcGetGeometryTransform\ \-\ returns\ the\ interpolated\ instance -\ \ transformation\ for\ the\ specified\ time -\f[] +rtcGetGeometryTransform \- returns the interpolated instance + transformation for the specified time +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcGetGeometryTransform( -\ \ RTCGeometry\ geometry, -\ \ float\ time, -\ \ enum\ RTCFormat\ format, -\ \ void*\ xfm +void rtcGetGeometryTransform( + RTCGeometry geometry, + float time, + enum RTCFormat format, + void* xfm ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryTransform\f[] function returns the interpolated -local to world transformation (\f[C]xfm\f[] parameter) of an instance -geometry (\f[C]geometry\f[] parameter) for a particular time -(\f[C]time\f[] parameter in range [0, 1]) in the specified format -(\f[C]format\f[] parameter). +The \f[C]rtcGetGeometryTransform\f[R] function returns the interpolated +local to world transformation (\f[C]xfm\f[R] parameter) of an instance +geometry (\f[C]geometry\f[R] parameter) for a particular time +(\f[C]time\f[R] parameter in range [0,\[u2006]1]) in the specified +format (\f[C]format\f[R] parameter). .PP Possible formats for the returned matrix are: .IP \[bu] 2 -\f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[]: The 3×4 float matrix is laid out -in row\-major form. +\f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[R]: The 3\[tmu]4 float matrix is +laid out in row\-major form. .IP \[bu] 2 -\f[C]RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR\f[]: The 3×4 float matrix is laid -out in column\-major form. +\f[C]RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR\f[R]: The 3\[tmu]4 float matrix is +laid out in column\-major form. .IP \[bu] 2 -\f[C]RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR\f[]: The 3×4 float matrix is laid -out in column\-major form as a 4×4 homogeneous matrix with last row -equal to (0, 0, 0, 1). +\f[C]RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR\f[R]: The 3\[tmu]4 float matrix is +laid out in column\-major form as a 4\[tmu]4 homogeneous matrix with +last row equal to (0, 0, 0, 1). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_INSTANCE], [rtcSetGeometryTransform] diff --git a/man/man3/rtcGetGeometryUserData.3embree3 b/man/man3/rtcGetGeometryUserData.3embree3 index 5f01ef8cab..a705412b53 100644 --- a/man/man3/rtcGetGeometryUserData.3embree3 +++ b/man/man3/rtcGetGeometryUserData.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetGeometryUserData" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,29 +6,29 @@ .IP .nf \f[C] -rtcGetGeometryUserData\ \-\ returns\ the\ user\ data\ pointer -\ \ of\ the\ geometry -\f[] +rtcGetGeometryUserData \- returns the user data pointer + of the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void*\ rtcGetGeometryUserData(RTCGeometry\ geometry); -\f[] +void* rtcGetGeometryUserData(RTCGeometry geometry); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetGeometryUserData\f[] function queries the user data -pointer previously set with \f[C]rtcSetGeometryUserData\f[]. -When \f[C]rtcSetGeometryUserData\f[] was not called yet, \f[C]NULL\f[] +The \f[C]rtcGetGeometryUserData\f[R] function queries the user data +pointer previously set with \f[C]rtcSetGeometryUserData\f[R]. +When \f[C]rtcSetGeometryUserData\f[R] was not called yet, \f[C]NULL\f[R] is returned. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryUserData] diff --git a/man/man3/rtcGetSceneBounds.3embree3 b/man/man3/rtcGetSceneBounds.3embree3 index edd78d680a..cf006e4643 100644 --- a/man/man3/rtcGetSceneBounds.3embree3 +++ b/man/man3/rtcGetSceneBounds.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetSceneBounds" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,35 +6,35 @@ .IP .nf \f[C] -rtcGetSceneBounds\ \-\ returns\ the\ axis\-aligned\ bounding\ box\ of\ the\ scene -\f[] +rtcGetSceneBounds \- returns the axis\-aligned bounding box of the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCORE_ALIGN(16)\ RTCBounds +struct RTCORE_ALIGN(16) RTCBounds { -\ \ float\ lower_x,\ lower_y,\ lower_z,\ align0; -\ \ float\ upper_x,\ upper_y,\ upper_z,\ align1; + float lower_x, lower_y, lower_z, align0; + float upper_x, upper_y, upper_z, align1; }; -void\ rtcGetSceneBounds( -\ \ RTCScene\ scene, -\ \ struct\ RTCBounds*\ bounds_o +void rtcGetSceneBounds( + RTCScene scene, + struct RTCBounds* bounds_o ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetSceneBounds\f[] function queries the axis\-aligned -bounding box of the specified scene (\f[C]scene\f[] argument) and stores -that bounding box to the provided destination pointer (\f[C]bounds_o\f[] -argument). +The \f[C]rtcGetSceneBounds\f[R] function queries the axis\-aligned +bounding box of the specified scene (\f[C]scene\f[R] argument) and +stores that bounding box to the provided destination pointer +(\f[C]bounds_o\f[R] argument). The stored bounding box consists of lower and upper bounds for the x, y, -and z dimensions as specified by the \f[C]RTCBounds\f[] structure. +and z dimensions as specified by the \f[C]RTCBounds\f[R] structure. .PP The provided destination pointer must be aligned to 16 bytes. The function may be invoked only after committing the scene; otherwise @@ -42,7 +42,7 @@ the result is undefined. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetSceneLinearBounds], [rtcCommitScene], [rtcJoinCommitScene] diff --git a/man/man3/rtcGetSceneDevice.3embree3 b/man/man3/rtcGetSceneDevice.3embree3 index 42c5bf9a1a..156601d904 100644 --- a/man/man3/rtcGetSceneDevice.3embree3 +++ b/man/man3/rtcGetSceneDevice.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetSceneDevice" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,28 +6,28 @@ .IP .nf \f[C] -rtcGetSceneDevice\ \-\ returns\ the\ device\ the\ scene\ got\ created\ in -\f[] +rtcGetSceneDevice \- returns the device the scene got created in +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCDevice\ rtcGetSceneDevice(RTCScene\ scene); -\f[] +RTCDevice rtcGetSceneDevice(RTCScene scene); +\f[R] .fi .SS DESCRIPTION .PP This function returns the device object the scene got created in. The returned handle own one additional reference to the device object, -thus you should need to call \f[C]rtcReleaseDevice\f[] when the returned -handle is no longer required. +thus you should need to call \f[C]rtcReleaseDevice\f[R] when the +returned handle is no longer required. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcReleaseDevice] diff --git a/man/man3/rtcGetSceneFlags.3embree3 b/man/man3/rtcGetSceneFlags.3embree3 index e207af4abe..9f7aa8ae9e 100644 --- a/man/man3/rtcGetSceneFlags.3embree3 +++ b/man/man3/rtcGetSceneFlags.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetSceneFlags" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,35 +6,34 @@ .IP .nf \f[C] -rtcGetSceneFlags\ \-\ returns\ the\ flags\ of\ the\ scene -\f[] +rtcGetSceneFlags \- returns the flags of the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -enum\ RTCSceneFlags\ rtcGetSceneFlags(RTCScene\ scene); -\f[] +enum RTCSceneFlags rtcGetSceneFlags(RTCScene scene); +\f[R] .fi .SS DESCRIPTION .PP Queries the flags of a scene. -This function can be useful when setting individual flags, e.g. -to just set the robust mode without changing other flags the following -way: +This function can be useful when setting individual flags, e.g.\ to just +set the robust mode without changing other flags the following way: .IP .nf \f[C] -RTCSceneFlags\ flags\ =\ rtcGetSceneFlags(scene); -rtcSetSceneFlags(scene,\ RTC_SCENE_FLAG_ROBUST\ |\ flags); -\f[] +RTCSceneFlags flags = rtcGetSceneFlags(scene); +rtcSetSceneFlags(scene, RTC_SCENE_FLAG_ROBUST | flags); +\f[R] .fi .SS EXIT STATUS .PP -On failure \f[C]RTC_SCENE_FLAG_NONE\f[] is returned and an error code is -set that can be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]RTC_SCENE_FLAG_NONE\f[R] is returned and an error code +is set that can be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetSceneFlags] diff --git a/man/man3/rtcGetSceneLinearBounds.3embree3 b/man/man3/rtcGetSceneLinearBounds.3embree3 index 2a78ab0200..e46084be68 100644 --- a/man/man3/rtcGetSceneLinearBounds.3embree3 +++ b/man/man3/rtcGetSceneLinearBounds.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcGetSceneLinearBounds" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,37 +6,37 @@ .IP .nf \f[C] -rtcGetSceneLinearBounds\ \-\ returns\ the\ linear\ bounds\ of\ the\ scene -\f[] +rtcGetSceneLinearBounds \- returns the linear bounds of the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCORE_ALIGN(16)\ RTCLinearBounds +struct RTCORE_ALIGN(16) RTCLinearBounds { -\ \ RTCBounds\ bounds0; -\ \ RTCBounds\ bounds1; + RTCBounds bounds0; + RTCBounds bounds1; }; -void\ rtcGetSceneLinearBounds( -\ \ RTCScene\ scene, -\ \ struct\ RTCLinearBounds*\ bounds_o +void rtcGetSceneLinearBounds( + RTCScene scene, + struct RTCLinearBounds* bounds_o ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcGetSceneLinearBounds\f[] function queries the linear bounds -of the specified scene (\f[C]scene\f[] argument) and stores them to the -provided destination pointer (\f[C]bounds_o\f[] argument). +The \f[C]rtcGetSceneLinearBounds\f[R] function queries the linear bounds +of the specified scene (\f[C]scene\f[R] argument) and stores them to the +provided destination pointer (\f[C]bounds_o\f[R] argument). The stored linear bounds consist of bounding boxes for time 0 -(\f[C]bounds0\f[] member) and time 1 (\f[C]bounds1\f[] member) as -specified by the \f[C]RTCLinearBounds\f[] structure. -Linearly interpolating these bounds to a specific time \f[C]t\f[] yields -bounds for the geometry at that time. +(\f[C]bounds0\f[R] member) and time 1 (\f[C]bounds1\f[R] member) as +specified by the \f[C]RTCLinearBounds\f[R] structure. +Linearly interpolating these bounds to a specific time \f[C]t\f[R] +yields bounds for the geometry at that time. .PP The provided destination pointer must be aligned to 16 bytes. The function may be called only after committing the scene, otherwise @@ -44,7 +44,7 @@ the result is undefined. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetSceneBounds], [rtcCommitScene], [rtcJoinCommitScene] diff --git a/man/man3/rtcInitIntersectContext.3embree3 b/man/man3/rtcInitIntersectContext.3embree3 index dab19bf181..aeae947139 100644 --- a/man/man3/rtcInitIntersectContext.3embree3 +++ b/man/man3/rtcInitIntersectContext.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcInitIntersectContext" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,74 +6,71 @@ .IP .nf \f[C] -rtcInitIntersectContext\ \-\ initializes\ the\ intersection\ context -\f[] +rtcInitIntersectContext \- initializes the intersection context +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -enum\ RTCIntersectContextFlags +enum RTCIntersectContextFlags { -\ \ RTC_INTERSECT_CONTEXT_FLAG_NONE, -\ \ RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT, -\ \ RTC_INTERSECT_CONTEXT_FLAG_COHERENT, + RTC_INTERSECT_CONTEXT_FLAG_NONE, + RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT, + RTC_INTERSECT_CONTEXT_FLAG_COHERENT, }; -struct\ RTCIntersectContext +struct RTCIntersectContext { -\ \ enum\ RTCIntersectContextFlags\ flags; -\ \ RTCFilterFunctionN\ filter; -\ \ -\ \ #if\ RTC_MAX_INSTANCE_LEVEL_COUNT\ >\ 1 -\ \ \ \ unsigned\ int\ instStackSize; -\ \ #endif -\ \ -\ \ unsigned\ int\ instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; + enum RTCIntersectContextFlags flags; + RTCFilterFunctionN filter; + + #if RTC_MAX_INSTANCE_LEVEL_COUNT > 1 + unsigned int instStackSize; + #endif + + unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; -\ \ #if\ RTC_MIN_WIDTH -\ \ \ \ float\ minWidthDistanceFactor; -\ \ #endif + #if RTC_MIN_WIDTH + float minWidthDistanceFactor; + #endif }; -void\ rtcInitIntersectContext( -\ \ struct\ RTCIntersectContext*\ context +void rtcInitIntersectContext( + struct RTCIntersectContext* context ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -A per ray\-query intersection context (\f[C]RTCIntersectContext\f[] +A per ray\-query intersection context (\f[C]RTCIntersectContext\f[R] type) is supported that can be used to configure intersection flags -(\f[C]flags\f[] member), specify a filter callback function -(\f[C]filter\f[] member), specify the chain of IDs of the current -instance (\f[C]instID\f[] and \f[C]instStackSize\f[] members), and to -attach arbitrary data to the query (e.g. -per ray data). +(\f[C]flags\f[R] member), specify a filter callback function +(\f[C]filter\f[R] member), specify the chain of IDs of the current +instance (\f[C]instID\f[R] and \f[C]instStackSize\f[R] members), and to +attach arbitrary data to the query (e.g.\ per ray data). .PP -The \f[C]rtcInitIntersectContext\f[] function initializes the context to -default values and should be called to initialize every intersection +The \f[C]rtcInitIntersectContext\f[R] function initializes the context +to default values and should be called to initialize every intersection context. This function gets inlined, which minimizes overhead and allows for compiler optimizations. .PP The intersection context flag can be used to tune the behavior of the traversal algorithm. -Using the \f[C]RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT\f[] flags uses an +Using the \f[C]RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT\f[R] flags uses an optimized traversal algorithm for incoherent rays (default), while -\f[C]RTC_INTERSECT_CONTEXT_FLAG_COHERENT\f[] uses an optimized traversal -algorithm for coherent rays (e.g. -primary camera rays). +\f[C]RTC_INTERSECT_CONTEXT_FLAG_COHERENT\f[R] uses an optimized +traversal algorithm for coherent rays (e.g.\ primary camera rays). .PP Best primary ray performance can be obtained by using the ray stream API and setting the intersect context flag to -\f[C]RTC_INTERSECT_CONTEXT_FLAG_COHERENT\f[]. +\f[C]RTC_INTERSECT_CONTEXT_FLAG_COHERENT\f[R]. For secondary rays, it is typically better to use the -\f[C]RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT\f[] flag, unless the rays are -known to be very coherent too (e.g. -for primary transparency rays). +\f[C]RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT\f[R] flag, unless the rays +are known to be very coherent too (e.g.\ for primary transparency rays). .PP A filter function can be specified inside the context. This filter function is invoked as a second filter stage after the @@ -84,7 +81,8 @@ Having such a per ray\-query filter function can be useful to implement modifications of the behavior of the query, such as collecting all hits or accumulating transparencies. The support for the context filter function must be enabled for a scene -by using the \f[C]RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION\f[] scene flag. +by using the \f[C]RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION\f[R] scene +flag. In case of instancing this feature has to get enabled also for each instantiated scene. .PP diff --git a/man/man3/rtcInitPointQueryContext.3embree3 b/man/man3/rtcInitPointQueryContext.3embree3 index e5ba8e7b99..32737d3db6 100644 --- a/man/man3/rtcInitPointQueryContext.3embree3 +++ b/man/man3/rtcInitPointQueryContext.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcInitPointQueryContext" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,45 +6,45 @@ .IP .nf \f[C] -rtcInitPointQueryContext\ \-\ initializes\ the\ context\ information\ (e.g. -\ \ stack\ of\ (multilevel\-)instance\ transformations)\ for\ point\ queries -\f[] +rtcInitPointQueryContext \- initializes the context information (e.g. + stack of (multilevel\-)instance transformations) for point queries +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTC_ALIGN(16)\ RTCPointQueryContext +struct RTC_ALIGN(16) RTCPointQueryContext { -\ \ //\ accumulated\ 4x4\ column\ major\ matrices\ from\ world\ to\ instance\ space. -\ \ float\ world2inst[RTC_MAX_INSTANCE_LEVEL_COUNT][16]; -\ \ -\ \ //\ accumulated\ 4x4\ column\ major\ matrices\ from\ instance\ to\ world\ space. -\ \ float\ inst2world[RTC_MAX_INSTANCE_LEVEL_COUNT][16]; + // accumulated 4x4 column major matrices from world to instance space. + float world2inst[RTC_MAX_INSTANCE_LEVEL_COUNT][16]; + + // accumulated 4x4 column major matrices from instance to world space. + float inst2world[RTC_MAX_INSTANCE_LEVEL_COUNT][16]; -\ \ //\ instance\ ids. -\ \ unsigned\ int\ instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; -\ \ -\ \ //\ number\ of\ instances\ currently\ on\ the\ stack. -\ \ unsigned\ int\ instStackSize; + // instance ids. + unsigned int instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; + + // number of instances currently on the stack. + unsigned int instStackSize; }; -void\ rtcInitPointQueryContext( -\ \ struct\ RTCPointQueryContext*\ context +void rtcInitPointQueryContext( + struct RTCPointQueryContext* context ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -A stack (\f[C]RTCPointQueryContext\f[] type) which stores the IDs and +A stack (\f[C]RTCPointQueryContext\f[R] type) which stores the IDs and instance transformations during a BVH traversal for a point query. -The transformations are assumed to be affine transformations (3×3 matrix -plus translation) and therefore the last column is ignored (see +The transformations are assumed to be affine transformations (3\[tmu]3 +matrix plus translation) and therefore the last column is ignored (see [RTC_GEOMETRY_TYPE_INSTANCE] for details). .PP -The \f[C]rtcInitPointContext\f[] function initializes the context to +The \f[C]rtcInitPointContext\f[R] function initializes the context to default values and should be called for initialization. .PP The context will be passed as an argument to the point query callback @@ -54,7 +54,7 @@ instancing (see tutorial [ClosestPoint] for a reference implementation of point queries with user defined instancing). .PP The context is an necessary argument to [rtcPointQuery] and Embree -internally uses the topmost instance tranformation of the stack to +internally uses the topmost instance transformation of the stack to transform the point query into instance space. .SS EXIT STATUS .PP diff --git a/man/man3/rtcInitPointQueryInstanceStack.3embree3 b/man/man3/rtcInitPointQueryInstanceStack.3embree3 deleted file mode 100644 index 907552b952..0000000000 --- a/man/man3/rtcInitPointQueryInstanceStack.3embree3 +++ /dev/null @@ -1,58 +0,0 @@ -.TH "rtcInitPointQueryInstanceStack" "3" "" "" "Embree Ray Tracing Kernels 3" -.SS NAME -.IP -.nf -\f[C] -rtcInitPointQueryInstanceStack\ \-\ initializes\ the\ stack\ of\ (multilevel\-)instance -\ \ information\ for\ point\ queries -\f[] -.fi -.SS SYNOPSIS -.IP -.nf -\f[C] -#include\ - -struct\ RTC_ALIGN(16)\ RTCPointQueryInstanceStack -{ -\ \ //\ accumulated\ 4x4\ column\ major\ matrices\ from\ world\ to\ instance\ space. -\ \ float\ world2inst[RTC_MAX_INSTANCE_LEVEL_COUNT][16]; -\ \ -\ \ //\ accumulated\ 4x4\ column\ major\ matrices\ from\ instance\ to\ world\ space. -\ \ float\ inst2world[RTC_MAX_INSTANCE_LEVEL_COUNT][16]; - -\ \ //\ instance\ ids. -\ \ unsigned\ int\ instID[RTC_MAX_INSTANCE_LEVEL_COUNT]; -\ \ -\ \ //\ number\ of\ instances\ currently\ on\ the\ stack. -\ \ unsigned\ int\ size; -}; - -void\ rtcInitPointQueryInstanceStack( -\ \ struct\ RTCPointQueryInstanceStack*\ instStack -); -\f[] -.fi -.SS DESCRIPTION -.PP -A stack (\f[C]RTCPointQueryInstanceStack\f[] type) which stores the IDs -and instance transformations during a BVH traversal for a point query. -.PP -The \f[C]rtcInitPointQueryStack\f[] function initializes the stack to -default values and should be called for initialization. -.PP -The stack will be passed as an argument to the point query callback -function (see [rtcSetGeometryPointQueryFunction]) and should be used to -pass instance information down the instancing chain for user defined -instancing (see tutorial [ClosestPoint] for a reference implementation -of point queries with user defined instancing). -.PP -The stack is an necessary argument to [rtcPointQuery] and Embree -internally uses the topmost instance tranformation of the stack to -transform the point query into instance space. -.SS EXIT STATUS -.PP -No error code is set by this function. -.SS SEE ALSO -.PP -[rtcPointQuery], [rtcSetGeometryPointQueryFunction] diff --git a/man/man3/rtcInitQuaternionDecomposition.3embree3 b/man/man3/rtcInitQuaternionDecomposition.3embree3 index e1364aa393..ba79cfc602 100644 --- a/man/man3/rtcInitQuaternionDecomposition.3embree3 +++ b/man/man3/rtcInitQuaternionDecomposition.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcInitQuaternionDecomposition" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,22 +6,22 @@ .IP .nf \f[C] -rtcInitQuaternionDecomposition\ \-\ initializes\ quaternion\ decomposition -\f[] +rtcInitQuaternionDecomposition \- initializes quaternion decomposition +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -void\ rtcInitQuaternionDecomposition( -\ \ struct\ RTCQuaternionDecomposition*\ qd +void rtcInitQuaternionDecomposition( + struct RTCQuaternionDecomposition* qd ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcInitQuaternionDecomposition\f[] function initializes a -\f[C]RTCQuaternionDecomposition\f[] structure to represent an identity +The \f[C]rtcInitQuaternionDecomposition\f[R] function initializes a +\f[C]RTCQuaternionDecomposition\f[R] structure to represent an identity transformation. .SS EXIT STATUS .PP diff --git a/man/man3/rtcInterpolate.3embree3 b/man/man3/rtcInterpolate.3embree3 index 8c34f7118d..8403f36e90 100644 --- a/man/man3/rtcInterpolate.3embree3 +++ b/man/man3/rtcInterpolate.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcInterpolate" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,40 +6,40 @@ .IP .nf \f[C] -rtcInterpolate\ \-\ interpolates\ vertex\ attributes -\f[] +rtcInterpolate \- interpolates vertex attributes +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCInterpolateArguments +struct RTCInterpolateArguments { -\ \ RTCGeometry\ geometry; -\ \ unsigned\ int\ primID; -\ \ float\ u; -\ \ float\ v; -\ \ enum\ RTCBufferType\ bufferType; -\ \ unsigned\ int\ bufferSlot; -\ \ float*\ P; -\ \ float*\ dPdu; -\ \ float*\ dPdv; -\ \ float*\ ddPdudu; -\ \ float*\ ddPdvdv; -\ \ float*\ ddPdudv; -\ \ unsigned\ int\ valueCount; + RTCGeometry geometry; + unsigned int primID; + float u; + float v; + enum RTCBufferType bufferType; + unsigned int bufferSlot; + float* P; + float* dPdu; + float* dPdv; + float* ddPdudu; + float* ddPdvdv; + float* ddPdudv; + unsigned int valueCount; }; -void\ rtcInterpolate( -\ \ const\ struct\ RTCInterpolateArguments*\ args +void rtcInterpolate( + const struct RTCInterpolateArguments* args ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcInterpolate\f[] function smoothly interpolates per\-vertex +The \f[C]rtcInterpolate\f[R] function smoothly interpolates per\-vertex data over the geometry. This interpolation is supported for triangle meshes, quad meshes, curve geometries, and subdivision geometries. @@ -48,45 +48,45 @@ possible to get the first and second order derivatives of that value. This interpolation ignores displacements of subdivision surfaces and always interpolates the underlying base surface. .PP -The \f[C]rtcInterpolate\f[] call gets passed a number of arguments -inside a structure of type \f[C]RTCInterpolateArguments\f[]. -For some geometry (\f[C]geometry\f[] parameter) this function smoothly +The \f[C]rtcInterpolate\f[R] call gets passed a number of arguments +inside a structure of type \f[C]RTCInterpolateArguments\f[R]. +For some geometry (\f[C]geometry\f[R] parameter) this function smoothly interpolates the per\-vertex data stored inside the specified geometry -buffer (\f[C]bufferType\f[] and \f[C]bufferSlot\f[] parameters) to the -u/v location (\f[C]u\f[] and \f[C]v\f[] parameters) of the primitive -(\f[C]primID\f[] parameter). +buffer (\f[C]bufferType\f[R] and \f[C]bufferSlot\f[R] parameters) to the +u/v location (\f[C]u\f[R] and \f[C]v\f[R] parameters) of the primitive +(\f[C]primID\f[R] parameter). The number of floating point values to interpolate and store to the -destination arrays can be specified using the \f[C]valueCount\f[] +destination arrays can be specified using the \f[C]valueCount\f[R] parameter. As interpolation buffer, one can specify vertex buffers -(\f[C]RTC_BUFFER_TYPE_VERTEX\f[]) and vertex attribute buffers -(\f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[]) as well. +(\f[C]RTC_BUFFER_TYPE_VERTEX\f[R]) and vertex attribute buffers +(\f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[R]) as well. .PP -The \f[C]rtcInterpolate\f[] call stores \f[C]valueCount\f[] number of +The \f[C]rtcInterpolate\f[R] call stores \f[C]valueCount\f[R] number of interpolated floating point values to the memory location pointed to by -\f[C]P\f[]. -One can avoid storing the interpolated value by setting \f[C]P\f[] to -\f[C]NULL\f[]. +\f[C]P\f[R]. +One can avoid storing the interpolated value by setting \f[C]P\f[R] to +\f[C]NULL\f[R]. .PP The first order derivative of the interpolation by u and v are stored at -the \f[C]dPdu\f[] and \f[C]dPdv\f[] memory locations. +the \f[C]dPdu\f[R] and \f[C]dPdv\f[R] memory locations. One can avoid storing first order derivatives by setting both -\f[C]dPdu\f[] and \f[C]dPdv\f[] to \f[C]NULL\f[]. +\f[C]dPdu\f[R] and \f[C]dPdv\f[R] to \f[C]NULL\f[R]. .PP -The second order derivatives are stored at the \f[C]ddPdudu\f[], -\f[C]ddPdvdv\f[], and \f[C]ddPdudv\f[] memory locations. +The second order derivatives are stored at the \f[C]ddPdudu\f[R], +\f[C]ddPdvdv\f[R], and \f[C]ddPdudv\f[R] memory locations. One can avoid storing second order derivatives by setting these three -pointers to \f[C]NULL\f[]. +pointers to \f[C]NULL\f[R]. .PP -To use \f[C]rtcInterpolate\f[] for a geometry, all changes to that -geometry must be properly committed using \f[C]rtcCommitGeometry\f[]. +To use \f[C]rtcInterpolate\f[R] for a geometry, all changes to that +geometry must be properly committed using \f[C]rtcCommitGeometry\f[R]. .PP All input buffers and output arrays must be padded to 16 bytes, as the implementation uses 16\-byte SSE instructions to read and write into these buffers. .PP See tutorial [Interpolation] for an example of using the -\f[C]rtcInterpolate\f[] function. +\f[C]rtcInterpolate\f[R] function. .SS EXIT STATUS .PP For performance reasons this function does not do any error checks, thus diff --git a/man/man3/rtcInterpolateN.3embree3 b/man/man3/rtcInterpolateN.3embree3 index 582263085d..762935ef3c 100644 --- a/man/man3/rtcInterpolateN.3embree3 +++ b/man/man3/rtcInterpolateN.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcInterpolateN" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,54 +6,54 @@ .IP .nf \f[C] -rtcInterpolateN\ \-\ performs\ N\ interpolations\ of\ vertex\ attribute\ data -\f[] +rtcInterpolateN \- performs N interpolations of vertex attribute data +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCInterpolateNArguments +struct RTCInterpolateNArguments { -\ \ RTCGeometry\ geometry; -\ \ const\ void*\ valid; -\ \ const\ unsigned\ int*\ primIDs; -\ \ const\ float*\ u; -\ \ const\ float*\ v; -\ \ unsigned\ int\ N; -\ \ enum\ RTCBufferType\ bufferType; -\ \ unsigned\ int\ bufferSlot; -\ \ float*\ P; -\ \ float*\ dPdu; -\ \ float*\ dPdv; -\ \ float*\ ddPdudu; -\ \ float*\ ddPdvdv; -\ \ float*\ ddPdudv; -\ \ unsigned\ int\ valueCount; + RTCGeometry geometry; + const void* valid; + const unsigned int* primIDs; + const float* u; + const float* v; + unsigned int N; + enum RTCBufferType bufferType; + unsigned int bufferSlot; + float* P; + float* dPdu; + float* dPdv; + float* ddPdudu; + float* ddPdvdv; + float* ddPdudv; + unsigned int valueCount; }; -void\ rtcInterpolateN( -\ \ const\ struct\ RTCInterpolateNArguments*\ args +void rtcInterpolateN( + const struct RTCInterpolateNArguments* args ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcInterpolateN\f[] is similar to \f[C]rtcInterpolate\f[], but -performs \f[C]N\f[] many interpolations at once. +The \f[C]rtcInterpolateN\f[R] is similar to \f[C]rtcInterpolate\f[R], +but performs \f[C]N\f[R] many interpolations at once. It additionally gets an array of u/v coordinates and a valid mask -(\f[C]valid\f[] parameter) that specifies which of these coordinates are -valid. -The valid mask points to \f[C]N\f[] integers, and a value of \-1 denotes -valid and 0 invalid. -If the valid pointer is \f[C]NULL\f[] all elements are considers valid. +(\f[C]valid\f[R] parameter) that specifies which of these coordinates +are valid. +The valid mask points to \f[C]N\f[R] integers, and a value of \-1 +denotes valid and 0 invalid. +If the valid pointer is \f[C]NULL\f[R] all elements are considers valid. The destination arrays are filled in structure of array (SOA) layout. -The value \f[C]N\f[] must be divisible by 4. +The value \f[C]N\f[R] must be divisible by 4. .PP -To use \f[C]rtcInterpolateN\f[] for a geometry, all changes to that -geometry must be properly committed using \f[C]rtcCommitGeometry\f[]. +To use \f[C]rtcInterpolateN\f[R] for a geometry, all changes to that +geometry must be properly committed using \f[C]rtcCommitGeometry\f[R]. .SS EXIT STATUS .PP For performance reasons this function does not do any error checks, thus diff --git a/man/man3/rtcIntersect1.3embree3 b/man/man3/rtcIntersect1.3embree3 index b52c3182a9..aa5e5292fc 100644 --- a/man/man3/rtcIntersect1.3embree3 +++ b/man/man3/rtcIntersect1.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcIntersect1" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,85 +6,86 @@ .IP .nf \f[C] -rtcIntersect1\ \-\ finds\ the\ closest\ hit\ for\ a\ single\ ray -\f[] +rtcIntersect1 \- finds the closest hit for a single ray +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcIntersect1( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHit*\ rayhit +void rtcIntersect1( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHit* rayhit ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcIntersect1\f[] function finds the closest hit of a single -ray with the scene (\f[C]scene\f[] argument). -The provided ray/hit structure (\f[C]rayhit\f[] argument) contains the +The \f[C]rtcIntersect1\f[R] function finds the closest hit of a single +ray with the scene (\f[C]scene\f[R] argument). +The provided ray/hit structure (\f[C]rayhit\f[R] argument) contains the ray to intersect and some hit output fields that are filled when a hit is found. .PP -The user has to initialize the ray origin (\f[C]org\f[] ray member), ray -direction (\f[C]dir\f[] ray member), ray segment (\f[C]tnear\f[], -\f[C]tfar\f[] ray members), and set the ray flags to \f[C]0\f[] -(\f[C]flags\f[] ray member). +The user has to initialize the ray origin (\f[C]org\f[R] ray member), +ray direction (\f[C]dir\f[R] ray member), ray segment (\f[C]tnear\f[R], +\f[C]tfar\f[R] ray members), and set the ray flags to \f[C]0\f[R] +(\f[C]flags\f[R] ray member). If the scene contains motion blur geometries, also the ray time -(\f[C]time\f[] ray member) must be initialized to a value in the range -[0, 1]. -If ray masks are enabled at compile time, the ray mask (\f[C]mask\f[] +(\f[C]time\f[R] ray member) must be initialized to a value in the range +[0,\[u2006]1]. +If ray masks are enabled at compile time, the ray mask (\f[C]mask\f[R] ray member) must be initialized as well. -The ray segment has to be in the range [0, ∞], thus ranges that start -behind the ray origin are not valid, but ranges can reach to infinity. +The ray segment has to be in the range [0,\[u2006]\[if]], thus ranges +that start behind the ray origin are not valid, but ranges can reach to +infinity. See Section [RTCRay] for the ray layout description. .PP -The geometry ID (\f[C]geomID\f[] hit member) of the hit data must be -initialized to \f[C]RTC_INVALID_GEOMETRY_ID\f[] (\-1). +The geometry ID (\f[C]geomID\f[R] hit member) of the hit data must be +initialized to \f[C]RTC_INVALID_GEOMETRY_ID\f[R] (\-1). .PP Further, an intersection context for the ray query function must be -created and initialized (see \f[C]rtcInitIntersectContext\f[]). +created and initialized (see \f[C]rtcInitIntersectContext\f[R]). .PP When no intersection is found, the ray/hit data is not updated. When an intersection is found, the hit distance is written into the -\f[C]tfar\f[] member of the ray and all hit data is set, such as -unnormalized geometry normal in object space (\f[C]Ng\f[] hit member), -local hit coordinates (\f[C]u\f[], \f[C]v\f[] hit member), instance ID -stack (\f[C]instID\f[] hit member), geometry ID (\f[C]geomID\f[] hit -member), and primitive ID (\f[C]primID\f[] hit member). +\f[C]tfar\f[R] member of the ray and all hit data is set, such as +unnormalized geometry normal in object space (\f[C]Ng\f[R] hit member), +local hit coordinates (\f[C]u\f[R], \f[C]v\f[R] hit member), instance ID +stack (\f[C]instID\f[R] hit member), geometry ID (\f[C]geomID\f[R] hit +member), and primitive ID (\f[C]primID\f[R] hit member). See Section [RTCHit] for the hit layout description. .PP If the instance ID stack has a prefix of values not equal to -\f[C]RTC_INVALID_GEOMETRY_ID\f[], the instance ID on each level +\f[C]RTC_INVALID_GEOMETRY_ID\f[R], the instance ID on each level corresponds to the geometry ID of the hit instance of the higher\-level scene, the geometry ID corresponds to the hit geometry inside the hit instanced scene, and the primitive ID corresponds to the n\-th primitive of that geometry. .PP If level 0 of the instance ID stack is equal to -\f[C]RTC_INVALID_GEOMETRY_ID\f[], the geometry ID corresponds to the hit -geometry inside the top\-level scene, and the primitive ID corresponds -to the n\-th primitive of that geometry. +\f[C]RTC_INVALID_GEOMETRY_ID\f[R], the geometry ID corresponds to the +hit geometry inside the top\-level scene, and the primitive ID +corresponds to the n\-th primitive of that geometry. .PP The implementation makes no guarantees that primitives whose hit -distance is exactly at (or very close to) \f[C]tnear\f[] or -\f[C]tfar\f[] are hit or missed. -If you want to exclude intersections at \f[C]tnear\f[] just pass a -slightly enlarged \f[C]tnear\f[], and if you want to include -intersections at \f[C]tfar\f[] pass a slightly enlarged \f[C]tfar\f[]. +distance is exactly at (or very close to) \f[C]tnear\f[R] or +\f[C]tfar\f[R] are hit or missed. +If you want to exclude intersections at \f[C]tnear\f[R] just pass a +slightly enlarged \f[C]tnear\f[R], and if you want to include +intersections at \f[C]tfar\f[R] pass a slightly enlarged \f[C]tfar\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP The ray/hit structure must be aligned to 16 bytes. diff --git a/man/man3/rtcIntersect1M.3embree3 b/man/man3/rtcIntersect1M.3embree3 index c8f6208da3..cbdd10bdb1 100644 --- a/man/man3/rtcIntersect1M.3embree3 +++ b/man/man3/rtcIntersect1M.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcIntersect1M" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,50 +6,50 @@ .IP .nf \f[C] -rtcIntersect1M\ \-\ finds\ the\ closest\ hits\ for\ a\ stream\ of\ M\ single -\ \ rays -\f[] +rtcIntersect1M \- finds the closest hits for a stream of M single + rays +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcIntersect1M( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHit*\ rayhit, -\ \ unsigned\ int\ M, -\ \ size_t\ byteStride +void rtcIntersect1M( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHit* rayhit, + unsigned int M, + size_t byteStride ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcIntersect1M\f[] function finds the closest hits for a stream -of \f[C]M\f[] single rays (\f[C]rayhit\f[] argument) with the scene -(\f[C]scene\f[] argument). -The \f[C]rayhit\f[] argument points to an array of ray and hit data with -specified byte stride (\f[C]byteStride\f[] argument) between the ray/hit -structures. +The \f[C]rtcIntersect1M\f[R] function finds the closest hits for a +stream of \f[C]M\f[R] single rays (\f[C]rayhit\f[R] argument) with the +scene (\f[C]scene\f[R] argument). +The \f[C]rayhit\f[R] argument points to an array of ray and hit data +with specified byte stride (\f[C]byteStride\f[R] argument) between the +ray/hit structures. See Section [rtcIntersect1] for a description of how to set up and trace rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The stream size \f[C]M\f[] can be an arbitrary positive integer +The stream size \f[C]M\f[R] can be an arbitrary positive integer including 0. Each ray must be aligned to 16 bytes. .SS EXIT STATUS diff --git a/man/man3/rtcIntersect1Mp.3embree3 b/man/man3/rtcIntersect1Mp.3embree3 index 9919ea4418..9eb34d5267 100644 --- a/man/man3/rtcIntersect1Mp.3embree3 +++ b/man/man3/rtcIntersect1Mp.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcIntersect1Mp" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,48 +6,48 @@ .IP .nf \f[C] -rtcIntersect1Mp\ \-\ finds\ the\ closest\ hits\ for\ a\ stream\ of\ M\ pointers -\ \ to\ single\ rays -\f[] +rtcIntersect1Mp \- finds the closest hits for a stream of M pointers + to single rays +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcIntersect1Mp( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHit**\ rayhit, -\ \ unsigned\ int\ M +void rtcIntersect1Mp( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHit** rayhit, + unsigned int M ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcIntersect1Mp\f[] function finds the closest hits for a -stream of \f[C]M\f[] single rays (\f[C]rayhit\f[] argument) with the -scene (\f[C]scene\f[] argument). -The \f[C]rayhit\f[] argument points to an array of pointers to the +The \f[C]rtcIntersect1Mp\f[R] function finds the closest hits for a +stream of \f[C]M\f[R] single rays (\f[C]rayhit\f[R] argument) with the +scene (\f[C]scene\f[R] argument). +The \f[C]rayhit\f[R] argument points to an array of pointers to the individual ray/hit structures. See Section [rtcIntersect1] for a description of how to set up and trace a ray. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The stream size \f[C]M\f[] can be an arbitrary positive integer +The stream size \f[C]M\f[R] can be an arbitrary positive integer including 0. Each ray must be aligned to 16 bytes. .SS EXIT STATUS diff --git a/man/man3/rtcIntersect4.3embree3 b/man/man3/rtcIntersect4.3embree3 index 64124458e0..c53d17777f 100644 --- a/man/man3/rtcIntersect4.3embree3 +++ b/man/man3/rtcIntersect4.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcIntersect4/8/16" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,80 +6,80 @@ .IP .nf \f[C] -rtcIntersect4/8/16\ \-\ finds\ the\ closest\ hits\ for\ a\ ray\ packet -\f[] +rtcIntersect4/8/16 \- finds the closest hits for a ray packet +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcIntersect4( -\ \ const\ int*\ valid, -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHit4*\ rayhit +void rtcIntersect4( + const int* valid, + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHit4* rayhit ); -void\ rtcIntersect8( -\ \ const\ int*\ valid, -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHit8*\ rayhit +void rtcIntersect8( + const int* valid, + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHit8* rayhit ); -void\ rtcIntersect16( -\ \ const\ int*\ valid, -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHit16*\ rayhit +void rtcIntersect16( + const int* valid, + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHit16* rayhit ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcIntersect4/8/16\f[] functions finds the closest hits for a -ray packet of size 4, 8, or 16 (\f[C]rayhit\f[] argument) with the scene -(\f[C]scene\f[] argument). +The \f[C]rtcIntersect4/8/16\f[R] functions finds the closest hits for a +ray packet of size 4, 8, or 16 (\f[C]rayhit\f[R] argument) with the +scene (\f[C]scene\f[R] argument). The ray/hit input contains a ray packet and hit packet. See Section [rtcIntersect1] for a description of how to set up and trace rays. .PP -A ray valid mask must be provided (\f[C]valid\f[] argument) which stores -one 32\-bit integer (\f[C]\-1\f[] means valid and \f[C]0\f[] invalid) -per ray in the packet. +A ray valid mask must be provided (\f[C]valid\f[R] argument) which +stores one 32\-bit integer (\f[C]\-1\f[R] means valid and \f[C]0\f[R] +invalid) per ray in the packet. Only active rays are processed, and hit data of inactive rays is not changed. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP The implementation of these functions is guaranteed to invoke callback functions always with the same ray packet size and ordering of rays as specified initially. .PP -For \f[C]rtcIntersect4\f[] the ray packet must be aligned to 16 bytes, -for \f[C]rtcIntersect8\f[] the alignment must be 32 bytes, and for -\f[C]rtcIntersect16\f[] the alignment must be 64 bytes. +For \f[C]rtcIntersect4\f[R] the ray packet must be aligned to 16 bytes, +for \f[C]rtcIntersect8\f[R] the alignment must be 32 bytes, and for +\f[C]rtcIntersect16\f[R] the alignment must be 64 bytes. .PP -The \f[C]rtcIntersect4\f[], \f[C]rtcIntersect8\f[] and -\f[C]rtcIntersect16\f[] functions may change the ray packet size and ray -order when calling back into intersect filter functions or user geometry -callbacks. +The \f[C]rtcIntersect4\f[R], \f[C]rtcIntersect8\f[R] and +\f[C]rtcIntersect16\f[R] functions may change the ray packet size and +ray order when calling back into intersect filter functions or user +geometry callbacks. Under some conditions the application can assume packets to stay intakt, which can determined by querying the -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[], -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[], -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[] properties through -the \f[C]rtcGetDeviceProperty\f[] function. +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[R], +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[R], +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[R] properties through +the \f[C]rtcGetDeviceProperty\f[R] function. See [rtcGetDeviceProperty] for more information. .SS EXIT STATUS .PP diff --git a/man/man3/rtcIntersectNM.3embree3 b/man/man3/rtcIntersectNM.3embree3 index 096e7713a1..a239481733 100644 --- a/man/man3/rtcIntersectNM.3embree3 +++ b/man/man3/rtcIntersectNM.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcIntersectNM" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,52 +6,52 @@ .IP .nf \f[C] -rtcIntersectNM\ \-\ finds\ the\ closest\ hits\ for\ a\ stream\ of\ M -\ \ ray\ packets\ of\ size\ N -\f[] +rtcIntersectNM \- finds the closest hits for a stream of M + ray packets of size N +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcIntersectNM( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHitN*\ rayhit, -\ \ unsigned\ int\ N, -\ \ unsigned\ int\ M, -\ \ size_t\ byteStride +void rtcIntersectNM( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHitN* rayhit, + unsigned int N, + unsigned int M, + size_t byteStride ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcIntersectNM\f[] function finds the closest hits for a stream -of \f[C]M\f[] ray packets (\f[C]rayhit\f[] argument) of size \f[C]N\f[] -with the scene (\f[C]scene\f[] argument). -The \f[C]rays\f[] argument points to an array of ray and hit packets -with specified byte stride (\f[C]byteStride\f[] argument) between the +The \f[C]rtcIntersectNM\f[R] function finds the closest hits for a +stream of \f[C]M\f[R] ray packets (\f[C]rayhit\f[R] argument) of size +\f[C]N\f[R] with the scene (\f[C]scene\f[R] argument). +The \f[C]rays\f[R] argument points to an array of ray and hit packets +with specified byte stride (\f[C]byteStride\f[R] argument) between the ray/hit packets. See Section [rtcIntersect1] for a description of how to set up and trace rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The packet size \f[C]N\f[] must be larger than 0, and the stream size -\f[C]M\f[] can be an arbitrary positive integer including 0. +The packet size \f[C]N\f[R] must be larger than 0, and the stream size +\f[C]M\f[R] can be an arbitrary positive integer including 0. Each ray must be aligned to 16 bytes. .SS EXIT STATUS .PP diff --git a/man/man3/rtcIntersectNp.3embree3 b/man/man3/rtcIntersectNp.3embree3 index 244040ebdc..5066ed2781 100644 --- a/man/man3/rtcIntersectNp.3embree3 +++ b/man/man3/rtcIntersectNp.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcIntersectNp" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcIntersectNp\ \-\ finds\ the\ closest\ hits\ for\ a\ SOA\ ray\ stream\ of -\ \ size\ N -\f[] +rtcIntersectNp \- finds the closest hits for a SOA ray stream of + size N +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcIntersectNp( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayHitNp*\ rayhit, -\ \ unsigned\ int\ N +void rtcIntersectNp( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayHitNp* rayhit, + unsigned int N ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcIntersectNp\f[] function finds the closest hits for a SOA -ray stream (\f[C]rays\f[] argument) of size \f[C]N\f[] (basically a -large ray packet) with the scene (\f[C]scene\f[] argument). -The \f[C]rayhit\f[] argument points to two structures of pointers with +The \f[C]rtcIntersectNp\f[R] function finds the closest hits for a SOA +ray stream (\f[C]rays\f[R] argument) of size \f[C]N\f[R] (basically a +large ray packet) with the scene (\f[C]scene\f[R] argument). +The \f[C]rayhit\f[R] argument points to two structures of pointers with one pointer for each ray and hit component. Each of these pointers points to an array with the ray or hit component data for each ray or hit. @@ -41,18 +41,18 @@ rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The stream size \f[C]N\f[] can be an arbitrary positive integer +The stream size \f[C]N\f[R] can be an arbitrary positive integer including 0. Each ray component array must be aligned to 16 bytes. .SS EXIT STATUS diff --git a/man/man3/rtcJoinCommitScene.3embree3 b/man/man3/rtcJoinCommitScene.3embree3 index 835ce400b8..52e5aa0cf3 100644 --- a/man/man3/rtcJoinCommitScene.3embree3 +++ b/man/man3/rtcJoinCommitScene.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcJoinCommitScene" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,86 +6,86 @@ .IP .nf \f[C] -rtcJoinCommitScene\ \-\ commits\ the\ scene\ from\ multiple\ threads -\f[] +rtcJoinCommitScene \- commits the scene from multiple threads +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcJoinCommitScene(RTCScene\ scene); -\f[] +void rtcJoinCommitScene(RTCScene scene); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcJoinCommitScene\f[] function commits all changes for the -specified scene (\f[C]scene\f[] argument). +The \f[C]rtcJoinCommitScene\f[R] function commits all changes for the +specified scene (\f[C]scene\f[R] argument). The scene commit internally triggers building of a spatial acceleration structure for the scene. Ray queries can be performed after scene changes got properly committed. .PP -The \f[C]rtcJoinCommitScene\f[] function can get called from multiple +The \f[C]rtcJoinCommitScene\f[R] function can get called from multiple user threads which will all cooperate in the build operation. All threads calling into this function will return from -\f[C]rtcJoinCommitScene\f[] after the scene commit is finished. -All threads must consistently call \f[C]rtcJoinCommitScene\f[] and not -\f[C]rtcCommitScene\f[]. +\f[C]rtcJoinCommitScene\f[R] after the scene commit is finished. +All threads must consistently call \f[C]rtcJoinCommitScene\f[R] and not +\f[C]rtcCommitScene\f[R]. .PP -In contrast to the \f[C]rtcCommitScene\f[] function, the -\f[C]rtcJoinCommitScene\f[] function can be called from multiple user -threads, while the \f[C]rtcCommitScene\f[] can only get called from +In contrast to the \f[C]rtcCommitScene\f[R] function, the +\f[C]rtcJoinCommitScene\f[R] function can be called from multiple user +threads, while the \f[C]rtcCommitScene\f[R] can only get called from multiple TBB worker threads when used concurrently. For optimal performance we strongly recommend using TBB inside the -application together with the \f[C]rtcCommitScene\f[] function and to -avoid using the \f[C]rtcJoinCommitScene\f[] function. +application together with the \f[C]rtcCommitScene\f[R] function and to +avoid using the \f[C]rtcJoinCommitScene\f[R] function. .PP -The \f[C]rtcJoinCommitScene\f[] feature allows a flexible way to lazily +The \f[C]rtcJoinCommitScene\f[R] feature allows a flexible way to lazily create hierarchies during rendering. A thread reaching a not\-yet\-constructed sub\-scene of a two\-level scene can generate the sub\-scene geometry and call -\f[C]rtcJoinCommitScene\f[] on that just generated scene. +\f[C]rtcJoinCommitScene\f[R] on that just generated scene. During construction, further threads reaching the not\-yet\-built scene can join the build operation by also invoking -\f[C]rtcJoinCommitScene\f[]. -A thread that calls \f[C]rtcJoinCommitScene\f[] after the build finishes -will directly return from the \f[C]rtcJoinCommitScene\f[] call. +\f[C]rtcJoinCommitScene\f[R]. +A thread that calls \f[C]rtcJoinCommitScene\f[R] after the build +finishes will directly return from the \f[C]rtcJoinCommitScene\f[R] +call. .PP Multiple scene commit operations on different scenes can be running at the same time, hence it is possible to commit many small scenes in parallel, distributing the commits to many threads. .PP -When using Embree with the Intel® Threading Building Blocks (which is -the default), threads that call \f[C]rtcJoinCommitScene\f[] will join -the build operation, but other TBB worker threads might also participate -in the build. +When using Embree with the Intel\[rg] Threading Building Blocks (which +is the default), threads that call \f[C]rtcJoinCommitScene\f[R] will +join the build operation, but other TBB worker threads might also +participate in the build. To avoid thread oversubscription, we recommend using TBB also inside the application. Further, the join mode only works properly starting with TBB v4.4 Update 1. -For earlier TBB versions, threads that call \f[C]rtcJoinCommitScene\f[] +For earlier TBB versions, threads that call \f[C]rtcJoinCommitScene\f[R] to join a running build will just trigger the build and wait for the build to finish. -Further, old TBB versions with -\f[C]TBB_INTERFACE_VERSION_MAJOR\ <\ 8\f[] do not support -\f[C]rtcJoinCommitScene\f[], and invoking this function will result in -an error. +Further, old TBB versions with \f[C]TBB_INTERFACE_VERSION_MAJOR < 8\f[R] +do not support \f[C]rtcJoinCommitScene\f[R], and invoking this function +will result in an error. .PP When using Embree with the internal tasking system, only threads that -call \f[C]rtcJoinCommitScene\f[] will perform the build operation, and +call \f[C]rtcJoinCommitScene\f[R] will perform the build operation, and no additional worker threads will be scheduled. .PP When using Embree with the Parallel Patterns Library (PPL), -\f[C]rtcJoinCommitScene\f[] is not supported and calling that function +\f[C]rtcJoinCommitScene\f[R] is not supported and calling that function will result in an error. .PP -To detect whether \f[C]rtcJoinCommitScene\f[] is supported, use the -\f[C]rtcGetDeviceProperty\f[] function. +To detect whether \f[C]rtcJoinCommitScene\f[R] is supported, use the +\f[C]rtcGetDeviceProperty\f[R] function. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcCommitScene], [rtcGetDeviceProperty] diff --git a/man/man3/rtcNewBVH.3embree3 b/man/man3/rtcNewBVH.3embree3 index 1c61e06e8c..41e644a616 100644 --- a/man/man3/rtcNewBVH.3embree3 +++ b/man/man3/rtcNewBVH.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcNewBVH" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,32 +6,33 @@ .IP .nf \f[C] -rtcNewBVH\ \-\ creates\ a\ new\ BVH\ object -\f[] +rtcNewBVH \- creates a new BVH object +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCBVH\ rtcNewBVH(RTCDevice\ device); -\f[] +RTCBVH rtcNewBVH(RTCDevice device); +\f[R] .fi .SS DESCRIPTION .PP This function creates a new BVH object and returns a handle to this BVH. The BVH object is reference counted with an initial reference count of 1. -The handle can be released using the \f[C]rtcReleaseBVH\f[] API call. +The handle can be released using the \f[C]rtcReleaseBVH\f[R] API call. .PP The BVH object can be used to build a BVH in a user\-specified format over user\-specified primitives. -See the documentation of the \f[C]rtcBuildBVH\f[] call for more details. +See the documentation of the \f[C]rtcBuildBVH\f[R] call for more +details. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcRetainBVH], [rtcReleaseBVH], [rtcBuildBVH] diff --git a/man/man3/rtcNewBuffer.3embree3 b/man/man3/rtcNewBuffer.3embree3 index 3ab75ad64f..e3109adfaa 100644 --- a/man/man3/rtcNewBuffer.3embree3 +++ b/man/man3/rtcNewBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcNewBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,41 +6,41 @@ .IP .nf \f[C] -rtcNewBuffer\ \-\ creates\ a\ new\ data\ buffer -\f[] +rtcNewBuffer \- creates a new data buffer +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCBuffer\ rtcNewBuffer( -\ \ RTCDevice\ device, -\ \ size_t\ byteSize +RTCBuffer rtcNewBuffer( + RTCDevice device, + size_t byteSize ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcNewBuffer\f[] function creates a new data buffer object of -specified size in bytes (\f[C]byteSize\f[] argument) that is bound to -the specified device (\f[C]device\f[] argument). +The \f[C]rtcNewBuffer\f[R] function creates a new data buffer object of +specified size in bytes (\f[C]byteSize\f[R] argument) that is bound to +the specified device (\f[C]device\f[R] argument). The buffer object is reference counted with an initial reference count of 1. The returned buffer object can be released using the -\f[C]rtcReleaseBuffer\f[] API call. +\f[C]rtcReleaseBuffer\f[R] API call. The specified number of bytes are allocated at buffer construction time and deallocated when the buffer is destroyed. .IP .nf \f[C] -\f[] +\f[R] .fi .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcRetainBuffer], [rtcReleaseBuffer] diff --git a/man/man3/rtcNewDevice.3embree3 b/man/man3/rtcNewDevice.3embree3 index d6f291cc95..231b5cd0c2 100644 --- a/man/man3/rtcNewDevice.3embree3 +++ b/man/man3/rtcNewDevice.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcNewDevice" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,24 +6,25 @@ .IP .nf \f[C] -rtcNewDevice\ \-\ creates\ a\ new\ device -\f[] +rtcNewDevice \- creates a new device +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCDevice\ rtcNewDevice(const\ char*\ config); -\f[] +RTCDevice rtcNewDevice(const char* config); +\f[R] .fi .SS DESCRIPTION .PP This function creates a new device and returns a handle to this device. The device object is reference counted with an initial reference count of 1. -The handle can be released using the \f[C]rtcReleaseDevice\f[] API call. +The handle can be released using the \f[C]rtcReleaseDevice\f[R] API +call. .PP The device object acts as a class factory for all other object types. All objects created from the device (like scenes, geometries, etc.) hold @@ -34,107 +35,94 @@ Objects are only compatible if they belong to the same device, e.g it is not allowed to create a geometry in one device and attach it to a scene created with a different device. .PP -A configuration string (\f[C]config\f[] argument) can be passed to the +A configuration string (\f[C]config\f[R] argument) can be passed to the device construction. -This configuration string can be \f[C]NULL\f[] to use the default +This configuration string can be \f[C]NULL\f[R] to use the default configuration. .PP -When creating the device, Embree reads configurations for the device -from the following locations in order: -.IP "1)" 3 -\f[C]config\f[] string passed to the \f[C]rtcNewDevice\f[] function -.IP "2)" 3 -\f[C]\&.embree3\f[] file in the application folder -.IP "3)" 3 -\f[C]\&.embree3\f[] file in the home folder -.PP -Settings performed later overwrite previous settings. -This way the configuration for the application can be changed globally -(either through the \f[C]rtcNewDevice\f[] call or through the -\f[C]\&.embree3\f[] file in the application folder), and each user has -the option to modify the configuration to fit their needs. -.PP The following configuration is supported: .IP \[bu] 2 -\f[C]threads=[int]\f[]: Specifies a number of build threads to use. +\f[C]threads=[int]\f[R]: Specifies a number of build threads to use. A value of 0 enables all detected hardware threads. By default all hardware threads are used. .IP \[bu] 2 -\f[C]user_threads=[int]\f[]: Sets the number of user threads that can be -used to join and participate in a scene commit using -\f[C]rtcJoinCommitScene\f[]. +\f[C]user_threads=[int]\f[R]: Sets the number of user threads that can +be used to join and participate in a scene commit using +\f[C]rtcJoinCommitScene\f[R]. The tasking system will only use threads\-user_threads many worker threads, thus if the app wants to solely use its threads to commit scenes, just set threads equal to user_threads. This option only has effect with the Intel(R) Threading Building Blocks (TBB) tasking system. .IP \[bu] 2 -\f[C]set_affinity=[0/1]\f[]: When enabled, build threads are affinitized -to hardware threads. +\f[C]set_affinity=[0/1]\f[R]: When enabled, build threads are +affinitized to hardware threads. This option is disabled by default on standard CPUs, and enabled by default on Xeon Phi Processors. .IP \[bu] 2 -\f[C]start_threads=[0/1]\f[]: When enabled, the build threads are +\f[C]start_threads=[0/1]\f[R]: When enabled, the build threads are started upfront. This can be useful for benchmarking to exclude thread creation time. This option is disabled by default. .IP \[bu] 2 -\f[C]isa=[sse2,sse4.2,avx,avx2,avx512knl,avx512skx]\f[]: Use specified -ISA. +\f[C]isa=[sse2,sse4.2,avx,avx2,avx512]\f[R]: Use specified ISA. By default the ISA is selected automatically. .IP \[bu] 2 -\f[C]max_isa=[sse2,sse4.2,avx,avx2,avx512knl,avx512skx]\f[]: Configures -the automated ISA selection to use maximally the specified ISA. +\f[C]max_isa=[sse2,sse4.2,avx,avx2,avx512]\f[R]: Configures the +automated ISA selection to use maximally the specified ISA. .IP \[bu] 2 -\f[C]hugepages=[0/1]\f[]: Enables or disables usage of huge pages. +\f[C]hugepages=[0/1]\f[R]: Enables or disables usage of huge pages. Under Linux huge pages are used by default but under Windows and macOS they are disabled by default. .IP \[bu] 2 -\f[C]enable_selockmemoryprivilege=[0/1]\f[]: When set to 1, this enables -the \f[C]SeLockMemoryPrivilege\f[] privilege with is required to use -huge pages on Windows. +\f[C]enable_selockmemoryprivilege=[0/1]\f[R]: When set to 1, this +enables the \f[C]SeLockMemoryPrivilege\f[R] privilege with is required +to use huge pages on Windows. This option has an effect only under Windows and is ignored on other platforms. See Section [Huge Page Support] for more details. .IP \[bu] 2 -\f[C]ignore_config_files=[0/1]\f[]: When set to 1, configuration files -are ignored. -Default is 0. -.IP \[bu] 2 -\f[C]verbose=[0,1,2,3]\f[]: Sets the verbosity of the output. +\f[C]verbose=[0,1,2,3]\f[R]: Sets the verbosity of the output. When set to 0, no output is printed by Embree, when set to a higher level more output is printed. By default Embree does not print anything on the console. .IP \[bu] 2 -\f[C]frequency_level=[simd128,simd256,simd512]\f[]: Specifies the -frequency level the application want to run on, which can be either: a) -simd128 for apps that do not use AVX instructions, b) simd256 for apps -that use heavy AVX instruction, c) simd512 for apps that use heavy -AVX\-512 instructions. +\f[C]frequency_level=[simd128,simd256,simd512]\f[R]: Specifies the +frequency level the application want to run on, which can be either: +.RS 2 +.IP "a)" 3 +simd128 to run at highest frequency +.IP "b)" 3 +simd256 to run at AVX2\-heavy frequency level +.IP "c)" 3 +simd512 to run at heavy AVX512 frequency level. When some frequency level is specified, Embree will avoid doing optimizations that may reduce the frequency level below the level specified. E.g. if your app does not use AVX instructions setting -"frequency_level=simd128" will cause some CPUs to run at highest -frequency, which may result in higher application performance. -However, this will prevent Embree from using AVX optimizations to -achieve higher ray tracing performance, thus applications that trace -many rays may still perform better with the default setting of simd256, -even though this reduces frequency on some CPUs. +\[lq]frequency_level=simd128\[rq] will cause some CPUs to run at highest +frequency, which may result in higher application performance if you do +much shading. +If you application heavily uses AVX code, you should best set the +frequency level to simd256. +Per default Embree tries to avoid reducing the frequency of the CPU by +setting the simd256 level only when the CPU has no significant down +clocking. +.RE .PP Different configuration options should be separated by commas, e.g.: .IP .nf \f[C] -rtcNewDevice("threads=1,isa=avx"); -\f[] +rtcNewDevice(\[dq]threads=1,isa=avx\[dq]); +\f[R] .fi .SS EXIT STATUS .PP On success returns a handle of the created device. -On failure returns \f[C]NULL\f[] as device and sets a per\-thread error -code that can be queried using \f[C]rtcGetDeviceError(NULL)\f[]. +On failure returns \f[C]NULL\f[R] as device and sets a per\-thread error +code that can be queried using \f[C]rtcGetDeviceError(NULL)\f[R]. .SS SEE ALSO .PP [rtcRetainDevice], [rtcReleaseDevice] diff --git a/man/man3/rtcNewGeometry.3embree3 b/man/man3/rtcNewGeometry.3embree3 index 007370e158..94e4d76093 100644 --- a/man/man3/rtcNewGeometry.3embree3 +++ b/man/man3/rtcNewGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcNewGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,141 +6,144 @@ .IP .nf \f[C] -rtcNewGeometry\ \-\ creates\ a\ new\ geometry\ object -\f[] +rtcNewGeometry \- creates a new geometry object +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -enum\ RTCGeometryType +enum RTCGeometryType { -\ RTC_GEOMETRY_TYPE_TRIANGLE, -\ RTC_GEOMETRY_TYPE_QUAD, -\ RTC_GEOMETRY_TYPE_SUBDIVISION, -\ RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, -\ RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE, -\ RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, -\ RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE, -\ RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, -\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE, -\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, -\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE, -\ RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE, -\ RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, -\ RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, -\ RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, -\ RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE, -\ RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE, -\ RTC_GEOMETRY_TYPE_GRID, -\ RTC_GEOMETRY_TYPE_SPHERE_POINT, -\ RTC_GEOMETRY_TYPE_DISC_POINT, -\ RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT, -\ RTC_GEOMETRY_TYPE_USER, -\ RTC_GEOMETRY_TYPE_INSTANCE + RTC_GEOMETRY_TYPE_TRIANGLE, + RTC_GEOMETRY_TYPE_QUAD, + RTC_GEOMETRY_TYPE_SUBDIVISION, + RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, + RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE, + RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, + RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE, + RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, + RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE, + RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, + RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE, + RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE, + RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, + RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, + RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, + RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, + RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE, + RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE, + RTC_GEOMETRY_TYPE_GRID, + RTC_GEOMETRY_TYPE_SPHERE_POINT, + RTC_GEOMETRY_TYPE_DISC_POINT, + RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT, + RTC_GEOMETRY_TYPE_USER, + RTC_GEOMETRY_TYPE_INSTANCE }; -RTCGeometry\ rtcNewGeometry( -\ \ RTCDevice\ device, -\ \ enum\ RTCGeometryType\ type +RTCGeometry rtcNewGeometry( + RTCDevice device, + enum RTCGeometryType type ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP Geometries are objects that represent an array of primitives of the same type. -The \f[C]rtcNewGeometry\f[] function creates a new geometry of specified -type (\f[C]type\f[] argument) bound to the specified device -(\f[C]device\f[] argument) and returns a handle to this geometry. +The \f[C]rtcNewGeometry\f[R] function creates a new geometry of +specified type (\f[C]type\f[R] argument) bound to the specified device +(\f[C]device\f[R] argument) and returns a handle to this geometry. The geometry object is reference counted with an initial reference count of 1. The geometry handle can be released using the -\f[C]rtcReleaseGeometry\f[] API call. +\f[C]rtcReleaseGeometry\f[R] API call. .PP Supported geometry types are triangle meshes -(\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[] type), quad meshes (triangle pairs) -(\f[C]RTC_GEOMETRY_TYPE_QUAD\f[] type), Catmull\-Clark subdivision -surfaces (\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[] type), curve geometries -with different bases (\f[C]RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[], +(\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[R] type), quad meshes (triangle +pairs) (\f[C]RTC_GEOMETRY_TYPE_QUAD\f[R] type), Catmull\-Clark +subdivision surfaces (\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[R] type), +curve geometries with different bases +(\f[C]RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[R], .PD 0 .P .PD -\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE\f[], +\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE\f[R], .PD 0 .P .PD -\f[C]RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\f[] types) grid meshes -(\f[C]RTC_GEOMETRY_TYPE_GRID\f[]), point geometries -(\f[C]RTC_GEOMETRY_TYPE_SPHERE_POINT\f[], -\f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[], -\f[C]RTC_TYPE_ORIENTED_DISC_POINT\f[]), user\-defined geometries -(\f[C]RTC_GEOMETRY_TYPE_USER\f[]), and instances -(\f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[]). +\f[C]RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\f[R] types) grid meshes +(\f[C]RTC_GEOMETRY_TYPE_GRID\f[R]), point geometries +(\f[C]RTC_GEOMETRY_TYPE_SPHERE_POINT\f[R], +\f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[R], +\f[C]RTC_TYPE_ORIENTED_DISC_POINT\f[R]), user\-defined geometries +(\f[C]RTC_GEOMETRY_TYPE_USER\f[R]), and instances +(\f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[R]). .PP -The types \f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[], and -\f[C]RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\f[] will treat the curve +The types \f[C]RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE\f[R], and +\f[C]RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE\f[R] will treat the curve as a sweep surface of a varying\-radius circle swept tangentially along the curve. -The types \f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[], -\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[], and -\f[C]RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE\f[] use ray\-facing +The types \f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[R], +\f[C]RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE\f[R], and +\f[C]RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE\f[R] use ray\-facing ribbons as a faster\-to\-intersect approximation. .PP After construction, geometries are enabled by default and not attached to any scene. -Geometries can be disabled (\f[C]rtcDisableGeometry\f[] call), and -enabled again (\f[C]rtcEnableGeometry\f[] call). +Geometries can be disabled (\f[C]rtcDisableGeometry\f[R] call), and +enabled again (\f[C]rtcEnableGeometry\f[R] call). A geometry can be attached to multiple scenes using the -\f[C]rtcAttachGeometry\f[] call (or \f[C]rtcAttachGeometryByID\f[] -call), and detached using the \f[C]rtcDetachGeometry\f[] call. +\f[C]rtcAttachGeometry\f[R] call (or \f[C]rtcAttachGeometryByID\f[R] +call), and detached using the \f[C]rtcDetachGeometry\f[R] call. During attachment, a geometry ID is assigned to the geometry (or -assigned by the user when using the \f[C]rtcAttachGeometryByID\f[] +assigned by the user when using the \f[C]rtcAttachGeometryByID\f[R] call), which uniquely identifies the geometry inside that scene. This identifier is returned when primitives of the geometry are hit in later ray queries for the scene. .PP Geometries can also be modified, including their vertex and index buffers. -After modifying a buffer, \f[C]rtcUpdateGeometryBuffer\f[] must be +After modifying a buffer, \f[C]rtcUpdateGeometryBuffer\f[R] must be called to notify that the buffer got modified. .PP -The application can use the \f[C]rtcSetGeometryUserData\f[] function to +The application can use the \f[C]rtcSetGeometryUserData\f[R] function to set a user data pointer to its own geometry representation, and later -read out this pointer using the \f[C]rtcGetGeometryUserData\f[] +read out this pointer using the \f[C]rtcGetGeometryUserData\f[R] function. .PP After setting up the geometry or modifying it, -\f[C]rtcCommitGeometry\f[] must be called to finish the geometry setup. +\f[C]rtcCommitGeometry\f[R] must be called to finish the geometry setup. After committing the geometry, vertex data interpolation can be -performed using the \f[C]rtcInterpolate\f[] and \f[C]rtcInterpolateN\f[] -functions. +performed using the \f[C]rtcInterpolate\f[R] and +\f[C]rtcInterpolateN\f[R] functions. .PP A build quality can be specified for a geometry using the -\f[C]rtcSetGeometryBuildQuality\f[] function, to balance between +\f[C]rtcSetGeometryBuildQuality\f[R] function, to balance between acceleration structure build performance and ray query performance. The build quality per geometry will be used if a two\-level acceleration structure is built internally, which is the case if the -\f[C]RTC_BUILD_QUALITY_LOW\f[] is set as the scene build quality. +\f[C]RTC_BUILD_QUALITY_LOW\f[R] is set as the scene build quality. See Section [rtcSetSceneBuildQuality] for more details. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcEnableGeometry], [rtcDisableGeometry], [rtcAttachGeometry], diff --git a/man/man3/rtcNewScene.3embree3 b/man/man3/rtcNewScene.3embree3 index d9207177c3..01fc9d2397 100644 --- a/man/man3/rtcNewScene.3embree3 +++ b/man/man3/rtcNewScene.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcNewScene" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcNewScene\ \-\ creates\ a\ new\ scene -\f[] +rtcNewScene \- creates a new scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCScene\ rtcNewScene(RTCDevice\ device); -\f[] +RTCScene rtcNewScene(RTCDevice device); +\f[R] .fi .SS DESCRIPTION .PP This function creates a new scene bound to the specified device -(\f[C]device\f[] argument), and returns a handle to this scene. +(\f[C]device\f[R] argument), and returns a handle to this scene. The scene object is reference counted with an initial reference count of 1. -The scene handle can be released using the \f[C]rtcReleaseScene\f[] API +The scene handle can be released using the \f[C]rtcReleaseScene\f[R] API call. .SS EXIT STATUS .PP On success a scene handle is returned. -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcRetainScene], [rtcReleaseScene] diff --git a/man/man3/rtcNewSharedBuffer.3embree3 b/man/man3/rtcNewSharedBuffer.3embree3 index 57a395fe66..73624e1fe5 100644 --- a/man/man3/rtcNewSharedBuffer.3embree3 +++ b/man/man3/rtcNewSharedBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcNewSharedBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,32 +6,33 @@ .IP .nf \f[C] -rtcNewSharedBuffer\ \-\ creates\ a\ new\ shared\ data\ buffer -\f[] +rtcNewSharedBuffer \- creates a new shared data buffer +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -RTCBuffer\ rtcNewSharedBuffer( -\ \ RTCDevice\ device, -\ \ void*\ ptr, -\ \ size_t\ byteSize +RTCBuffer rtcNewSharedBuffer( + RTCDevice device, + void* ptr, + size_t byteSize ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcNewSharedBuffer\f[] function creates a new shared data -buffer object bound to the specified device (\f[C]device\f[] argument). +The \f[C]rtcNewSharedBuffer\f[R] function creates a new shared data +buffer object bound to the specified device (\f[C]device\f[R] argument). The buffer object is reference counted with an initial reference count of 1. -The buffer can be released using the \f[C]rtcReleaseBuffer\f[] function. +The buffer can be released using the \f[C]rtcReleaseBuffer\f[R] +function. .PP At construction time, the pointer to the user\-managed buffer data -(\f[C]ptr\f[] argument) including its size in bytes (\f[C]byteSize\f[] +(\f[C]ptr\f[R] argument) including its size in bytes (\f[C]byteSize\f[R] argument) is provided to create the buffer. At buffer construction time no buffer data is allocated, but the buffer data provided by the application is used. @@ -41,15 +42,15 @@ required. .IP .nf \f[C] -\f[] +\f[R] .fi .PP -The data pointer (\f[C]ptr\f[] argument) must be aligned to 4 bytes; -otherwise the \f[C]rtcNewSharedBuffer\f[] function will fail. +The data pointer (\f[C]ptr\f[R] argument) must be aligned to 4 bytes; +otherwise the \f[C]rtcNewSharedBuffer\f[R] function will fail. .SS EXIT STATUS .PP -On failure \f[C]NULL\f[] is returned and an error code is set that can -be queried using \f[C]rtcGetDeviceError\f[]. +On failure \f[C]NULL\f[R] is returned and an error code is set that can +be queried using \f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcRetainBuffer], [rtcReleaseBuffer] diff --git a/man/man3/rtcOccluded1.3embree3 b/man/man3/rtcOccluded1.3embree3 index 2adcf0a4fd..334c0f259d 100644 --- a/man/man3/rtcOccluded1.3embree3 +++ b/man/man3/rtcOccluded1.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcOccluded1" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,60 +6,61 @@ .IP .nf \f[C] -rtcOccluded1\ \-\ finds\ any\ hit\ for\ a\ single\ ray -\f[] +rtcOccluded1 \- finds any hit for a single ray +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcOccluded1( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRay*\ ray +void rtcOccluded1( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRay* ray ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcOccluded1\f[] function checks for a single ray (\f[C]ray\f[] -argument) whether there is any hit with the scene (\f[C]scene\f[] -argument). +The \f[C]rtcOccluded1\f[R] function checks for a single ray +(\f[C]ray\f[R] argument) whether there is any hit with the scene +(\f[C]scene\f[R] argument). .PP -The user must initialize the ray origin (\f[C]org\f[] ray member), ray -direction (\f[C]dir\f[] ray member), ray segment (\f[C]tnear\f[], -\f[C]tfar\f[] ray members), and must set the ray flags to \f[C]0\f[] -(\f[C]flags\f[] ray member). +The user must initialize the ray origin (\f[C]org\f[R] ray member), ray +direction (\f[C]dir\f[R] ray member), ray segment (\f[C]tnear\f[R], +\f[C]tfar\f[R] ray members), and must set the ray flags to \f[C]0\f[R] +(\f[C]flags\f[R] ray member). If the scene contains motion blur geometries, also the ray time -(\f[C]time\f[] ray member) must be initialized to a value in the range -[0, 1]. -If ray masks are enabled at compile time, the ray mask (\f[C]mask\f[] +(\f[C]time\f[R] ray member) must be initialized to a value in the range +[0,\[u2006]1]. +If ray masks are enabled at compile time, the ray mask (\f[C]mask\f[R] ray member) must be initialized as well. -The ray segment must be in the range [0, ∞], thus ranges that start -behind the ray origin are not valid, but ranges can reach to infinity. +The ray segment must be in the range [0,\[u2006]\[if]], thus ranges that +start behind the ray origin are not valid, but ranges can reach to +infinity. See Section [RTCRay] for the ray layout description. .PP When no intersection is found, the ray data is not updated. -In case a hit was found, the \f[C]tfar\f[] component of the ray is set -to \f[C]\-inf\f[]. +In case a hit was found, the \f[C]tfar\f[R] component of the ray is set +to \f[C]\-inf\f[R]. .PP The implementation makes no guarantees that primitives whose hit -distance is exactly at (or very close to) \f[C]tnear\f[] or -\f[C]tfar\f[] are hit or missed. -If you want to exclude intersections at \f[C]tnear\f[] just pass a -slightly enlarged \f[C]tnear\f[], and if you want to include -intersections at \f[C]tfar\f[] pass a slightly enlarged \f[C]tfar\f[]. +distance is exactly at (or very close to) \f[C]tnear\f[R] or +\f[C]tfar\f[R] are hit or missed. +If you want to exclude intersections at \f[C]tnear\f[R] just pass a +slightly enlarged \f[C]tnear\f[R], and if you want to include +intersections at \f[C]tfar\f[R] pass a slightly enlarged \f[C]tfar\f[R]. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP The ray must be aligned to 16 bytes. diff --git a/man/man3/rtcOccluded1M.3embree3 b/man/man3/rtcOccluded1M.3embree3 index f477959f6f..380a7d4528 100644 --- a/man/man3/rtcOccluded1M.3embree3 +++ b/man/man3/rtcOccluded1M.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcOccluded1M" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,48 +6,48 @@ .IP .nf \f[C] -rtcOccluded1M\ \-\ finds\ any\ hits\ for\ a\ stream\ of\ M\ single\ rays -\f[] +rtcOccluded1M \- finds any hits for a stream of M single rays +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcOccluded1M( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRay*\ ray, -\ \ unsigned\ int\ M, -\ \ size_t\ byteStride +void rtcOccluded1M( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRay* ray, + unsigned int M, + size_t byteStride ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcOccluded1M\f[] function checks whether there are any hits -for a stream of \f[C]M\f[] single rays (\f[C]ray\f[] argument) with the -scene (\f[C]scene\f[] argument). -The \f[C]ray\f[] argument points to an array of rays with specified byte -stride (\f[C]byteStride\f[] argument) between the rays. +The \f[C]rtcOccluded1M\f[R] function checks whether there are any hits +for a stream of \f[C]M\f[R] single rays (\f[C]ray\f[R] argument) with +the scene (\f[C]scene\f[R] argument). +The \f[C]ray\f[R] argument points to an array of rays with specified +byte stride (\f[C]byteStride\f[R] argument) between the rays. See Section [rtcOccluded1] for a description of how to set up and trace occlusion rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The stream size \f[C]M\f[] can be an arbitrary positive integer +The stream size \f[C]M\f[R] can be an arbitrary positive integer including 0. Each ray must be aligned to 16 bytes. .SS EXIT STATUS diff --git a/man/man3/rtcOccluded1Mp.3embree3 b/man/man3/rtcOccluded1Mp.3embree3 index ae1995f47c..6f1481bfd3 100644 --- a/man/man3/rtcOccluded1Mp.3embree3 +++ b/man/man3/rtcOccluded1Mp.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcOccluded1Mp" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,47 +6,47 @@ .IP .nf \f[C] -rtcOccluded1Mp\ \-\ find\ any\ hits\ for\ a\ stream\ of\ M\ pointers\ to -\ \ single\ rays -\f[] +rtcOccluded1Mp \- find any hits for a stream of M pointers to + single rays +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcOccluded1M( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRay**\ ray, -\ \ unsigned\ int\ M +void rtcOccluded1M( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRay** ray, + unsigned int M ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcOccluded1Mp\f[] function checks whether there are any hits -for a stream of \f[C]M\f[] single rays (\f[C]ray\f[] argument) with the -scene (\f[C]scene\f[] argument). -The \f[C]ray\f[] argument points to an array of pointers to rays. +The \f[C]rtcOccluded1Mp\f[R] function checks whether there are any hits +for a stream of \f[C]M\f[R] single rays (\f[C]ray\f[R] argument) with +the scene (\f[C]scene\f[R] argument). +The \f[C]ray\f[R] argument points to an array of pointers to rays. Section [rtcOccluded1] for a description of how to set up and trace a occlusion rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The stream size \f[C]M\f[] can be an arbitrary positive integer +The stream size \f[C]M\f[R] can be an arbitrary positive integer including 0. Each ray must be aligned to 16 bytes. .SS EXIT STATUS diff --git a/man/man3/rtcOccluded4.3embree3 b/man/man3/rtcOccluded4.3embree3 index f71416147e..8eff0e92d8 100644 --- a/man/man3/rtcOccluded4.3embree3 +++ b/man/man3/rtcOccluded4.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcOccluded4/8/16" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,79 +6,79 @@ .IP .nf \f[C] -rtcOccluded4/8/16\ \-\ finds\ any\ hits\ for\ a\ ray\ packet -\f[] +rtcOccluded4/8/16 \- finds any hits for a ray packet +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcOccluded4( -\ \ const\ int*\ valid, -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRay4*\ ray +void rtcOccluded4( + const int* valid, + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRay4* ray ); -void\ rtcOccluded8( -\ \ const\ int*\ valid, -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRay8*\ ray +void rtcOccluded8( + const int* valid, + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRay8* ray ); -void\ rtcOccluded16( -\ \ const\ int*\ valid, -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRay16*\ ray +void rtcOccluded16( + const int* valid, + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRay16* ray ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcOccluded4/8/16\f[] functions checks for each active ray of -the ray packet of size 4, 8, or 16 (\f[C]ray\f[] argument) whether there -is any hit with the scene (\f[C]scene\f[] argument). +The \f[C]rtcOccluded4/8/16\f[R] functions checks for each active ray of +the ray packet of size 4, 8, or 16 (\f[C]ray\f[R] argument) whether +there is any hit with the scene (\f[C]scene\f[R] argument). See Section [rtcOccluded1] for a description of how to set up and trace occlusion rays. .PP -A ray valid mask must be provided (\f[C]valid\f[] argument) which stores -one 32\-bit integer (\f[C]\-1\f[] means valid and \f[C]0\f[] invalid) -per ray in the packet. +A ray valid mask must be provided (\f[C]valid\f[R] argument) which +stores one 32\-bit integer (\f[C]\-1\f[R] means valid and \f[C]0\f[R] +invalid) per ray in the packet. Only active rays are processed, and hit data of inactive rays is not changed. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP The implementation of these functions is guaranteed to invoke callback functions always with the same ray packet size and ordering of rays as specified initially. .PP -For \f[C]rtcOccluded4\f[] the ray packet must be aligned to 16 bytes, -for \f[C]rtcOccluded8\f[] the alignment must be 32 bytes, and for -\f[C]rtcOccluded16\f[] the alignment must be 64 bytes. +For \f[C]rtcOccluded4\f[R] the ray packet must be aligned to 16 bytes, +for \f[C]rtcOccluded8\f[R] the alignment must be 32 bytes, and for +\f[C]rtcOccluded16\f[R] the alignment must be 64 bytes. .PP -The \f[C]rtcOccluded4\f[], \f[C]rtcOccluded8\f[] and -\f[C]rtcOccluded16\f[] functions may change the ray packet size and ray +The \f[C]rtcOccluded4\f[R], \f[C]rtcOccluded8\f[R] and +\f[C]rtcOccluded16\f[R] functions may change the ray packet size and ray order when calling back into intersect filter functions or user geometry callbacks. Under some conditions the application can assume packets to stay intakt, which can determined by querying the -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[], -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[], -\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[] properties through -the \f[C]rtcGetDeviceProperty\f[] function. +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED\f[R], +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED\f[R], +\f[C]RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED\f[R] properties through +the \f[C]rtcGetDeviceProperty\f[R] function. See [rtcGetDeviceProperty] for more information. .SS EXIT STATUS .PP diff --git a/man/man3/rtcOccludedNM.3embree3 b/man/man3/rtcOccludedNM.3embree3 index ac2ead2a86..d9ba449017 100644 --- a/man/man3/rtcOccludedNM.3embree3 +++ b/man/man3/rtcOccludedNM.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcOccludedNM" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,52 +6,52 @@ .IP .nf \f[C] -rtcOccludedNM\ \-\ finds\ any\ hits\ for\ a\ stream\ of\ M\ ray\ packets\ of -\ \ size\ N -\f[] +rtcOccludedNM \- finds any hits for a stream of M ray packets of + size N +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcOccludedNM( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayN*\ ray, -\ \ unsigned\ int\ N, -\ \ unsigned\ int\ M, -\ \ size_t\ byteStride +void rtcOccludedNM( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayN* ray, + unsigned int N, + unsigned int M, + size_t byteStride ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcOccludedNM\f[] function checks whether there are any hits -for a stream of \f[C]M\f[] ray packets (\f[C]ray\f[] argument) of size -\f[C]N\f[] with the scene (\f[C]scene\f[] argument). -The \f[C]ray\f[] argument points to an array of ray packets with -specified byte stride (\f[C]byteStride\f[] argument) between the ray +The \f[C]rtcOccludedNM\f[R] function checks whether there are any hits +for a stream of \f[C]M\f[R] ray packets (\f[C]ray\f[R] argument) of size +\f[C]N\f[R] with the scene (\f[C]scene\f[R] argument). +The \f[C]ray\f[R] argument points to an array of ray packets with +specified byte stride (\f[C]byteStride\f[R] argument) between the ray packets. See Section [rtcOccluded1] for a description of how to set up and trace occlusion rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The packet size \f[C]N\f[] must be larger than 0, and the stream size -\f[C]M\f[] can be an arbitrary positive integer including 0. +The packet size \f[C]N\f[R] must be larger than 0, and the stream size +\f[C]M\f[R] can be an arbitrary positive integer including 0. Each ray must be aligned to 16 bytes. .SS EXIT STATUS .PP diff --git a/man/man3/rtcOccludedNp.3embree3 b/man/man3/rtcOccludedNp.3embree3 index 09e4005dde..027b944813 100644 --- a/man/man3/rtcOccludedNp.3embree3 +++ b/man/man3/rtcOccludedNp.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcOccludedNp" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,29 +6,30 @@ .IP .nf \f[C] -rtcOccludedNp\ \-\ finds\ any\ hits\ for\ a\ SOA\ ray\ stream\ of\ size\ N -\f[] +rtcOccludedNp \- finds any hits for a SOA ray stream of size N +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcOccludedNp( -\ \ RTCScene\ scene, -\ \ struct\ RTCIntersectContext*\ context, -\ \ struct\ RTCRayNp*\ ray, -\ \ unsigned\ int\ N +void rtcOccludedNp( + RTCScene scene, + struct RTCIntersectContext* context, + struct RTCRayNp* ray, + unsigned int N ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcOccludedNp\f[] function checks whether there are any hits -for a SOA ray stream (\f[C]ray\f[] argument) of size \f[C]N\f[] -(basically a large ray packet) with the scene (\f[C]scene\f[] argument). -The \f[C]ray\f[] argument points to a structure of pointers with one +The \f[C]rtcOccludedNp\f[R] function checks whether there are any hits +for a SOA ray stream (\f[C]ray\f[R] argument) of size \f[C]N\f[R] +(basically a large ray packet) with the scene (\f[C]scene\f[R] +argument). +The \f[C]ray\f[R] argument points to a structure of pointers with one pointer for each ray component. Each of these pointers points to an array with the ray component data for each ray. @@ -40,18 +41,18 @@ occlusion rays. .IP .nf \f[C] -\f[] +\f[R] .fi .IP .nf \f[C] -\f[] +\f[R] .fi .PP -A ray in a ray stream is considered inactive if its \f[C]tnear\f[] value -is larger than its \f[C]tfar\f[] value. +A ray in a ray stream is considered inactive if its \f[C]tnear\f[R] +value is larger than its \f[C]tfar\f[R] value. .PP -The stream size \f[C]N\f[] can be an arbitrary positive integer +The stream size \f[C]N\f[R] can be an arbitrary positive integer including 0. Each ray component array must be aligned to 16 bytes. .SS EXIT STATUS diff --git a/man/man3/rtcPointQuery.3embree3 b/man/man3/rtcPointQuery.3embree3 index c831d33a87..6242d7aa7a 100644 --- a/man/man3/rtcPointQuery.3embree3 +++ b/man/man3/rtcPointQuery.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcPointQuery" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,74 +6,73 @@ .IP .nf \f[C] -rtcPointQuery\ \-\ traverses\ the\ BVH\ with\ a\ point\ query\ object -\f[] +rtcPointQuery \- traverses the BVH with a point query object +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTC_ALIGN(16)\ RTCPointQuery +struct RTC_ALIGN(16) RTCPointQuery { -\ \ //\ location\ of\ the\ query -\ \ float\ x; -\ \ float\ y; -\ \ float\ z; + // location of the query + float x; + float y; + float z; -\ \ //\ radius\ and\ time\ of\ the\ query -\ \ float\ radius; -\ \ float\ time; + // radius and time of the query + float radius; + float time; }; -void\ rtcPointQuery( -\ \ RTCScene\ scene, -\ \ struct\ RTCPointQuery*\ query, -\ \ struct\ RTCPointQueryContext*\ context, -\ \ struct\ RTCPointQueryFunction*\ queryFunc, -\ \ void*\ userPtr +void rtcPointQuery( + RTCScene scene, + struct RTCPointQuery* query, + struct RTCPointQueryContext* context, + struct RTCPointQueryFunction* queryFunc, + void* userPtr ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcPointQuery\f[] function traverses the BVH using a -\f[C]RTCPointQuery\f[] object (\f[C]query\f[] argument) and calls a user -defined callback function (e.g \f[C]queryFunc\f[] argument) for each -primitive of the scene (\f[C]scene\f[] argument) that intersects the -query domain. +The \f[C]rtcPointQuery\f[R] function traverses the BVH using a +\f[C]RTCPointQuery\f[R] object (\f[C]query\f[R] argument) and calls a +user defined callback function (e.g \f[C]queryFunc\f[R] argument) for +each primitive of the scene (\f[C]scene\f[R] argument) that intersects +the query domain. .PP -The user has to initialize the query location (\f[C]x\f[], \f[C]y\f[] -and \f[C]z\f[] member) and query radius in the range [0, ∞]. +The user has to initialize the query location (\f[C]x\f[R], \f[C]y\f[R] +and \f[C]z\f[R] member) and query radius in the range [0,\[u2006]\[if]]. If the scene contains motion blur geometries, also the query time -(\f[C]time\f[] member) must be initialized to a value in the range -[0, 1]. +(\f[C]time\f[R] member) must be initialized to a value in the range +[0,\[u2006]1]. .PP -Further, a \f[C]RTCPointQueryContext\f[] (\f[C]context\f[] argument) +Further, a \f[C]RTCPointQueryContext\f[R] (\f[C]context\f[R] argument) must be created and initialized. It contains ID and transformation information of the instancing hierarchy if (multilevel\-)instancing is used. See [rtcInitPointQueryContext] for further information. .PP For every primitive that intersects the query domain, the callback -function (\f[C]queryFunc\f[] argument) is called, in which distance +function (\f[C]queryFunc\f[R] argument) is called, in which distance computations to the primitive can be implemented. The user will be provided with the primID and geomID of the according primitive, however, the geometry information (e.g. triangle index and vertex data) has to be determined manually. -The \f[C]userPtr\f[] argument can be used to input geometry data of the -scene or output results of the point query (e.g. -closest point currently found on surface geometry (see tutorial -[ClosestPoint])). +The \f[C]userPtr\f[R] argument can be used to input geometry data of the +scene or output results of the point query (e.g.\ closest point +currently found on surface geometry (see tutorial [ClosestPoint])). .PP -The parameter \f[C]queryFunc\f[] is optional and can be NULL, in which +The parameter \f[C]queryFunc\f[R] is optional and can be NULL, in which case the callback function is not invoked. However, a callback function can still get attached to a specific -\f[C]RTCGeometry\f[] object using [rtcSetGeometryPointQueryFunction]. +\f[C]RTCGeometry\f[R] object using [rtcSetGeometryPointQueryFunction]. If a callback function is attached to a geometry and (a potentially different) callback function is passed as an argument to -\f[C]rtcPointQuery\f[], both functions are called for the primitives of +\f[C]rtcPointQuery\f[R], both functions are called for the primitives of the according geometries. .PP The query radius can be decreased inside the callback function, which @@ -91,7 +90,7 @@ anisotropic scaling or sheering. In these cases distance computations have to be performed in world space to ensure correctness and the ellipsoidal query domain (in instance space) will be approximated with its axis aligned bounding box -interally. +internally. Therefore, the callback function might be invoked even for primitives in inner BVH nodes that do not intersect the query domain. See [rtcSetGeometryPointQueryFunction] for details. @@ -99,7 +98,7 @@ See [rtcSetGeometryPointQueryFunction] for details. The point query structure must be aligned to 16 bytes. .SS SUPPORTED PRIMITIVES .PP -Currenly, all primitive types are supported by the point query API +Currently, all primitive types are supported by the point query API except of points (see [RTC_GEOMETRY_TYPE_POINT]), curves (see [RTC_GEOMETRY_TYPE_CURVE]) and sudivision surfaces (see [RTC_GEOMETRY_SUBDIVISION]). diff --git a/man/man3/rtcPointQuery4.3embree3 b/man/man3/rtcPointQuery4.3embree3 index fe9fcfa300..d86a537ab3 100644 --- a/man/man3/rtcPointQuery4.3embree3 +++ b/man/man3/rtcPointQuery4.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcPointQuery" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,12 +6,12 @@ .IP .nf \f[C] -rtcPointQuery4/8/16\ \-\ traverses\ the\ BVH\ with\ a\ point\ query\ object\ for\ a\ ray\ packet -\f[] +rtcPointQuery4/8/16 \- traverses the BVH with a point query object for a ray packet +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcPointQuery4/8/16\f[] function unrolls the ray packet +The \f[C]rtcPointQuery4/8/16\f[R] function unrolls the ray packet internally and calls [rtcPointQuery]. .SS SEE ALSO .PP diff --git a/man/man3/rtcReleaseBVH.3embree3 b/man/man3/rtcReleaseBVH.3embree3 index e3329733b0..8ea7f506ba 100644 --- a/man/man3/rtcReleaseBVH.3embree3 +++ b/man/man3/rtcReleaseBVH.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcReleaseBVH" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,28 +6,28 @@ .IP .nf \f[C] -rtcReleaseBVH\ \-\ decrements\ the\ BVH\ reference\ count -\f[] +rtcReleaseBVH \- decrements the BVH reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcReleaseBVH(RTCBVH\ bvh); -\f[] +void rtcReleaseBVH(RTCBVH bvh); +\f[R] .fi .SS DESCRIPTION .PP BVH objects are reference counted. -The \f[C]rtcReleaseBVH\f[] function decrements the reference count of -the passed BVH object (\f[C]bvh\f[] argument). +The \f[C]rtcReleaseBVH\f[R] function decrements the reference count of +the passed BVH object (\f[C]bvh\f[R] argument). When the reference count falls to 0, the BVH gets destroyed. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewBVH], [rtcRetainBVH] diff --git a/man/man3/rtcReleaseBuffer.3embree3 b/man/man3/rtcReleaseBuffer.3embree3 index 44b0ef6a32..1acc94db71 100644 --- a/man/man3/rtcReleaseBuffer.3embree3 +++ b/man/man3/rtcReleaseBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcReleaseBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,28 +6,28 @@ .IP .nf \f[C] -rtcReleaseBuffer\ \-\ decrements\ the\ buffer\ reference\ count -\f[] +rtcReleaseBuffer \- decrements the buffer reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcReleaseBuffer(RTCBuffer\ buffer); -\f[] +void rtcReleaseBuffer(RTCBuffer buffer); +\f[R] .fi .SS DESCRIPTION .PP Buffer objects are reference counted. -The \f[C]rtcReleaseBuffer\f[] function decrements the reference count of -the passed buffer object (\f[C]buffer\f[] argument). +The \f[C]rtcReleaseBuffer\f[R] function decrements the reference count +of the passed buffer object (\f[C]buffer\f[R] argument). When the reference count falls to 0, the buffer gets destroyed. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewBuffer], [rtcRetainBuffer] diff --git a/man/man3/rtcReleaseDevice.3embree3 b/man/man3/rtcReleaseDevice.3embree3 index eb2099b88a..4841b52bc5 100644 --- a/man/man3/rtcReleaseDevice.3embree3 +++ b/man/man3/rtcReleaseDevice.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcReleaseDevice" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,23 +6,23 @@ .IP .nf \f[C] -rtcReleaseDevice\ \-\ decrements\ the\ device\ reference\ count -\f[] +rtcReleaseDevice \- decrements the device reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcReleaseDevice(RTCDevice\ device); -\f[] +void rtcReleaseDevice(RTCDevice device); +\f[R] .fi .SS DESCRIPTION .PP Device objects are reference counted. -The \f[C]rtcReleaseDevice\f[] function decrements the reference count of -the passed device object (\f[C]device\f[] argument). +The \f[C]rtcReleaseDevice\f[R] function decrements the reference count +of the passed device object (\f[C]device\f[R] argument). When the reference count falls to 0, the device gets destroyed. .PP All objects created from the device (like scenes, geometries, etc.) hold @@ -31,7 +31,7 @@ these objects are destroyed first. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewDevice], [rtcRetainDevice] diff --git a/man/man3/rtcReleaseGeometry.3embree3 b/man/man3/rtcReleaseGeometry.3embree3 index 79248775be..bde3c98a3b 100644 --- a/man/man3/rtcReleaseGeometry.3embree3 +++ b/man/man3/rtcReleaseGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcReleaseGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,28 +6,28 @@ .IP .nf \f[C] -rtcReleaseGeometry\ \-\ decrements\ the\ geometry\ reference\ count -\f[] +rtcReleaseGeometry \- decrements the geometry reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcReleaseGeometry(RTCGeometry\ geometry); -\f[] +void rtcReleaseGeometry(RTCGeometry geometry); +\f[R] .fi .SS DESCRIPTION .PP Geometry objects are reference counted. -The \f[C]rtcReleaseGeometry\f[] function decrements the reference count -of the passed geometry object (\f[C]geometry\f[] argument). +The \f[C]rtcReleaseGeometry\f[R] function decrements the reference count +of the passed geometry object (\f[C]geometry\f[R] argument). When the reference count falls to 0, the geometry gets destroyed. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcRetainGeometry] diff --git a/man/man3/rtcReleaseScene.3embree3 b/man/man3/rtcReleaseScene.3embree3 index 036901ea78..fea4cf6ab6 100644 --- a/man/man3/rtcReleaseScene.3embree3 +++ b/man/man3/rtcReleaseScene.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcReleaseScene" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,23 +6,23 @@ .IP .nf \f[C] -rtcReleaseScene\ \-\ decrements\ the\ scene\ reference\ count -\f[] +rtcReleaseScene \- decrements the scene reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcReleaseScene(RTCScene\ scene); -\f[] +void rtcReleaseScene(RTCScene scene); +\f[R] .fi .SS DESCRIPTION .PP Scene objects are reference counted. -The \f[C]rtcReleaseScene\f[] function decrements the reference count of -the passed scene object (\f[C]scene\f[] argument). +The \f[C]rtcReleaseScene\f[R] function decrements the reference count of +the passed scene object (\f[C]scene\f[R] argument). When the reference count falls to 0, the scene gets destroyed. .PP The scene holds a reference to all attached geometries, thus if the @@ -31,7 +31,7 @@ count decremented. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewScene], [rtcRetainScene] diff --git a/man/man3/rtcRetainBVH.3embree3 b/man/man3/rtcRetainBVH.3embree3 index 10ea6f76db..a20ba46b6d 100644 --- a/man/man3/rtcRetainBVH.3embree3 +++ b/man/man3/rtcRetainBVH.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcRetainBVH" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcRetainBVH\ \-\ increments\ the\ BVH\ reference\ count -\f[] +rtcRetainBVH \- increments the BVH reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcRetainBVH(RTCBVH\ bvh); -\f[] +void rtcRetainBVH(RTCBVH bvh); +\f[R] .fi .SS DESCRIPTION .PP BVH objects are reference counted. -The \f[C]rtcRetainBVH\f[] function increments the reference count of the -passed BVH object (\f[C]bvh\f[] argument). -This function together with \f[C]rtcReleaseBVH\f[] allows to use the +The \f[C]rtcRetainBVH\f[R] function increments the reference count of +the passed BVH object (\f[C]bvh\f[R] argument). +This function together with \f[C]rtcReleaseBVH\f[R] allows to use the internal reference counting in a C++ wrapper class to handle the ownership of the object. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewBVH], [rtcReleaseBVH] diff --git a/man/man3/rtcRetainBuffer.3embree3 b/man/man3/rtcRetainBuffer.3embree3 index cfd73aa521..0e35bb7448 100644 --- a/man/man3/rtcRetainBuffer.3embree3 +++ b/man/man3/rtcRetainBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcRetainBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcRetainBuffer\ \-\ increments\ the\ buffer\ reference\ count -\f[] +rtcRetainBuffer \- increments the buffer reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcRetainBuffer(RTCBuffer\ buffer); -\f[] +void rtcRetainBuffer(RTCBuffer buffer); +\f[R] .fi .SS DESCRIPTION .PP Buffer objects are reference counted. -The \f[C]rtcRetainBuffer\f[] function increments the reference count of -the passed buffer object (\f[C]buffer\f[] argument). -This function together with \f[C]rtcReleaseBuffer\f[] allows to use the +The \f[C]rtcRetainBuffer\f[R] function increments the reference count of +the passed buffer object (\f[C]buffer\f[R] argument). +This function together with \f[C]rtcReleaseBuffer\f[R] allows to use the internal reference counting in a C++ wrapper class to handle the ownership of the object. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewBuffer], [rtcReleaseBuffer] diff --git a/man/man3/rtcRetainDevice.3embree3 b/man/man3/rtcRetainDevice.3embree3 index 672d54b94e..3c4c247eed 100644 --- a/man/man3/rtcRetainDevice.3embree3 +++ b/man/man3/rtcRetainDevice.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcRetainDevice" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcRetainDevice\ \-\ increments\ the\ device\ reference\ count -\f[] +rtcRetainDevice \- increments the device reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcRetainDevice(RTCDevice\ device); -\f[] +void rtcRetainDevice(RTCDevice device); +\f[R] .fi .SS DESCRIPTION .PP Device objects are reference counted. -The \f[C]rtcRetainDevice\f[] function increments the reference count of -the passed device object (\f[C]device\f[] argument). -This function together with \f[C]rtcReleaseDevice\f[] allows to use the +The \f[C]rtcRetainDevice\f[R] function increments the reference count of +the passed device object (\f[C]device\f[R] argument). +This function together with \f[C]rtcReleaseDevice\f[R] allows to use the internal reference counting in a C++ wrapper class to manage the ownership of the object. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewDevice], [rtcReleaseDevice] diff --git a/man/man3/rtcRetainGeometry.3embree3 b/man/man3/rtcRetainGeometry.3embree3 index f8c7096867..1fa9656535 100644 --- a/man/man3/rtcRetainGeometry.3embree3 +++ b/man/man3/rtcRetainGeometry.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcRetainGeometry" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcRetainGeometry\ \-\ increments\ the\ geometry\ reference\ count -\f[] +rtcRetainGeometry \- increments the geometry reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcRetainGeometry(RTCGeometry\ geometry); -\f[] +void rtcRetainGeometry(RTCGeometry geometry); +\f[R] .fi .SS DESCRIPTION .PP Geometry objects are reference counted. -The \f[C]rtcRetainGeometry\f[] function increments the reference count -of the passed geometry object (\f[C]geometry\f[] argument). -This function together with \f[C]rtcReleaseGeometry\f[] allows to use +The \f[C]rtcRetainGeometry\f[R] function increments the reference count +of the passed geometry object (\f[C]geometry\f[R] argument). +This function together with \f[C]rtcReleaseGeometry\f[R] allows to use the internal reference counting in a C++ wrapper class to handle the ownership of the object. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcReleaseGeometry] diff --git a/man/man3/rtcRetainScene.3embree3 b/man/man3/rtcRetainScene.3embree3 index 8def63a1a2..f73b1b08df 100644 --- a/man/man3/rtcRetainScene.3embree3 +++ b/man/man3/rtcRetainScene.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcRetainScene" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcRetainScene\ \-\ increments\ the\ scene\ reference\ count -\f[] +rtcRetainScene \- increments the scene reference count +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcRetainScene(RTCScene\ scene); -\f[] +void rtcRetainScene(RTCScene scene); +\f[R] .fi .SS DESCRIPTION .PP Scene objects are reference counted. -The \f[C]rtcRetainScene\f[] function increments the reference count of -the passed scene object (\f[C]scene\f[] argument). -This function together with \f[C]rtcReleaseScene\f[] allows to use the +The \f[C]rtcRetainScene\f[R] function increments the reference count of +the passed scene object (\f[C]scene\f[R] argument). +This function together with \f[C]rtcReleaseScene\f[R] allows to use the internal reference counting in a C++ wrapper class to handle the ownership of the object. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewScene], [rtcReleaseScene] diff --git a/man/man3/rtcSetDeviceErrorFunction.3embree3 b/man/man3/rtcSetDeviceErrorFunction.3embree3 index 45a764293f..a47ea4ec88 100644 --- a/man/man3/rtcSetDeviceErrorFunction.3embree3 +++ b/man/man3/rtcSetDeviceErrorFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetDeviceErrorFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,51 +6,51 @@ .IP .nf \f[C] -rtcSetDeviceErrorFunction\ \-\ sets\ an\ error\ callback\ function\ for\ the\ device -\f[] +rtcSetDeviceErrorFunction \- sets an error callback function for the device +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -typedef\ void\ (*RTCErrorFunction)( -\ \ void*\ userPtr, -\ \ RTCError\ code, -\ \ const\ char*\ str +typedef void (*RTCErrorFunction)( + void* userPtr, + RTCError code, + const char* str ); -void\ rtcSetDeviceErrorFunction( -\ \ RTCDevice\ device, -\ \ RTCErrorFunction\ error, -\ \ void*\ userPtr +void rtcSetDeviceErrorFunction( + RTCDevice device, + RTCErrorFunction error, + void* userPtr ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -Using the \f[C]rtcSetDeviceErrorFunction\f[] call, it is possible to set -a callback function (\f[C]error\f[] argument) with payload -(\f[C]userPtr\f[] argument), which is called whenever an error occurs -for the specified device (\f[C]device\f[] argument). +Using the \f[C]rtcSetDeviceErrorFunction\f[R] call, it is possible to +set a callback function (\f[C]error\f[R] argument) with payload +(\f[C]userPtr\f[R] argument), which is called whenever an error occurs +for the specified device (\f[C]device\f[R] argument). .PP Only a single callback function can be registered per device, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP When the registered callback function is invoked, it gets passed the -user\-defined payload (\f[C]userPtr\f[] argument as specified at -registration time), the error code (\f[C]code\f[] argument) of the -occurred error, as well as a string (\f[C]str\f[] argument) that further -describes the error. +user\-defined payload (\f[C]userPtr\f[R] argument as specified at +registration time), the error code (\f[C]code\f[R] argument) of the +occurred error, as well as a string (\f[C]str\f[R] argument) that +further describes the error. .PP The error code is also set if an error callback function is registered. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetDeviceError] diff --git a/man/man3/rtcSetDeviceMemoryMonitorFunction.3embree3 b/man/man3/rtcSetDeviceMemoryMonitorFunction.3embree3 index 493f265cbc..45f3cf9ce8 100644 --- a/man/man3/rtcSetDeviceMemoryMonitorFunction.3embree3 +++ b/man/man3/rtcSetDeviceMemoryMonitorFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetDeviceMemoryMonitorFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,35 +6,35 @@ .IP .nf \f[C] -rtcSetDeviceMemoryMonitorFunction\ \-\ registers\ a\ callback\ function -\ \ to\ track\ memory\ consumption -\f[] +rtcSetDeviceMemoryMonitorFunction \- registers a callback function + to track memory consumption +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -typedef\ bool\ (*RTCMemoryMonitorFunction)( -\ \ void*\ userPtr, -\ \ ssize_t\ bytes, -\ \ bool\ post +typedef bool (*RTCMemoryMonitorFunction)( + void* userPtr, + ssize_t bytes, + bool post ); -void\ rtcSetDeviceMemoryMonitorFunction( -\ \ RTCDevice\ device, -\ \ RTCMemoryMonitorFunction\ memoryMonitor, -\ \ void*\ userPtr +void rtcSetDeviceMemoryMonitorFunction( + RTCDevice device, + RTCMemoryMonitorFunction memoryMonitor, + void* userPtr ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -Using the \f[C]rtcSetDeviceMemoryMonitorFunction\f[] call, it is -possible to register a callback function (\f[C]memoryMonitor\f[] -argument) with payload (\f[C]userPtr\f[] argument) for a device -(\f[C]device\f[] argument), which is called whenever internal memory is +Using the \f[C]rtcSetDeviceMemoryMonitorFunction\f[R] call, it is +possible to register a callback function (\f[C]memoryMonitor\f[R] +argument) with payload (\f[C]userPtr\f[R] argument) for a device +(\f[C]device\f[R] argument), which is called whenever internal memory is allocated or deallocated by objects of that device. Using this memory monitor callback mechanism, the application can track the memory consumption of an Embree device, and optionally terminate API @@ -42,44 +42,44 @@ calls that consume too much memory. .PP Only a single callback function can be registered per device, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP Once registered, the Embree device will invoke the memory monitor callback function before or after it allocates or frees important memory blocks. The callback function gets passed the payload as specified at -registration time (\f[C]userPtr\f[] argument), the number of bytes -allocated or deallocated (\f[C]bytes\f[] argument), and whether the +registration time (\f[C]userPtr\f[R] argument), the number of bytes +allocated or deallocated (\f[C]bytes\f[R] argument), and whether the callback is invoked after the allocation or deallocation took place -(\f[C]post\f[] argument). +(\f[C]post\f[R] argument). The callback function might get called from multiple threads concurrently. .PP The application can track the current memory usage of the Embree device -by atomically accumulating the \f[C]bytes\f[] input parameter provided +by atomically accumulating the \f[C]bytes\f[R] input parameter provided to the callback function. This parameter will be >0 for allocations and <0 for deallocations. .PP -Embree will continue its operation normally when returning \f[C]true\f[] -from the callback function. -If \f[C]false\f[] is returned, Embree will cancel the current operation -with the \f[C]RTC_ERROR_OUT_OF_MEMORY\f[] error code. +Embree will continue its operation normally when returning +\f[C]true\f[R] from the callback function. +If \f[C]false\f[R] is returned, Embree will cancel the current operation +with the \f[C]RTC_ERROR_OUT_OF_MEMORY\f[R] error code. Issuing multiple cancel requests from different threads is allowed. Canceling will only happen when the callback was called for allocations (bytes > 0), otherwise the cancel request will be ignored. .PP If a callback to cancel was invoked before the allocation happens -(\f[C]post\ ==\ false\f[]), then the \f[C]bytes\f[] parameter should not +(\f[C]post == false\f[R]), then the \f[C]bytes\f[R] parameter should not be accumulated, as the allocation will never happen. If the callback to cancel was invoked after the allocation happened -(\f[C]post\ ==\ true\f[]), then the \f[C]bytes\f[] parameter should be +(\f[C]post == true\f[R]), then the \f[C]bytes\f[R] parameter should be accumulated, as the allocation properly happened and a deallocation will later free that data block. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewDevice] diff --git a/man/man3/rtcSetGeometryBoundsFunction.3embree3 b/man/man3/rtcSetGeometryBoundsFunction.3embree3 index d9bcd231b1..e3b7266a04 100644 --- a/man/man3/rtcSetGeometryBoundsFunction.3embree3 +++ b/man/man3/rtcSetGeometryBoundsFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryBoundsFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,70 +6,70 @@ .IP .nf \f[C] -rtcSetGeometryBoundsFunction\ \-\ sets\ a\ callback\ to\ query\ the -\ \ bounding\ box\ of\ user\-defined\ primitives -\f[] +rtcSetGeometryBoundsFunction \- sets a callback to query the + bounding box of user\-defined primitives +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCBoundsFunctionArguments +struct RTCBoundsFunctionArguments { -\ \ void*\ geometryUserPtr; -\ \ unsigned\ int\ primID; -\ \ unsigned\ int\ timeStep; -\ \ struct\ RTCBounds*\ bounds_o; + void* geometryUserPtr; + unsigned int primID; + unsigned int timeStep; + struct RTCBounds* bounds_o; }; -typedef\ void\ (*RTCBoundsFunction)( -\ \ const\ struct\ RTCBoundsFunctionArguments*\ args +typedef void (*RTCBoundsFunction)( + const struct RTCBoundsFunctionArguments* args ); -void\ rtcSetGeometryBoundsFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCBoundsFunction\ bounds, -\ \ void*\ userPtr +void rtcSetGeometryBoundsFunction( + RTCGeometry geometry, + RTCBoundsFunction bounds, + void* userPtr ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryBoundsFunction\f[] function registers a bounding -box callback function (\f[C]bounds\f[] argument) with payload -(\f[C]userPtr\f[] argument) for the specified user geometry -(\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryBoundsFunction\f[R] function registers a bounding +box callback function (\f[C]bounds\f[R] argument) with payload +(\f[C]userPtr\f[R] argument) for the specified user geometry +(\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered bounding box callback function is invoked to calculate axis\-aligned bounding boxes of the primitives of the user\-defined geometry during spatial acceleration structure construction. -The bounding box callback of \f[C]RTCBoundsFunction\f[] type is invoked +The bounding box callback of \f[C]RTCBoundsFunction\f[R] type is invoked with a pointer to a structure of type -\f[C]RTCBoundsFunctionArguments\f[] which contains various arguments, -such as: the user data of the geometry (\f[C]geometryUserPtr\f[] +\f[C]RTCBoundsFunctionArguments\f[R] which contains various arguments, +such as: the user data of the geometry (\f[C]geometryUserPtr\f[R] member), the ID of the primitive to calculate the bounds for -(\f[C]primID\f[] member), the time step at which to calculate the bounds -(\f[C]timeStep\f[] member), and a memory location to write the -calculated bound to (\f[C]bounds_o\f[] member). +(\f[C]primID\f[R] member), the time step at which to calculate the +bounds (\f[C]timeStep\f[R] member), and a memory location to write the +calculated bound to (\f[C]bounds_o\f[R] member). .PP In a typical usage scenario one would store a pointer to the internal representation of the user geometry object using -\f[C]rtcSetGeometryUserData\f[]. +\f[C]rtcSetGeometryUserData\f[R]. The callback function can then read that pointer from the -\f[C]geometryUserPtr\f[] field and calculate the proper bounding box for -the requested primitive and time, and store that bounding box to the -destination structure (\f[C]bounds_o\f[] member). +\f[C]geometryUserPtr\f[R] field and calculate the proper bounding box +for the requested primitive and time, and store that bounding box to the +destination structure (\f[C]bounds_o\f[R] member). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_USER] diff --git a/man/man3/rtcSetGeometryBuffer.3embree3 b/man/man3/rtcSetGeometryBuffer.3embree3 index f34ae231ba..d9d01c396d 100644 --- a/man/man3/rtcSetGeometryBuffer.3embree3 +++ b/man/man3/rtcSetGeometryBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,50 +6,50 @@ .IP .nf \f[C] -rtcSetGeometryBuffer\ \-\ assigns\ a\ view\ of\ a\ buffer\ to\ the\ geometry -\f[] +rtcSetGeometryBuffer \- assigns a view of a buffer to the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryBuffer( -\ \ RTCGeometry\ geometry, -\ \ enum\ RTCBufferType\ type, -\ \ unsigned\ int\ slot, -\ \ enum\ RTCFormat\ format, -\ \ RTCBuffer\ buffer, -\ \ size_t\ byteOffset, -\ \ size_t\ byteStride, -\ \ size_t\ itemCount +void rtcSetGeometryBuffer( + RTCGeometry geometry, + enum RTCBufferType type, + unsigned int slot, + enum RTCFormat format, + RTCBuffer buffer, + size_t byteOffset, + size_t byteStride, + size_t itemCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryBuffer\f[] function binds a view of a buffer -object (\f[C]buffer\f[] argument) to a geometry buffer type and slot -(\f[C]type\f[] and \f[C]slot\f[] argument) of the specified geometry -(\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryBuffer\f[R] function binds a view of a buffer +object (\f[C]buffer\f[R] argument) to a geometry buffer type and slot +(\f[C]type\f[R] and \f[C]slot\f[R] argument) of the specified geometry +(\f[C]geometry\f[R] argument). .PP One can specify the start of the first buffer element in bytes -(\f[C]byteOffset\f[] argument), the byte stride between individual -buffer elements (\f[C]byteStride\f[] argument), the format of the buffer -elements (\f[C]format\f[] argument), and the number of elements to bind -(\f[C]itemCount\f[]). +(\f[C]byteOffset\f[R] argument), the byte stride between individual +buffer elements (\f[C]byteStride\f[R] argument), the format of the +buffer elements (\f[C]format\f[R] argument), and the number of elements +to bind (\f[C]itemCount\f[R]). .PP -The start address (\f[C]byteOffset\f[] argument) and stride -(\f[C]byteStride\f[] argument) must be both aligned to 4 bytes, -otherwise the \f[C]rtcSetGeometryBuffer\f[] function will fail. +The start address (\f[C]byteOffset\f[R] argument) and stride +(\f[C]byteStride\f[R] argument) must be both aligned to 4 bytes, +otherwise the \f[C]rtcSetGeometryBuffer\f[R] function will fail. .PP After successful completion of this function, the geometry will hold a reference to the buffer object. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer] diff --git a/man/man3/rtcSetGeometryBuildQuality.3embree3 b/man/man3/rtcSetGeometryBuildQuality.3embree3 index f9c394acc7..a44778b5a4 100644 --- a/man/man3/rtcSetGeometryBuildQuality.3embree3 +++ b/man/man3/rtcSetGeometryBuildQuality.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryBuildQuality" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,52 +6,51 @@ .IP .nf \f[C] -rtcSetGeometryBuildQuality\ \-\ sets\ the\ build\ quality\ for\ the\ geometry -\f[] +rtcSetGeometryBuildQuality \- sets the build quality for the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryBuildQuality( -\ \ RTCGeometry\ geometry, -\ \ enum\ RTCBuildQuality\ quality +void rtcSetGeometryBuildQuality( + RTCGeometry geometry, + enum RTCBuildQuality quality ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryBuildQuality\f[] function sets the build quality -(\f[C]quality\f[] argument) for the specified geometry -(\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryBuildQuality\f[R] function sets the build quality +(\f[C]quality\f[R] argument) for the specified geometry +(\f[C]geometry\f[R] argument). The per\-geometry build quality is only a hint and may be ignored. Embree currently uses the per\-geometry build quality when the scene -build quality is set to \f[C]RTC_BUILD_QUALITY_LOW\f[]. +build quality is set to \f[C]RTC_BUILD_QUALITY_LOW\f[R]. In this mode a two\-level acceleration structure is build, and geometries build a separate acceleration structure using the geometry build quality. The per\-geometry build quality can be one of: .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_LOW\f[]: Creates lower quality data structures, -e.g. -for dynamic scenes. +\f[C]RTC_BUILD_QUALITY_LOW\f[R]: Creates lower quality data structures, +e.g.\ for dynamic scenes. .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_MEDIUM\f[]: Default build quality for most +\f[C]RTC_BUILD_QUALITY_MEDIUM\f[R]: Default build quality for most usages. Gives a good compromise between build and render performance. .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_HIGH\f[]: Creates higher quality data structures +\f[C]RTC_BUILD_QUALITY_HIGH\f[R]: Creates higher quality data structures for final\-frame rendering. Enables a spatial split builder for certain primitive types. .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_REFIT\f[]: Uses a BVH refitting approach when +\f[C]RTC_BUILD_QUALITY_REFIT\f[R]: Uses a BVH refitting approach when changing only the vertex buffer. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetSceneBuildQuality] diff --git a/man/man3/rtcSetGeometryDisplacementFunction.3embree3 b/man/man3/rtcSetGeometryDisplacementFunction.3embree3 index aa1e6d3c89..4e095de85b 100644 --- a/man/man3/rtcSetGeometryDisplacementFunction.3embree3 +++ b/man/man3/rtcSetGeometryDisplacementFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryDisplacementFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,76 +6,76 @@ .IP .nf \f[C] -rtcSetGeometryDisplacementFunction\ \-\ sets\ the\ displacement\ function -\ \ for\ a\ subdivision\ geometry -\f[] +rtcSetGeometryDisplacementFunction \- sets the displacement function + for a subdivision geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCDisplacementFunctionNArguments +struct RTCDisplacementFunctionNArguments { -\ \ void*\ geometryUserPtr; -\ \ RTCGeometry\ geometry; -\ \ unsigned\ int\ primID; -\ \ unsigned\ int\ timeStep; -\ \ const\ float*\ u; -\ \ const\ float*\ v; -\ \ const\ float*\ Ng_x; -\ \ const\ float*\ Ng_y; -\ \ const\ float*\ Ng_z; -\ \ float*\ P_x; -\ \ float*\ P_y; -\ \ float*\ P_z; -\ \ unsigned\ int\ N; + void* geometryUserPtr; + RTCGeometry geometry; + unsigned int primID; + unsigned int timeStep; + const float* u; + const float* v; + const float* Ng_x; + const float* Ng_y; + const float* Ng_z; + float* P_x; + float* P_y; + float* P_z; + unsigned int N; }; -typedef\ void\ (*RTCDisplacementFunctionN)( -\ \ \ const\ struct\ RTCDisplacementFunctionNArguments*\ args +typedef void (*RTCDisplacementFunctionN)( + const struct RTCDisplacementFunctionNArguments* args ); -void\ rtcSetGeometryDisplacementFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCDisplacementFunctionN\ displacement +void rtcSetGeometryDisplacementFunction( + RTCGeometry geometry, + RTCDisplacementFunctionN displacement ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryDisplacementFunction\f[] function registers a -displacement callback function (\f[C]displacement\f[] argument) for the -specified subdivision geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryDisplacementFunction\f[R] function registers a +displacement callback function (\f[C]displacement\f[R] argument) for the +specified subdivision geometry (\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered displacement callback function is invoked to displace points on the subdivision geometry during spatial acceleration structure -construction, during the \f[C]rtcCommitScene\f[] call. +construction, during the \f[C]rtcCommitScene\f[R] call. .PP -The callback function of type \f[C]RTCDisplacementFunctionN\f[] is +The callback function of type \f[C]RTCDisplacementFunctionN\f[R] is invoked with a number of arguments stored inside the -\f[C]RTCDisplacementFunctionNArguments\f[] structure. -The provided user data pointer of the geometry (\f[C]geometryUserPtr\f[] -member) can be used to point to the application\[aq]s representation of -the subdivision mesh. -A number \f[C]N\f[] of points to displace are specified in a structure +\f[C]RTCDisplacementFunctionNArguments\f[R] structure. +The provided user data pointer of the geometry +(\f[C]geometryUserPtr\f[R] member) can be used to point to the +application\[cq]s representation of the subdivision mesh. +A number \f[C]N\f[R] of points to displace are specified in a structure of array layout. -For each point to displace, the local patch UV coordinates (\f[C]u\f[] -and \f[C]v\f[] arrays), the normalized geometry normal (\f[C]Ng_x\f[], -\f[C]Ng_y\f[], and \f[C]Ng_z\f[] arrays), and the position -(\f[C]P_x\f[], \f[C]P_y\f[], and \f[C]P_z\f[] arrays) are provided. +For each point to displace, the local patch UV coordinates (\f[C]u\f[R] +and \f[C]v\f[R] arrays), the normalized geometry normal (\f[C]Ng_x\f[R], +\f[C]Ng_y\f[R], and \f[C]Ng_z\f[R] arrays), and the position +(\f[C]P_x\f[R], \f[C]P_y\f[R], and \f[C]P_z\f[R] arrays) are provided. The task of the displacement function is to use this information and change the position data. .PP -The geometry handle (\f[C]geometry\f[] member) and primitive ID -(\f[C]primID\f[] member) of the patch to displace are additionally -provided as well as the time step \f[C]timeStep\f[], which can be +The geometry handle (\f[C]geometry\f[R] member) and primitive ID +(\f[C]primID\f[R] member) of the patch to displace are additionally +provided as well as the time step \f[C]timeStep\f[R], which can be important if the displacement is time\-dependent and motion blur is used. .PP @@ -88,7 +88,7 @@ the displacement mapping functions. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_SUBDIVISION] diff --git a/man/man3/rtcSetGeometryInstancedScene.3embree3 b/man/man3/rtcSetGeometryInstancedScene.3embree3 index ee8b4655ae..3ea523fa41 100644 --- a/man/man3/rtcSetGeometryInstancedScene.3embree3 +++ b/man/man3/rtcSetGeometryInstancedScene.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryInstancedScene" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcSetGeometryInstancedScene\ \-\ sets\ the\ instanced\ scene\ of -\ \ an\ instance\ geometry -\f[] +rtcSetGeometryInstancedScene \- sets the instanced scene of + an instance geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryInstancedScene( -\ \ RTCGeometry\ geometry, -\ \ RTCScene\ scene +void rtcSetGeometryInstancedScene( + RTCGeometry geometry, + RTCScene scene ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryInstancedScene\f[] function sets the instanced -scene (\f[C]scene\f[] argument) of the specified instance geometry -(\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryInstancedScene\f[R] function sets the instanced +scene (\f[C]scene\f[R] argument) of the specified instance geometry +(\f[C]geometry\f[R] argument). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_INSTANCE], [rtcSetGeometryTransform] diff --git a/man/man3/rtcSetGeometryIntersectFilterFunction.3embree3 b/man/man3/rtcSetGeometryIntersectFilterFunction.3embree3 index 63b8fdaea9..967258b22d 100644 --- a/man/man3/rtcSetGeometryIntersectFilterFunction.3embree3 +++ b/man/man3/rtcSetGeometryIntersectFilterFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryIntersectFilterFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,49 +6,49 @@ .IP .nf \f[C] -rtcSetGeometryIntersectFilterFunction\ \-\ sets\ the\ intersection\ filter -\ \ for\ the\ geometry -\f[] +rtcSetGeometryIntersectFilterFunction \- sets the intersection filter + for the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCFilterFunctionNArguments +struct RTCFilterFunctionNArguments { -\ \ int*\ valid; -\ \ void*\ geometryUserPtr; -\ \ const\ struct\ RTCIntersectContext*\ context; -\ \ struct\ RTCRayN*\ ray; -\ \ struct\ RTCHitN*\ hit; -\ \ unsigned\ int\ N; + int* valid; + void* geometryUserPtr; + const struct RTCIntersectContext* context; + struct RTCRayN* ray; + struct RTCHitN* hit; + unsigned int N; }; -typedef\ void\ (*RTCFilterFunctionN)( -\ \ const\ struct\ RTCFilterFunctionNArguments*\ args +typedef void (*RTCFilterFunctionN)( + const struct RTCFilterFunctionNArguments* args ); -void\ rtcSetGeometryIntersectFilterFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCFilterFunctionN\ filter +void rtcSetGeometryIntersectFilterFunction( + RTCGeometry geometry, + RTCFilterFunctionN filter ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryIntersectFilterFunction\f[] function registers an -intersection filter callback function (\f[C]filter\f[] argument) for the -specified geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryIntersectFilterFunction\f[R] function registers +an intersection filter callback function (\f[C]filter\f[R] argument) for +the specified geometry (\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered intersection filter function is invoked for every hit -encountered during the \f[C]rtcIntersect\f[]\-type ray queries and can +encountered during the \f[C]rtcIntersect\f[R]\-type ray queries and can accept or reject that hit. The feature can be used to define a silhouette for a primitive and reject hits that are outside the silhouette. @@ -56,58 +56,58 @@ E.g. a tree leaf could be modeled with an alpha texture that decides whether hit points lie inside or outside the leaf. .PP -If the \f[C]RTC_BUILD_QUALITY_HIGH\f[] mode is set, the filter functions -may be called multiple times for the same primitive hit. +If the \f[C]RTC_BUILD_QUALITY_HIGH\f[R] mode is set, the filter +functions may be called multiple times for the same primitive hit. Further, rays hitting exactly the edge might also report two hits for the same surface. For certain use cases, the application may have to work around this limitation by collecting already reported hits -(\f[C]geomID\f[]/\f[C]primID\f[] pairs) and ignoring duplicates. +(\f[C]geomID\f[R]/\f[C]primID\f[R] pairs) and ignoring duplicates. .PP -The filter function callback of type \f[C]RTCFilterFunctionN\f[] gets +The filter function callback of type \f[C]RTCFilterFunctionN\f[R] gets passed a number of arguments through the -\f[C]RTCFilterFunctionNArguments\f[] structure. -The \f[C]valid\f[] parameter of that structure points to an integer +\f[C]RTCFilterFunctionNArguments\f[R] structure. +The \f[C]valid\f[R] parameter of that structure points to an integer valid mask (0 means invalid and \-1 means valid). -The \f[C]geometryUserPtr\f[] member is a user pointer optionally set per -geometry through the \f[C]rtcSetGeometryUserData\f[] function. -The \f[C]context\f[] member points to the intersection context passed to -the ray query function. -The \f[C]ray\f[] parameter points to \f[C]N\f[] rays in SOA layout. -The \f[C]hit\f[] parameter points to \f[C]N\f[] hits in SOA layout to +The \f[C]geometryUserPtr\f[R] member is a user pointer optionally set +per geometry through the \f[C]rtcSetGeometryUserData\f[R] function. +The \f[C]context\f[R] member points to the intersection context passed +to the ray query function. +The \f[C]ray\f[R] parameter points to \f[C]N\f[R] rays in SOA layout. +The \f[C]hit\f[R] parameter points to \f[C]N\f[R] hits in SOA layout to test. -The \f[C]N\f[] parameter is the number of rays and hits in \f[C]ray\f[] -and \f[C]hit\f[]. -The hit distance is provided as the \f[C]tfar\f[] value of the ray. -If the hit geometry is instanced, the \f[C]instID\f[] member of the ray +The \f[C]N\f[R] parameter is the number of rays and hits in +\f[C]ray\f[R] and \f[C]hit\f[R]. +The hit distance is provided as the \f[C]tfar\f[R] value of the ray. +If the hit geometry is instanced, the \f[C]instID\f[R] member of the ray is valid, and the ray and the potential hit are in object space. .PP The filter callback function has the task to check for each valid ray whether it wants to accept or reject the corresponding hit. To reject a hit, the filter callback function just has to write -\f[C]0\f[] to the integer valid mask of the corresponding ray. +\f[C]0\f[R] to the integer valid mask of the corresponding ray. To accept the hit, it just has to leave the valid mask set to -\f[C]\-1\f[]. +\f[C]\-1\f[R]. The filter function is further allowed to change the hit and decrease -the \f[C]tfar\f[] value of the ray but it should not modify other ray +the \f[C]tfar\f[R] value of the ray but it should not modify other ray data nor any inactive components of the ray or hit. .IP .nf \f[C] -\f[] +\f[R] .fi .PP The implementation of the filter function can choose to implement a single code path that uses the ray access helper functions -\f[C]RTCRay_XXX\f[] and hit access helper functions \f[C]RTCHit_XXX\f[] -to access ray and hit data. +\f[C]RTCRay_XXX\f[R] and hit access helper functions +\f[C]RTCHit_XXX\f[R] to access ray and hit data. Alternatively the code can branch to optimized implementations for -specific sizes of \f[C]N\f[] and cast the \f[C]ray\f[] and \f[C]hit\f[] -inputs to the proper packet types. +specific sizes of \f[C]N\f[R] and cast the \f[C]ray\f[R] and +\f[C]hit\f[R] inputs to the proper packet types. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryOccludedFilterFunction] diff --git a/man/man3/rtcSetGeometryIntersectFunction.3embree3 b/man/man3/rtcSetGeometryIntersectFunction.3embree3 index 7fe025a85a..d0b3a2dede 100644 --- a/man/man3/rtcSetGeometryIntersectFunction.3embree3 +++ b/man/man3/rtcSetGeometryIntersectFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryIntersectFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,68 +6,68 @@ .IP .nf \f[C] -rtcSetGeometryIntersectFunction\ \-\ sets\ the\ callback\ function\ to -\ \ intersect\ a\ user\ geometry -\f[] +rtcSetGeometryIntersectFunction \- sets the callback function to + intersect a user geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCIntersectFunctionNArguments +struct RTCIntersectFunctionNArguments { -\ \ int*\ valid; -\ \ void*\ geometryUserPtr; -\ \ unsigned\ int\ primID; -\ \ struct\ RTCIntersectContext*\ context; -\ \ struct\ RTCRayHitN*\ rayhit; -\ \ unsigned\ int\ N; -\ \ unsigned\ int\ geomID; + int* valid; + void* geometryUserPtr; + unsigned int primID; + struct RTCIntersectContext* context; + struct RTCRayHitN* rayhit; + unsigned int N; + unsigned int geomID; }; -typedef\ void\ (*RTCIntersectFunctionN)( -\ \ const\ struct\ RTCIntersectFunctionNArguments*\ args +typedef void (*RTCIntersectFunctionN)( + const struct RTCIntersectFunctionNArguments* args ); -void\ rtcSetGeometryIntersectFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCIntersectFunctionN\ intersect +void rtcSetGeometryIntersectFunction( + RTCGeometry geometry, + RTCIntersectFunctionN intersect ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryIntersectFunction\f[] function registers a -ray/primitive intersection callback function (\f[C]intersect\f[] -argument) for the specified user geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryIntersectFunction\f[R] function registers a +ray/primitive intersection callback function (\f[C]intersect\f[R] +argument) for the specified user geometry (\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered callback function is invoked by -\f[C]rtcIntersect\f[]\-type ray queries to calculate the intersection of -a ray packet of variable size with one user\-defined primitive. -The callback function of type \f[C]RTCIntersectFunctionN\f[] gets passed -a number of arguments through the -\f[C]RTCIntersectFunctionNArguments\f[] structure. -The value \f[C]N\f[] specifies the ray packet size, \f[C]valid\f[] +\f[C]rtcIntersect\f[R]\-type ray queries to calculate the intersection +of a ray packet of variable size with one user\-defined primitive. +The callback function of type \f[C]RTCIntersectFunctionN\f[R] gets +passed a number of arguments through the +\f[C]RTCIntersectFunctionNArguments\f[R] structure. +The value \f[C]N\f[R] specifies the ray packet size, \f[C]valid\f[R] points to an array of integers that specify whether the corresponding -ray is valid (\-1) or invalid (0), the \f[C]geometryUserPtr\f[] member +ray is valid (\-1) or invalid (0), the \f[C]geometryUserPtr\f[R] member points to the geometry user data previously set through -\f[C]rtcSetGeometryUserData\f[], the \f[C]context\f[] member points to -the intersection context passed to the ray query, the \f[C]rayhit\f[] -member points to a ray and hit packet of variable size \f[C]N\f[], and -the \f[C]geomID\f[] and \f[C]primID\f[] member identifies the geometry +\f[C]rtcSetGeometryUserData\f[R], the \f[C]context\f[R] member points to +the intersection context passed to the ray query, the \f[C]rayhit\f[R] +member points to a ray and hit packet of variable size \f[C]N\f[R], and +the \f[C]geomID\f[R] and \f[C]primID\f[R] member identifies the geometry ID and primitive ID of the primitive to intersect. .PP -The \f[C]ray\f[] component of the \f[C]rayhit\f[] structure contains -valid data, in particular the \f[C]tfar\f[] value is the current closest -hit distance found. -All data inside the \f[C]hit\f[] component of the \f[C]rayhit\f[] +The \f[C]ray\f[R] component of the \f[C]rayhit\f[R] structure contains +valid data, in particular the \f[C]tfar\f[R] value is the current +closest hit distance found. +All data inside the \f[C]hit\f[R] component of the \f[C]rayhit\f[R] structure are undefined and should not be read by the function. .PP The task of the callback function is to intersect each active ray from @@ -75,31 +75,31 @@ the ray packet with the specified user primitive. If the user\-defined primitive is missed by a ray of the ray packet, the function should return without modifying the ray or hit. If an intersection of the user\-defined primitive with the ray was found -in the valid range (from \f[C]tnear\f[] to \f[C]tfar\f[]), it should -update the hit distance of the ray (\f[C]tfar\f[] member) and the hit -(\f[C]u\f[], \f[C]v\f[], \f[C]Ng\f[], \f[C]instID\f[], \f[C]geomID\f[], -\f[C]primID\f[] members). +in the valid range (from \f[C]tnear\f[R] to \f[C]tfar\f[R]), it should +update the hit distance of the ray (\f[C]tfar\f[R] member) and the hit +(\f[C]u\f[R], \f[C]v\f[R], \f[C]Ng\f[R], \f[C]instID\f[R], +\f[C]geomID\f[R], \f[C]primID\f[R] members). In particular, the currently intersected instance is stored in the -\f[C]instID\f[] field of the intersection context, which must be deep -copied into the \f[C]instID\f[] member of the hit. +\f[C]instID\f[R] field of the intersection context, which must be deep +copied into the \f[C]instID\f[R] member of the hit. .PP As a primitive might have multiple intersections with a ray, the intersection filter function needs to be invoked by the user geometry intersection callback for each encountered intersection, if filtering of intersections is desired. -This can be achieved through the \f[C]rtcFilterIntersection\f[] call. +This can be achieved through the \f[C]rtcFilterIntersection\f[R] call. .PP Within the user geometry intersect function, it is safe to trace new rays and create new scenes and geometries. .IP .nf \f[C] -\f[] +\f[R] .fi .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryOccludedFunction], [rtcSetGeometryUserData], diff --git a/man/man3/rtcSetGeometryMask.3embree3 b/man/man3/rtcSetGeometryMask.3embree3 index d3e6ebb914..128919ec34 100644 --- a/man/man3/rtcSetGeometryMask.3embree3 +++ b/man/man3/rtcSetGeometryMask.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryMask" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,44 +6,43 @@ .IP .nf \f[C] -rtcSetGeometryMask\ \-\ sets\ the\ geometry\ mask -\f[] +rtcSetGeometryMask \- sets the geometry mask +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryMask( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ mask +void rtcSetGeometryMask( + RTCGeometry geometry, + unsigned int mask ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryMask\f[] function sets a 32\-bit geometry mask -(\f[C]mask\f[] argument) for the specified geometry (\f[C]geometry\f[] +The \f[C]rtcSetGeometryMask\f[R] function sets a 32\-bit geometry mask +(\f[C]mask\f[R] argument) for the specified geometry (\f[C]geometry\f[R] argument). .PP This geometry mask is used together with the ray mask stored inside the -\f[C]mask\f[] field of the ray. +\f[C]mask\f[R] field of the ray. The primitives of the geometry are hit by the ray only if the bitwise -\f[C]and\f[] operation of the geometry mask with the ray mask is not 0. +\f[C]and\f[R] operation of the geometry mask with the ray mask is not 0. This feature can be used to disable selected geometries for specifically -tagged rays, e.g. -to disable shadow casting for certain geometries. +tagged rays, e.g.\ to disable shadow casting for certain geometries. .PP Ray masks are disabled in Embree by default at compile time, and can be -enabled through the \f[C]EMBREE_RAY_MASK\f[] parameter in CMake. +enabled through the \f[C]EMBREE_RAY_MASK\f[R] parameter in CMake. One can query whether ray masks are enabled by querying the -\f[C]RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED\f[] device property using -\f[C]rtcGetDeviceProperty\f[]. +\f[C]RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED\f[R] device property using +\f[C]rtcGetDeviceProperty\f[R]. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTCRay], [rtcGetDeviceProperty] diff --git a/man/man3/rtcSetGeometryMaxRadiusScale.3embree3 b/man/man3/rtcSetGeometryMaxRadiusScale.3embree3 index 53553be65c..adb3e7be64 100644 --- a/man/man3/rtcSetGeometryMaxRadiusScale.3embree3 +++ b/man/man3/rtcSetGeometryMaxRadiusScale.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryMaxRadiusScale" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,22 +6,22 @@ .IP .nf \f[C] -rtcSetGeometryMaxRadiusScale\ \-\ assigns\ a\ maximal\ curve\ radius\ scale\ factor\ for\ min\-width\ feature -\f[] +rtcSetGeometryMaxRadiusScale \- assigns a maximal curve radius scale factor for min\-width feature +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryMaxRadiusScale(RTCGeometry\ geometry,\ float\ maxRadiusScale); -\f[] +void rtcSetGeometryMaxRadiusScale(RTCGeometry geometry, float maxRadiusScale); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetMaxGeometryScale\f[] function specifies a maximal scaling -factor for curve radii used by the min\-width feature. +The \f[C]rtcSetMaxGeometryScale\f[R] function specifies a maximal +scaling factor for curve radii used by the min\-width feature. .PP The min\-width feature can increase the radius of curves and points, in order to reduce aliasing and improve render times. @@ -30,9 +30,9 @@ EMBREE_MIN_WIDTH cmake option. .PP To use the feature, one has to specify a maximal curve radius scaling factor using the [rtcSetGeometryMaxRadiusScale] function. -This factor should be a small number (e.g. -4) as the constructed BVH bounds get increased in order to bound the -curve in the worst case of maximal radii. +This factor should be a small number (e.g.\ 4) as the constructed BVH +bounds get increased in order to bound the curve in the worst case of +maximal radii. .PP One also has to set the minWidthDistanceFactor in the RTCIntersectContext when tracing a ray. @@ -40,39 +40,39 @@ This factor controls the target radius size of a curve or point at some distance away of the ray origin. .PP For each control point p with radius r of a curve or point primitive, -the primitive intersectors first calculate a target radius r\[aq] as: +the primitive intersectors first calculate a target radius r\[cq] as: .IP .nf \f[C] -r\[aq]\ =\ length(p\-ray_org)\ *\ minWidthDistanceFactor -\f[] +r\[aq] = length(p\-ray_org) * minWidthDistanceFactor +\f[R] .fi .PP Typically the minWidthDistanceFactor is set by the application such that the target radius projects to the width of half a pixel (thus primitive diameter is pixel sized). .PP -The target radius r\[aq] is then clamped against the minimal bound r and -maximal bound maxRadiusScale*r to obtain the final radius r\[aq]\[aq]: +The target radius r\[cq] is then clamped against the minimal bound r and +maximal bound maxRadiusScale*r to obtain the final radius r\[cq]\[cq]: .IP .nf \f[C] -r\[aq]\[aq]\ =\ max(r,\ min(r\[aq],\ maxRadiusScale*r)) -\f[] +r\[aq]\[aq] = max(r, min(r\[aq], maxRadiusScale*r)) +\f[R] .fi .PP Thus curves or points close to the camera are rendered with a normal radii r, and curves or points far from the camera are not enlarged too much, as this would be very expensive to render. .PP -When \f[C]rtcSetGeometryMaxRadiusScale\f[] function is not invoked for a -curve or point geometry (or if the maximal scaling factor is set to +When \f[C]rtcSetGeometryMaxRadiusScale\f[R] function is not invoked for +a curve or point geometry (or if the maximal scaling factor is set to 1.0), then the curve or point geometry renders normally, with radii not modified by the min\-width feature. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcInitIntersectContext] diff --git a/man/man3/rtcSetGeometryOccludedFilterFunction.3embree3 b/man/man3/rtcSetGeometryOccludedFilterFunction.3embree3 index def801788a..37b77c800a 100644 --- a/man/man3/rtcSetGeometryOccludedFilterFunction.3embree3 +++ b/man/man3/rtcSetGeometryOccludedFilterFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryOccludedFilterFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,35 +6,35 @@ .IP .nf \f[C] -rtcSetGeometryOccludedFilterFunction\ \-\ sets\ the\ occlusion\ filter -\ \ for\ the\ geometry -\f[] +rtcSetGeometryOccludedFilterFunction \- sets the occlusion filter + for the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryOccludedFilterFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCFilterFunctionN\ filter +void rtcSetGeometryOccludedFilterFunction( + RTCGeometry geometry, + RTCFilterFunctionN filter ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryOccludedFilterFunction\f[] function registers an -occlusion filter callback function (\f[C]filter\f[] argument) for the -specified geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryOccludedFilterFunction\f[R] function registers an +occlusion filter callback function (\f[C]filter\f[R] argument) for the +specified geometry (\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered intersection filter function is invoked for every hit -encountered during the \f[C]rtcOccluded\f[]\-type ray queries and can +encountered during the \f[C]rtcOccluded\f[R]\-type ray queries and can accept or reject that hit. The feature can be used to define a silhouette for a primitive and reject hits that are outside the silhouette. @@ -43,12 +43,12 @@ a tree leaf could be modeled with an alpha texture that decides whether hit points lie inside or outside the leaf. .PP Please see the description of the -\f[C]rtcSetGeometryIntersectFilterFunction\f[] for a description of the +\f[C]rtcSetGeometryIntersectFilterFunction\f[R] for a description of the filter callback function. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryIntersectFilterFunction] diff --git a/man/man3/rtcSetGeometryOccludedFunction.3embree3 b/man/man3/rtcSetGeometryOccludedFunction.3embree3 index 60671cf59b..594e8f1c14 100644 --- a/man/man3/rtcSetGeometryOccludedFunction.3embree3 +++ b/man/man3/rtcSetGeometryOccludedFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryOccludedFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,62 +6,62 @@ .IP .nf \f[C] -rtcSetGeometryOccludedFunction\ \-\ sets\ the\ callback\ function\ to -\ \ test\ a\ user\ geometry\ for\ occlusion -\f[] +rtcSetGeometryOccludedFunction \- sets the callback function to + test a user geometry for occlusion +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCOccludedFunctionNArguments +struct RTCOccludedFunctionNArguments { -\ \ int*\ valid; -\ \ void*\ geometryUserPtr; -\ \ unsigned\ int\ primID; -\ \ struct\ RTCIntersectContext*\ context; -\ \ struct\ RTCRayN*\ ray; -\ \ unsigned\ int\ N; -\ \ unsigned\ int\ geomID; + int* valid; + void* geometryUserPtr; + unsigned int primID; + struct RTCIntersectContext* context; + struct RTCRayN* ray; + unsigned int N; + unsigned int geomID; }; -typedef\ void\ (*RTCOccludedFunctionN)( -\ \ const\ struct\ RTCOccludedFunctionNArguments*\ args +typedef void (*RTCOccludedFunctionN)( + const struct RTCOccludedFunctionNArguments* args ); -void\ rtcSetGeometryOccludedFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCOccludedFunctionN\ filter +void rtcSetGeometryOccludedFunction( + RTCGeometry geometry, + RTCOccludedFunctionN filter ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryOccludedFunction\f[] function registers a -ray/primitive occlusion callback function (\f[C]filter\f[] argument) for -the specified user geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryOccludedFunction\f[R] function registers a +ray/primitive occlusion callback function (\f[C]filter\f[R] argument) +for the specified user geometry (\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered callback function is invoked by -\f[C]rtcOccluded\f[]\-type ray queries to test whether the rays of a +\f[C]rtcOccluded\f[R]\-type ray queries to test whether the rays of a packet of variable size are occluded by a user\-defined primitive. -The callback function of type \f[C]RTCOccludedFunctionN\f[] gets passed -a number of arguments through the \f[C]RTCOccludedFunctionNArguments\f[] -structure. -The value \f[C]N\f[] specifies the ray packet size, \f[C]valid\f[] +The callback function of type \f[C]RTCOccludedFunctionN\f[R] gets passed +a number of arguments through the +\f[C]RTCOccludedFunctionNArguments\f[R] structure. +The value \f[C]N\f[R] specifies the ray packet size, \f[C]valid\f[R] points to an array of integers which specify whether the corresponding -ray is valid (\-1) or invalid (0), the \f[C]geometryUserPtr\f[] member +ray is valid (\-1) or invalid (0), the \f[C]geometryUserPtr\f[R] member points to the geometry user data previously set through -\f[C]rtcSetGeometryUserData\f[], the \f[C]context\f[] member points to -the intersection context passed to the ray query, the \f[C]ray\f[] -member points to a ray packet of variable size \f[C]N\f[], and the -\f[C]geomID\f[] and \f[C]primID\f[] member identifies the geometry ID +\f[C]rtcSetGeometryUserData\f[R], the \f[C]context\f[R] member points to +the intersection context passed to the ray query, the \f[C]ray\f[R] +member points to a ray packet of variable size \f[C]N\f[R], and the +\f[C]geomID\f[R] and \f[C]primID\f[R] member identifies the geometry ID and primitive ID of the primitive to intersect. .PP The task of the callback function is to intersect each active ray from @@ -69,26 +69,26 @@ the ray packet with the specified user primitive. If the user\-defined primitive is missed by a ray of the ray packet, the function should return without modifying the ray. If an intersection of the user\-defined primitive with the ray was found -in the valid range (from \f[C]tnear\f[] to \f[C]tfar\f[]), it should set -the \f[C]tfar\f[] member of the ray to \f[C]\-inf\f[]. +in the valid range (from \f[C]tnear\f[R] to \f[C]tfar\f[R]), it should +set the \f[C]tfar\f[R] member of the ray to \f[C]\-inf\f[R]. .PP As a primitive might have multiple intersections with a ray, the occlusion filter function needs to be invoked by the user geometry occlusion callback for each encountered intersection, if filtering of intersections is desired. -This can be achieved through the \f[C]rtcFilterOcclusion\f[] call. +This can be achieved through the \f[C]rtcFilterOcclusion\f[R] call. .PP Within the user geometry occlusion function, it is safe to trace new rays and create new scenes and geometries. .IP .nf \f[C] -\f[] +\f[R] .fi .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryIntersectFunction], [rtcSetGeometryUserData], diff --git a/man/man3/rtcSetGeometryPointQueryFunction.3embree3 b/man/man3/rtcSetGeometryPointQueryFunction.3embree3 index d8856eb4b0..d2f9ffe810 100644 --- a/man/man3/rtcSetGeometryPointQueryFunction.3embree3 +++ b/man/man3/rtcSetGeometryPointQueryFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryPointQueryFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,71 +6,71 @@ .IP .nf \f[C] -rtcSetGeometryPointQueryFunction\ \-\ sets\ the\ point\ query\ callback\ function -\ \ for\ a\ geometry -\f[] +rtcSetGeometryPointQueryFunction \- sets the point query callback function + for a geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -struct\ RTCPointQueryFunctionArguments +struct RTCPointQueryFunctionArguments { -\ \ //\ the\ (world\ space)\ query\ object\ that\ was\ passed\ as\ an\ argument\ of\ rtcPointQuery. -\ \ struct\ RTCPointQuery*\ query; + // the (world space) query object that was passed as an argument of rtcPointQuery. + struct RTCPointQuery* query; -\ \ //\ used\ for\ user\ input/output\ data.\ Will\ not\ be\ read\ or\ modified\ internally. -\ \ void*\ userPtr; + // used for user input/output data. Will not be read or modified internally. + void* userPtr; -\ \ //\ primitive\ and\ geometry\ ID\ of\ primitive -\ \ unsigned\ int\ \ primID;\ \ \ \ \ \ \ \ -\ \ unsigned\ int\ \ geomID;\ \ \ \ + // primitive and geometry ID of primitive + unsigned int primID; + unsigned int geomID; -\ \ //\ the\ context\ with\ transformation\ and\ instance\ ID\ stack -\ \ struct\ RTCPointQueryContext*\ context; + // the context with transformation and instance ID stack + struct RTCPointQueryContext* context; -\ \ //\ scaling\ factor\ indicating\ whether\ the\ current\ instance\ transformation -\ \ //\ is\ a\ similarity\ transformation. -\ \ float\ similarityScale; + // scaling factor indicating whether the current instance transformation + // is a similarity transformation. + float similarityScale; }; -typedef\ bool\ (*RTCPointQueryFunction)( -\ \ struct\ RTCPointQueryFunctionArguments*\ args +typedef bool (*RTCPointQueryFunction)( + struct RTCPointQueryFunctionArguments* args ); -void\ rtcSetGeometryPointQueryFunction( -\ \ RTCGeometry\ geometry, -\ \ RTCPointQueryFunction\ queryFunc +void rtcSetGeometryPointQueryFunction( + RTCGeometry geometry, + RTCPointQueryFunction queryFunc ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryPointQueryFunction\f[] function registers a point -query callback function (\f[C]queryFunc\f[] argument) for the specified -geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryPointQueryFunction\f[R] function registers a +point query callback function (\f[C]queryFunc\f[R] argument) for the +specified geometry (\f[C]geometry\f[R] argument). .PP Only a single callback function can be registered per geometry and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP The registered callback function is invoked by [rtcPointQuery] for every primitive of the geometry that intersects the corresponding point query domain. -The callback function of type \f[C]RTCPointQueryFunction\f[] gets passed -a number of arguments through the -\f[C]RTCPointQueryFunctionArguments\f[] structure. -The \f[C]query\f[] object is the original point query object passed into -[rtcPointQuery], \f[C]usrPtr\f[] is an arbitrary pointer to pass input -into and store results of the callback function. -The \f[C]primID\f[], \f[C]geomID\f[] and \f[C]context\f[] (see +The callback function of type \f[C]RTCPointQueryFunction\f[R] gets +passed a number of arguments through the +\f[C]RTCPointQueryFunctionArguments\f[R] structure. +The \f[C]query\f[R] object is the original point query object passed +into [rtcPointQuery], \f[C]usrPtr\f[R] is an arbitrary pointer to pass +input into and store results of the callback function. +The \f[C]primID\f[R], \f[C]geomID\f[R] and \f[C]context\f[R] (see [rtcInitPointQueryContext] for details) can be used to identify the geometry data of the primitive. .PP -A \f[C]RTCPointQueryFunction\f[] can also be passed directly as an +A \f[C]RTCPointQueryFunction\f[R] can also be passed directly as an argument to [rtcPointQuery]. In this case the callback is invoked for all primitives in the scene that intersect the query domain. @@ -80,31 +80,31 @@ If a callback function is passed as an argument to [rtcPointQuery] and and the callback function passed to [rtcPointQuery] will be called before the geometry specific callback function. .PP -If instancing is used, the parameter \f[C]simliarityScale\f[] indicates +If instancing is used, the parameter \f[C]simliarityScale\f[R] indicates whether the current instance transform (top element of the stack in -\f[C]context\f[]) is a similarity transformation or not. +\f[C]context\f[R]) is a similarity transformation or not. Similarity transformations are composed of translation, rotation and uniform scaling and if a matrix M defines a similarity transformation, there is a scaling factor D such that for all x,y: dist(Mx, My) = D * dist(x, y). -In this case the parameter \f[C]scalingFactor\f[] is this scaling factor -D and otherwise it is 0. -A valid similarity scale (\f[C]similarityScale\f[] > 0) allows to +In this case the parameter \f[C]scalingFactor\f[R] is this scaling +factor D and otherwise it is 0. +A valid similarity scale (\f[C]similarityScale\f[R] > 0) allows to compute distance information in instance space and scale the distances into world space (for example, to update the query radius, see below) by dividing the instance space distance with the similarity scale. If the current instance transform is not a similarity transform -(\f[C]similarityScale\f[] is 0), the distance computation has to be +(\f[C]similarityScale\f[R] is 0), the distance computation has to be performed in world space to ensure correctness. In this case the instance to world transformations given with the -\f[C]context\f[] should be used to transform the primitive data into +\f[C]context\f[R] should be used to transform the primitive data into world space. Otherwise, the query location can be transformed into instance space which can be more efficient. If there is no instance transform, the similarity scale is 1. .PP The callback function will potentially be called for primitives outside -the query domain for two resons: First, the callback is invoked for all +the query domain for two reasons: First, the callback is invoked for all primitives inside a BVH leaf node since no geometry data of primitives is determined internally and therefore individual primitives are not culled (only their (aggregated) bounding boxes). @@ -112,25 +112,25 @@ Second, in case non similarity transformations are used, the resulting ellipsoidal query domain (in instance space) is approximated by its axis aligned bounding box internally and therefore inner nodes that do not intersect the original domain might intersect the approximative bounding -box which results in unneccessary callbacks. -In any case, the callbacks are conservative, i.e. -if a primitive is inside the query domain a callback will be invoked but -the reverse is not neccessarily true. +box which results in unnecessary callbacks. +In any case, the callbacks are conservative, i.e.\ if a primitive is +inside the query domain a callback will be invoked but the reverse is +not necessarily true. .PP -For efficiency, the radius of the \f[C]query\f[] object can be decreased -(in world space) inside the callback function to improve culling of -geometry during BVH traversal. +For efficiency, the radius of the \f[C]query\f[R] object can be +decreased (in world space) inside the callback function to improve +culling of geometry during BVH traversal. If the query radius was updated, the callback function should return -\f[C]true\f[] to issue an update of internal traversal information. +\f[C]true\f[R] to issue an update of internal traversal information. Increasing the radius or modifying the time or position of the query results in undefined behaviour. .PP Within the callback function, it is safe to call [rtcPointQuery] again, for example when implementing instancing manually. In this case the instance transformation should be pushed onto the stack -in \f[C]context\f[]. +in \f[C]context\f[R]. Embree will internally compute the point query information in instance -space using the top element of the stack in \f[C]context\f[] when +space using the top element of the stack in \f[C]context\f[R] when [rtcPointQuery] is called. .PP For a reference implementation of a closest point traversal of triangle diff --git a/man/man3/rtcSetGeometrySubdivisionMode.3embree3 b/man/man3/rtcSetGeometrySubdivisionMode.3embree3 index d80a182486..9d0d0420fd 100644 --- a/man/man3/rtcSetGeometrySubdivisionMode.3embree3 +++ b/man/man3/rtcSetGeometrySubdivisionMode.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometrySubdivisionMode" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,56 +6,57 @@ .IP .nf \f[C] -rtcSetGeometrySubdivisionMode\ \-\ sets\ the\ subdivision\ mode -\ \ of\ a\ subdivision\ geometry -\f[] +rtcSetGeometrySubdivisionMode \- sets the subdivision mode + of a subdivision geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometrySubdivisionMode( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ topologyID, -\ \ enum\ RTCSubdivisionMode\ mode +void rtcSetGeometrySubdivisionMode( + RTCGeometry geometry, + unsigned int topologyID, + enum RTCSubdivisionMode mode ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometrySubdivisionMode\f[] function sets the subdivision -mode (\f[C]mode\f[] parameter) for the topology (\f[C]topologyID\f[] -parameter) of the specified subdivision geometry (\f[C]geometry\f[] -parameter). +The \f[C]rtcSetGeometrySubdivisionMode\f[R] function sets the +subdivision mode (\f[C]mode\f[R] parameter) for the topology +(\f[C]topologyID\f[R] parameter) of the specified subdivision geometry +(\f[C]geometry\f[R] parameter). .PP The subdivision modes can be used to force linear interpolation for certain parts of the subdivision mesh: .IP \[bu] 2 -\f[C]RTC_SUBDIVISION_MODE_NO_BOUNDARY\f[]: Boundary patches are ignored. +\f[C]RTC_SUBDIVISION_MODE_NO_BOUNDARY\f[R]: Boundary patches are +ignored. This way each rendered patch has a full set of control vertices. .IP \[bu] 2 -\f[C]RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY\f[]: The sequence of boundary +\f[C]RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY\f[R]: The sequence of boundary control points are used to generate a smooth B\-spline boundary curve (default mode). .IP \[bu] 2 -\f[C]RTC_SUBDIVISION_MODE_PIN_CORNERS\f[]: Corner vertices are pinned to -their location during subdivision. +\f[C]RTC_SUBDIVISION_MODE_PIN_CORNERS\f[R]: Corner vertices are pinned +to their location during subdivision. .IP \[bu] 2 -\f[C]RTC_SUBDIVISION_MODE_PIN_BOUNDARY\f[]: All vertices at the border +\f[C]RTC_SUBDIVISION_MODE_PIN_BOUNDARY\f[R]: All vertices at the border are pinned to their location during subdivision. This way the boundary is interpolated linearly. This mode is typically used for texturing to also map texels at the border of the texture to the mesh. .IP \[bu] 2 -\f[C]RTC_SUBDIVISION_MODE_PIN_ALL\f[]: All vertices at the border are +\f[C]RTC_SUBDIVISION_MODE_PIN_ALL\f[R]: All vertices at the border are pinned to their location during subdivision. This way all patches are linearly interpolated. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_SUBDIVISION] diff --git a/man/man3/rtcSetGeometryTessellationRate.3embree3 b/man/man3/rtcSetGeometryTessellationRate.3embree3 index 4277eb2cb7..c23f66cb8e 100644 --- a/man/man3/rtcSetGeometryTessellationRate.3embree3 +++ b/man/man3/rtcSetGeometryTessellationRate.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTessellationRate" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,27 +6,27 @@ .IP .nf \f[C] -rtcSetGeometryTessellationRate\ \-\ sets\ the\ tessellation\ rate\ of\ the -\ \ geometry -\f[] +rtcSetGeometryTessellationRate \- sets the tessellation rate of the + geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryTessellationRate( -\ \ RTCGeometry\ geometry, -\ \ float\ tessellationRate +void rtcSetGeometryTessellationRate( + RTCGeometry geometry, + float tessellationRate ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryTessellationRate\f[] function sets the -tessellation rate (\f[C]tessellationRate\f[] argument) for the specified -geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryTessellationRate\f[R] function sets the +tessellation rate (\f[C]tessellationRate\f[R] argument) for the +specified geometry (\f[C]geometry\f[R] argument). The tessellation rate can only be set for flat curves and subdivision geometries. For curves, the tessellation rate specifies the number of ray\-facing @@ -36,7 +36,7 @@ quads along each edge. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_CURVE], [RTC_GEOMETRY_TYPE_SUBDIVISION] diff --git a/man/man3/rtcSetGeometryTimeRange.3embree3 b/man/man3/rtcSetGeometryTimeRange.3embree3 index c35db5d421..21be889b9f 100644 --- a/man/man3/rtcSetGeometryTimeRange.3embree3 +++ b/man/man3/rtcSetGeometryTimeRange.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTimeRange" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,25 +6,25 @@ .IP .nf \f[C] -rtcSetGeometryTimeRange\ \-\ sets\ the\ time\ range\ for\ a\ motion\ blur\ geometry -\f[] +rtcSetGeometryTimeRange \- sets the time range for a motion blur geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryTimeRange( -\ \ RTCGeometry\ geometry, -\ \ float\ startTime, -\ \ float\ endTime +void rtcSetGeometryTimeRange( + RTCGeometry geometry, + float startTime, + float endTime ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryTimeRange\f[] function sets a time range which +The \f[C]rtcSetGeometryTimeRange\f[R] function sets a time range which defines the start (and end time) of the first (and last) time step of a motion blur geometry. The time range is defined relative to the camera shutter interval [0,1] @@ -49,13 +49,13 @@ This time range feature will also allow geometries to appear and disappear during the camera shutter time if the specified time range is a sub range of [0,1]. .PP -Please also have a look at the \f[C]rtcSetGeometryTimeStepCount\f[] +Please also have a look at the \f[C]rtcSetGeometryTimeStepCount\f[R] function to see how to define the time steps for the specified time range. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryTimeStepCount] diff --git a/man/man3/rtcSetGeometryTimeStepCount.3embree3 b/man/man3/rtcSetGeometryTimeStepCount.3embree3 index 0b5e460457..6768865da5 100644 --- a/man/man3/rtcSetGeometryTimeStepCount.3embree3 +++ b/man/man3/rtcSetGeometryTimeStepCount.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTimeStepCount" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,41 +6,41 @@ .IP .nf \f[C] -rtcSetGeometryTimeStepCount\ \-\ sets\ the\ number\ of\ time\ steps\ of\ the -\ \ geometry -\f[] +rtcSetGeometryTimeStepCount \- sets the number of time steps of the + geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryTimeStepCount( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ timeStepCount +void rtcSetGeometryTimeStepCount( + RTCGeometry geometry, + unsigned int timeStepCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryTimeStepCount\f[] function sets the number of -time steps for multi\-segment motion blur (\f[C]timeStepCount\f[] -parameter) of the specified geometry (\f[C]geometry\f[] parameter). +The \f[C]rtcSetGeometryTimeStepCount\f[R] function sets the number of +time steps for multi\-segment motion blur (\f[C]timeStepCount\f[R] +parameter) of the specified geometry (\f[C]geometry\f[R] parameter). .PP -For triangle meshes (\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[]), quad meshes -(\f[C]RTC_GEOMETRY_TYPE_QUAD\f[]), curves -(\f[C]RTC_GEOMETRY_TYPE_CURVE\f[]), points -(\f[C]RTC_GEOMETRY_TYPE_POINT\f[]), and subdivision geometries -(\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[]), the number of time steps +For triangle meshes (\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[R]), quad meshes +(\f[C]RTC_GEOMETRY_TYPE_QUAD\f[R]), curves +(\f[C]RTC_GEOMETRY_TYPE_CURVE\f[R]), points +(\f[C]RTC_GEOMETRY_TYPE_POINT\f[R]), and subdivision geometries +(\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[R]), the number of time steps directly corresponds to the number of vertex buffer slots available -(\f[C]RTC_BUFFER_TYPE_VERTEX\f[] buffer type). +(\f[C]RTC_BUFFER_TYPE_VERTEX\f[R] buffer type). For these geometries, one vertex buffer per time step must be specified when creating multi\-segment motion blur geometries. .PP -For instance geometries (\f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[]), a +For instance geometries (\f[C]RTC_GEOMETRY_TYPE_INSTANCE\f[R]), a transformation must be specified for each time step (see -\f[C]rtcSetGeometryTransform\f[]). +\f[C]rtcSetGeometryTransform\f[R]). .PP For user geometries, the registered bounding callback function must provide a bounding box per primitive and time step, and the intersection @@ -49,7 +49,7 @@ motion\-blurred geometry at the ray time. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcSetGeometryTimeRange] diff --git a/man/man3/rtcSetGeometryTopologyCount.3embree3 b/man/man3/rtcSetGeometryTopologyCount.3embree3 index b2b13964dd..bd1cdaaeba 100644 --- a/man/man3/rtcSetGeometryTopologyCount.3embree3 +++ b/man/man3/rtcSetGeometryTopologyCount.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTimeStepCount" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,39 +6,39 @@ .IP .nf \f[C] -rtcSetGeometryTopologyCount\ \-\ sets\ the\ number\ of\ topologies\ of -\ \ a\ subdivision\ geometry -\f[] +rtcSetGeometryTopologyCount \- sets the number of topologies of + a subdivision geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryTopologyCount( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ topologyCount +void rtcSetGeometryTopologyCount( + RTCGeometry geometry, + unsigned int topologyCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryTopologyCount\f[] function sets the number of -topologies (\f[C]topologyCount\f[] parameter) for the specified -subdivision geometry (\f[C]geometry\f[] parameter). +The \f[C]rtcSetGeometryTopologyCount\f[R] function sets the number of +topologies (\f[C]topologyCount\f[R] parameter) for the specified +subdivision geometry (\f[C]geometry\f[R] parameter). The number of topologies of a subdivision geometry must be greater or equal to 1. .PP To use multiple topologies, first the number of topologies must be specified, then the individual topologies can be configured using -\f[C]rtcSetGeometrySubdivisionMode\f[] and by setting an index buffer -(\f[C]RTC_BUFFER_TYPE_INDEX\f[]) using the topology ID as the buffer +\f[C]rtcSetGeometrySubdivisionMode\f[R] and by setting an index buffer +(\f[C]RTC_BUFFER_TYPE_INDEX\f[R]) using the topology ID as the buffer slot. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_SUBDIVISION], [rtcSetGeometrySubdivisionMode] diff --git a/man/man3/rtcSetGeometryTransform.3embree3 b/man/man3/rtcSetGeometryTransform.3embree3 index a6c9fdc61c..dca14de764 100644 --- a/man/man3/rtcSetGeometryTransform.3embree3 +++ b/man/man3/rtcSetGeometryTransform.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTransform" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,47 +6,47 @@ .IP .nf \f[C] -rtcSetGeometryTransform\ \-\ sets\ the\ transformation\ for\ a\ particular -\ \ time\ step\ of\ an\ instance\ geometry -\f[] +rtcSetGeometryTransform \- sets the transformation for a particular + time step of an instance geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryTransform( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ timeStep, -\ \ enum\ RTCFormat\ format, -\ \ const\ float*\ xfm +void rtcSetGeometryTransform( + RTCGeometry geometry, + unsigned int timeStep, + enum RTCFormat format, + const float* xfm ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryTransform\f[] function sets the local\-to\-world -affine transformation (\f[C]xfm\f[] parameter) of an instance geometry -(\f[C]geometry\f[] parameter) for a particular time step -(\f[C]timeStep\f[] parameter). -The transformation is specified as a 3×4 matrix (3×3 linear +The \f[C]rtcSetGeometryTransform\f[R] function sets the local\-to\-world +affine transformation (\f[C]xfm\f[R] parameter) of an instance geometry +(\f[C]geometry\f[R] parameter) for a particular time step +(\f[C]timeStep\f[R] parameter). +The transformation is specified as a 3\[tmu]4 matrix (3\[tmu]3 linear transformation plus translation), for which the following formats -(\f[C]format\f[] parameter) are supported: +(\f[C]format\f[R] parameter) are supported: .IP \[bu] 2 -\f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[]: The 3×4 float matrix is laid out -in row\-major form. +\f[C]RTC_FORMAT_FLOAT3X4_ROW_MAJOR\f[R]: The 3\[tmu]4 float matrix is +laid out in row\-major form. .IP \[bu] 2 -\f[C]RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR\f[]: The 3×4 float matrix is laid -out in column\-major form. +\f[C]RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR\f[R]: The 3\[tmu]4 float matrix is +laid out in column\-major form. .IP \[bu] 2 -\f[C]RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR\f[]: The 3×4 float matrix is laid -out in column\-major form as a 4×4 homogeneous matrix with the last row -being equal to (0, 0, 0, 1). +\f[C]RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR\f[R]: The 3\[tmu]4 float matrix is +laid out in column\-major form as a 4\[tmu]4 homogeneous matrix with the +last row being equal to (0, 0, 0, 1). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_INSTANCE] diff --git a/man/man3/rtcSetGeometryTransformQuaternion.3embree3 b/man/man3/rtcSetGeometryTransformQuaternion.3embree3 index bd188c436e..be54b55350 100644 --- a/man/man3/rtcSetGeometryTransformQuaternion.3embree3 +++ b/man/man3/rtcSetGeometryTransformQuaternion.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTransformQuaternion" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,30 +6,30 @@ .IP .nf \f[C] -rtcSetGeometryTransformQuaternion\ \-\ sets\ the\ transformation\ for\ a\ particular -\ \ time\ step\ of\ an\ instance\ geometry\ as\ a\ decomposition\ of\ the -\ \ transformation\ matrix\ using\ quaternions\ to\ represent\ the\ rotation. -\f[] +rtcSetGeometryTransformQuaternion \- sets the transformation for a particular + time step of an instance geometry as a decomposition of the + transformation matrix using quaternions to represent the rotation. +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryTransformQuaternion( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ timeStep, -\ \ const\ struct\ RTCQuaternionDecomposition*\ qd +void rtcSetGeometryTransformQuaternion( + RTCGeometry geometry, + unsigned int timeStep, + const struct RTCQuaternionDecomposition* qd ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryTransformQuaternion\f[] function sets the -local\-to\-world affine transformation (\f[C]qd\f[] parameter) of an -instance geometry (\f[C]geometry\f[] parameter) for a particular time -step (\f[C]timeStep\f[] parameter). +The \f[C]rtcSetGeometryTransformQuaternion\f[R] function sets the +local\-to\-world affine transformation (\f[C]qd\f[R] parameter) of an +instance geometry (\f[C]geometry\f[R] parameter) for a particular time +step (\f[C]timeStep\f[R] parameter). The transformation is specified as a [RTCQuaternionDecomposition], which is a decomposition of an affine transformation that represents the rotational component of an affine transformation as a quaternion. @@ -38,22 +38,22 @@ spherical linear interpolation (such as a turning wheel). .PP For more information about the decomposition see [RTCQuaternionDecomposition]. -The quaternion given in the \f[C]RTCQuaternionDecomposition\f[] struct +The quaternion given in the \f[C]RTCQuaternionDecomposition\f[R] struct will be normalized internally. .PP For correct results, the transformation matrices for all time steps must -be set either using \f[C]rtcSetGeometryTransform\f[] or -\f[C]rtcSetGeometryTransformQuaternion\f[]. +be set either using \f[C]rtcSetGeometryTransform\f[R] or +\f[C]rtcSetGeometryTransformQuaternion\f[R]. Mixing both representations is not allowed. Spherical linear interpolation will be used, iff the transformation -matizes are set with \f[C]rtcSetGeometryTransformQuaternion\f[]. +matizes are set with \f[C]rtcSetGeometryTransformQuaternion\f[R]. .PP For an example of this feature see the tutorial [Quaternion Motion Blur]. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcInitQuaternionDecomposition], [rtcSetGeometryTransform] diff --git a/man/man3/rtcSetGeometryUserData.3embree3 b/man/man3/rtcSetGeometryUserData.3embree3 index 461714b510..9e8f43d9e0 100644 --- a/man/man3/rtcSetGeometryUserData.3embree3 +++ b/man/man3/rtcSetGeometryUserData.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryUserData" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,36 +6,36 @@ .IP .nf \f[C] -rtcSetGeometryUserData\ \-\ sets\ the\ user\-defined\ data\ pointer\ of\ the -\ \ geometry -\f[] +rtcSetGeometryUserData \- sets the user\-defined data pointer of the + geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryUserData(RTCGeometry\ geometry,\ void*\ userPtr); -\f[] +void rtcSetGeometryUserData(RTCGeometry geometry, void* userPtr); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryUserData\f[] function sets the user\-defined data -pointer (\f[C]userPtr\f[] argument) for a geometry (\f[C]geometry\f[] -argument). +The \f[C]rtcSetGeometryUserData\f[R] function sets the user\-defined +data pointer (\f[C]userPtr\f[R] argument) for a geometry +(\f[C]geometry\f[R] argument). This user data pointer is intended to be pointing to the -application\[aq]s representation of the geometry, and is passed to +application\[cq]s representation of the geometry, and is passed to various callback functions. The application can use this pointer inside the callback functions to access its geometry representation. .PP -The \f[C]rtcGetGeometryUserData\f[] function can be used to query an +The \f[C]rtcGetGeometryUserData\f[R] function can be used to query an already set user data pointer of a geometry. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetGeometryUserData] diff --git a/man/man3/rtcSetGeometryUserPrimitiveCount.3embree3 b/man/man3/rtcSetGeometryUserPrimitiveCount.3embree3 index 71aff7a2c5..6b61cedc80 100644 --- a/man/man3/rtcSetGeometryUserPrimitiveCount.3embree3 +++ b/man/man3/rtcSetGeometryUserPrimitiveCount.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryUserPrimitiveCount" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,31 +6,31 @@ .IP .nf \f[C] -rtcSetGeometryUserPrimitiveCount\ \-\ sets\ the\ number\ of\ primitives -\ \ of\ a\ user\-defined\ geometry -\f[] +rtcSetGeometryUserPrimitiveCount \- sets the number of primitives + of a user\-defined geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryUserPrimitiveCount( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ userPrimitiveCount +void rtcSetGeometryUserPrimitiveCount( + RTCGeometry geometry, + unsigned int userPrimitiveCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryUserPrimitiveCount\f[] function sets the number -of user\-defined primitives (\f[C]userPrimitiveCount\f[] parameter) of -the specified user\-defined geometry (\f[C]geometry\f[] parameter). +The \f[C]rtcSetGeometryUserPrimitiveCount\f[R] function sets the number +of user\-defined primitives (\f[C]userPrimitiveCount\f[R] parameter) of +the specified user\-defined geometry (\f[C]geometry\f[R] parameter). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [RTC_GEOMETRY_TYPE_USER] diff --git a/man/man3/rtcSetGeometryVertexAttributeCount.3embree3 b/man/man3/rtcSetGeometryVertexAttributeCount.3embree3 index 96af992a9a..2035bea6c1 100644 --- a/man/man3/rtcSetGeometryVertexAttributeCount.3embree3 +++ b/man/man3/rtcSetGeometryVertexAttributeCount.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryTimeStepCount" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,39 +6,39 @@ .IP .nf \f[C] -rtcSetGeometryVertexAttributeCount\ \-\ sets\ the\ number\ of\ vertex -\ \ attributes\ of\ the\ geometry -\f[] +rtcSetGeometryVertexAttributeCount \- sets the number of vertex + attributes of the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryVertexAttributeCount( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ vertexAttributeCount +void rtcSetGeometryVertexAttributeCount( + RTCGeometry geometry, + unsigned int vertexAttributeCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryVertexAttributeCount\f[] function sets the number -of slots (\f[C]vertexAttributeCount\f[] parameter) for vertex attribute -buffers (\f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[]) that can be used for -the specified geometry (\f[C]geometry\f[] parameter). +The \f[C]rtcSetGeometryVertexAttributeCount\f[R] function sets the +number of slots (\f[C]vertexAttributeCount\f[R] parameter) for vertex +attribute buffers (\f[C]RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE\f[R]) that can +be used for the specified geometry (\f[C]geometry\f[R] parameter). .PP This function is supported only for triangle meshes -(\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[]), quad meshes -(\f[C]RTC_GEOMETRY_TYPE_QUAD\f[]), curves -(\f[C]RTC_GEOMETRY_TYPE_CURVE\f[]), points -(\f[C]RTC_GEOMETRY_TYPE_POINT\f[]), and subdivision geometries -(\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[]). +(\f[C]RTC_GEOMETRY_TYPE_TRIANGLE\f[R]), quad meshes +(\f[C]RTC_GEOMETRY_TYPE_QUAD\f[R]), curves +(\f[C]RTC_GEOMETRY_TYPE_CURVE\f[R]), points +(\f[C]RTC_GEOMETRY_TYPE_POINT\f[R]), and subdivision geometries +(\f[C]RTC_GEOMETRY_TYPE_SUBDIVISION\f[R]). .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [RTCBufferType] diff --git a/man/man3/rtcSetGeometryVertexAttributeTopology.3embree3 b/man/man3/rtcSetGeometryVertexAttributeTopology.3embree3 index 5342fb1d14..c4cbd5e25a 100644 --- a/man/man3/rtcSetGeometryVertexAttributeTopology.3embree3 +++ b/man/man3/rtcSetGeometryVertexAttributeTopology.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetGeometryVertexAttributeTopology" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,37 +6,38 @@ .IP .nf \f[C] -rtcSetGeometryVertexAttributeTopology\ \-\ binds\ a\ vertex -\ \ attribute\ to\ a\ topology\ of\ the\ geometry -\f[] +rtcSetGeometryVertexAttributeTopology \- binds a vertex + attribute to a topology of the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetGeometryVertexAttributeTopology( -\ \ RTCGeometry\ geometry, -\ \ unsigned\ int\ vertexAttributeID, -\ \ unsigned\ int\ topologyID +void rtcSetGeometryVertexAttributeTopology( + RTCGeometry geometry, + unsigned int vertexAttributeID, + unsigned int topologyID ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetGeometryVertexAttributeTopology\f[] function binds a -vertex attribute buffer slot (\f[C]vertexAttributeID\f[] argument) to a -topology (\f[C]topologyID\f[] argument) for the specified subdivision -geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetGeometryVertexAttributeTopology\f[R] function binds a +vertex attribute buffer slot (\f[C]vertexAttributeID\f[R] argument) to a +topology (\f[C]topologyID\f[R] argument) for the specified subdivision +geometry (\f[C]geometry\f[R] argument). Standard vertex buffers are always bound to the default topology (topology 0) and cannot be bound differently. A vertex attribute buffer always uses the topology it is bound to when -used in the \f[C]rtcInterpolate\f[] and \f[C]rtcInterpolateN\f[] calls. +used in the \f[C]rtcInterpolate\f[R] and \f[C]rtcInterpolateN\f[R] +calls. .PP -A topology with ID \f[C]i\f[] consists of a subdivision mode set through -\f[C]rtcSetGeometrySubdivisionMode\f[] and the index buffer bound to the -index buffer slot \f[C]i\f[]. +A topology with ID \f[C]i\f[R] consists of a subdivision mode set +through \f[C]rtcSetGeometrySubdivisionMode\f[R] and the index buffer +bound to the index buffer slot \f[C]i\f[R]. This index buffer can assign indices for each face of the subdivision geometry that are different to the indices of the default topology. These new indices can for example be used to introduce additional @@ -45,7 +46,7 @@ subdivision geometry. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometrySubdivisionMode], [rtcInterpolate], [rtcInterpolateN] diff --git a/man/man3/rtcSetNewGeometryBuffer.3embree3 b/man/man3/rtcSetNewGeometryBuffer.3embree3 index 2ca2e691c6..cdd068f4ed 100644 --- a/man/man3/rtcSetNewGeometryBuffer.3embree3 +++ b/man/man3/rtcSetNewGeometryBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetNewGeometryBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,39 +6,39 @@ .IP .nf \f[C] -rtcSetNewGeometryBuffer\ \-\ creates\ and\ assigns\ a\ new\ data\ buffer\ to -\ \ the\ geometry -\f[] +rtcSetNewGeometryBuffer \- creates and assigns a new data buffer to + the geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void*\ rtcSetNewGeometryBuffer( -\ \ RTCGeometry\ geometry, -\ \ enum\ RTCBufferType\ type, -\ \ unsigned\ int\ slot, -\ \ enum\ RTCFormat\ format, -\ \ size_t\ byteStride, -\ \ size_t\ itemCount +void* rtcSetNewGeometryBuffer( + RTCGeometry geometry, + enum RTCBufferType type, + unsigned int slot, + enum RTCFormat format, + size_t byteStride, + size_t itemCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetNewGeometryBuffer\f[] function creates a new data buffer -of specified format (\f[C]format\f[] argument), byte stride -(\f[C]byteStride\f[] argument), and number of items (\f[C]itemCount\f[] -argument), and assigns it to a geometry buffer slot (\f[C]type\f[] and -\f[C]slot\f[] argument) of the specified geometry (\f[C]geometry\f[] -argument). +The \f[C]rtcSetNewGeometryBuffer\f[R] function creates a new data buffer +of specified format (\f[C]format\f[R] argument), byte stride +(\f[C]byteStride\f[R] argument), and number of items +(\f[C]itemCount\f[R] argument), and assigns it to a geometry buffer slot +(\f[C]type\f[R] and \f[C]slot\f[R] argument) of the specified geometry +(\f[C]geometry\f[R] argument). The buffer data is managed internally and automatically freed when the geometry is destroyed. .PP -The byte stride (\f[C]byteStride\f[] argument) must be aligned to 4 -bytes; otherwise the \f[C]rtcSetNewGeometryBuffer\f[] function will +The byte stride (\f[C]byteStride\f[R] argument) must be aligned to 4 +bytes; otherwise the \f[C]rtcSetNewGeometryBuffer\f[R] function will fail. .PP The allocated buffer will be automatically over\-allocated slightly when @@ -47,7 +47,7 @@ should be readable using 16\-byte SSE load instructions. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer] diff --git a/man/man3/rtcSetSceneBuildQuality.3embree3 b/man/man3/rtcSetSceneBuildQuality.3embree3 index 55f2983b0c..9dd942feeb 100644 --- a/man/man3/rtcSetSceneBuildQuality.3embree3 +++ b/man/man3/rtcSetSceneBuildQuality.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetSceneBuildQuality" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,53 +6,52 @@ .IP .nf \f[C] -rtcSetSceneBuildQuality\ \-\ sets\ the\ build\ quality\ for -\ \ the\ scene -\f[] +rtcSetSceneBuildQuality \- sets the build quality for + the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetSceneBuildQuality( -\ \ RTCScene\ scene, -\ \ enum\ RTCBuildQuality\ quality +void rtcSetSceneBuildQuality( + RTCScene scene, + enum RTCBuildQuality quality ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetSceneBuildQuality\f[] function sets the build quality -(\f[C]quality\f[] argument) for the specified scene (\f[C]scene\f[] +The \f[C]rtcSetSceneBuildQuality\f[R] function sets the build quality +(\f[C]quality\f[R] argument) for the specified scene (\f[C]scene\f[R] argument). Possible values for the build quality are: .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_LOW\f[]: Create lower quality data structures, -e.g. -for dynamic scenes. +\f[C]RTC_BUILD_QUALITY_LOW\f[R]: Create lower quality data structures, +e.g.\ for dynamic scenes. A two\-level spatial index structure is built when enabling this mode, which supports fast partial scene updates, and allows for setting a per\-geometry build quality through the -\f[C]rtcSetGeometryBuildQuality\f[] function. +\f[C]rtcSetGeometryBuildQuality\f[R] function. .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_MEDIUM\f[]: Default build quality for most +\f[C]RTC_BUILD_QUALITY_MEDIUM\f[R]: Default build quality for most usages. Gives a good compromise between build and render performance. .IP \[bu] 2 -\f[C]RTC_BUILD_QUALITY_HIGH\f[]: Create higher quality data structures +\f[C]RTC_BUILD_QUALITY_HIGH\f[R]: Create higher quality data structures for final\-frame rendering. For certain geometry types this enables a spatial split BVH. .PP Selecting a higher build quality results in better rendering performance but slower scene commit times. The default build quality for a scene is -\f[C]RTC_BUILD_QUALITY_MEDIUM\f[]. +\f[C]RTC_BUILD_QUALITY_MEDIUM\f[R]. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryBuildQuality] diff --git a/man/man3/rtcSetSceneFlags.3embree3 b/man/man3/rtcSetSceneFlags.3embree3 index 4bfccfae6e..1f10e10559 100644 --- a/man/man3/rtcSetSceneFlags.3embree3 +++ b/man/man3/rtcSetSceneFlags.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetSceneFlags" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,49 +6,49 @@ .IP .nf \f[C] -rtcSetSceneFlags\ \-\ sets\ the\ flags\ for\ the\ scene -\f[] +rtcSetSceneFlags \- sets the flags for the scene +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetSceneFlags(RTCScene\ scene,\ enum\ RTCSceneFlags\ flags); -\f[] +void rtcSetSceneFlags(RTCScene scene, enum RTCSceneFlags flags); +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetSceneFlags\f[] function sets the scene flags -(\f[C]flags\f[] argument) for the specified scene (\f[C]scene\f[] +The \f[C]rtcSetSceneFlags\f[R] function sets the scene flags +(\f[C]flags\f[R] argument) for the specified scene (\f[C]scene\f[R] argument). Possible scene flags are: .IP \[bu] 2 -\f[C]RTC_SCENE_FLAG_NONE\f[]: No flags set. +\f[C]RTC_SCENE_FLAG_NONE\f[R]: No flags set. .IP \[bu] 2 -\f[C]RTC_SCENE_FLAG_DYNAMIC\f[]: Provides better build performance for +\f[C]RTC_SCENE_FLAG_DYNAMIC\f[R]: Provides better build performance for dynamic scenes (but also higher memory consumption). .IP \[bu] 2 -\f[C]RTC_SCENE_FLAG_COMPACT\f[]: Uses compact acceleration structures +\f[C]RTC_SCENE_FLAG_COMPACT\f[R]: Uses compact acceleration structures and avoids algorithms that consume much memory. .IP \[bu] 2 -\f[C]RTC_SCENE_FLAG_ROBUST\f[]: Uses acceleration structures that allow +\f[C]RTC_SCENE_FLAG_ROBUST\f[R]: Uses acceleration structures that allow for robust traversal, and avoids optimizations that reduce arithmetic accuracy. This mode is typically used for avoiding artifacts caused by rays shooting through edges of neighboring primitives. .IP \[bu] 2 -\f[C]RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION\f[]: Enables support for a +\f[C]RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION\f[R]: Enables support for a filter function inside the intersection context for this scene. See Section [rtcInitIntersectContext] for more details. .PP -Multiple flags can be enabled using an \f[C]or\f[] operation, e.g. -\f[C]RTC_SCENE_FLAG_COMPACT\ |\ RTC_SCENE_FLAG_ROBUST\f[]. +Multiple flags can be enabled using an \f[C]or\f[R] operation, +e.g.\ \f[C]RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST\f[R]. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcGetSceneFlags] diff --git a/man/man3/rtcSetSceneProgressMonitorFunction.3embree3 b/man/man3/rtcSetSceneProgressMonitorFunction.3embree3 index eeec6efd0a..44747f60b4 100644 --- a/man/man3/rtcSetSceneProgressMonitorFunction.3embree3 +++ b/man/man3/rtcSetSceneProgressMonitorFunction.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetSceneProgressMonitorFunction" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,27 +6,27 @@ .IP .nf \f[C] -rtcSetSceneProgressMonitorFunction\ \-\ registers\ a\ callback -\ \ to\ track\ build\ progress -\f[] +rtcSetSceneProgressMonitorFunction \- registers a callback + to track build progress +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -typedef\ bool\ (*RTCProgressMonitorFunction)( -\ \ void*\ ptr, -\ \ double\ n +typedef bool (*RTCProgressMonitorFunction)( + void* ptr, + double n ); -void\ rtcSetSceneProgressMonitorFunction( -\ \ RTCScene\ scene, -\ \ RTCProgressMonitorFunction\ progress, -\ \ void*\ userPtr +void rtcSetSceneProgressMonitorFunction( + RTCScene scene, + RTCProgressMonitorFunction progress, + void* userPtr ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP @@ -34,34 +34,34 @@ Embree supports a progress monitor callback mechanism that can be used to report progress of hierarchy build operations and to cancel build operations. .PP -The \f[C]rtcSetSceneProgressMonitorFunction\f[] registers a progress -monitor callback function (\f[C]progress\f[] argument) with payload -(\f[C]userPtr\f[] argument) for the specified scene (\f[C]scene\f[] +The \f[C]rtcSetSceneProgressMonitorFunction\f[R] registers a progress +monitor callback function (\f[C]progress\f[R] argument) with payload +(\f[C]userPtr\f[R] argument) for the specified scene (\f[C]scene\f[R] argument). .PP Only a single callback function can be registered per scene, and further invocations overwrite the previously set callback function. -Passing \f[C]NULL\f[] as function pointer disables the registered +Passing \f[C]NULL\f[R] as function pointer disables the registered callback function. .PP Once registered, Embree will invoke the callback function multiple times during hierarchy build operations of the scene, by passing the payload -as set at registration time (\f[C]userPtr\f[] argument), and a double in -the range [0, 1] which estimates the progress of the operation -(\f[C]n\f[] argument). +as set at registration time (\f[C]userPtr\f[R] argument), and a double +in the range [0,\[u2006]1] which estimates the progress of the operation +(\f[C]n\f[R] argument). The callback function might be called from multiple threads concurrently. .PP -When returning \f[C]true\f[] from the callback function, Embree will +When returning \f[C]true\f[R] from the callback function, Embree will continue the build operation normally. -When returning \f[C]false\f[], Embree will cancel the build operation -with the \f[C]RTC_ERROR_CANCELLED\f[] error code. +When returning \f[C]false\f[R], Embree will cancel the build operation +with the \f[C]RTC_ERROR_CANCELLED\f[R] error code. Issuing multiple cancel requests for the same build operation is allowed. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewScene] diff --git a/man/man3/rtcSetSharedGeometryBuffer.3embree3 b/man/man3/rtcSetSharedGeometryBuffer.3embree3 index 608514b041..4f95167afd 100644 --- a/man/man3/rtcSetSharedGeometryBuffer.3embree3 +++ b/man/man3/rtcSetSharedGeometryBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcSetSharedGeometryBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,48 +6,48 @@ .IP .nf \f[C] -rtcSetSharedGeometryBuffer\ \-\ assigns\ a\ view\ of\ a\ shared\ data\ buffer -\ \ to\ a\ geometry -\f[] +rtcSetSharedGeometryBuffer \- assigns a view of a shared data buffer + to a geometry +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcSetSharedGeometryBuffer( -\ \ RTCGeometry\ geometry, -\ \ enum\ RTCBufferType\ type, -\ \ unsigned\ int\ slot, -\ \ enum\ RTCFormat\ format, -\ \ const\ void*\ ptr, -\ \ size_t\ byteOffset, -\ \ size_t\ byteStride, -\ \ size_t\ itemCount +void rtcSetSharedGeometryBuffer( + RTCGeometry geometry, + enum RTCBufferType type, + unsigned int slot, + enum RTCFormat format, + const void* ptr, + size_t byteOffset, + size_t byteStride, + size_t itemCount ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcSetSharedGeometryBuffer\f[] function binds a view of a -shared user\-managed data buffer (\f[C]ptr\f[] argument) to a geometry -buffer type and slot (\f[C]type\f[] and \f[C]slot\f[] argument) of the -specified geometry (\f[C]geometry\f[] argument). +The \f[C]rtcSetSharedGeometryBuffer\f[R] function binds a view of a +shared user\-managed data buffer (\f[C]ptr\f[R] argument) to a geometry +buffer type and slot (\f[C]type\f[R] and \f[C]slot\f[R] argument) of the +specified geometry (\f[C]geometry\f[R] argument). .PP One can specify the start of the first buffer element in bytes -(\f[C]byteOffset\f[] argument), the byte stride between individual -buffer elements (\f[C]byteStride\f[] argument), the format of the buffer -elements (\f[C]format\f[] argument), and the number of elements to bind -(\f[C]itemCount\f[]). +(\f[C]byteOffset\f[R] argument), the byte stride between individual +buffer elements (\f[C]byteStride\f[R] argument), the format of the +buffer elements (\f[C]format\f[R] argument), and the number of elements +to bind (\f[C]itemCount\f[R]). .PP -The start address (\f[C]byteOffset\f[] argument) and stride -(\f[C]byteStride\f[] argument) must be both aligned to 4 bytes; -otherwise the \f[C]rtcSetGeometryBuffer\f[] function will fail. +The start address (\f[C]byteOffset\f[R] argument) and stride +(\f[C]byteStride\f[R] argument) must be both aligned to 4 bytes; +otherwise the \f[C]rtcSetSharedGeometryBuffer\f[R] function will fail. .IP .nf \f[C] -\f[] +\f[R] .fi .PP The buffer data must remain valid for as long as the buffer may be used, @@ -56,13 +56,13 @@ required. .PP Sharing buffers can significantly reduce the memory required by the application, thus we recommend using this feature. -When enabling the \f[C]RTC_SCENE_COMPACT\f[] scene flag, the spatial -index structures index into the vertex buffer, resulting in even higher -memory savings. +When enabling the \f[C]RTC_SCENE_FLAG_COMPACT\f[R] scene flag, the +spatial index structures index into the vertex buffer, resulting in even +higher memory savings. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcSetGeometryBuffer], [rtcSetNewGeometryBuffer] diff --git a/man/man3/rtcUpdateGeometryBuffer.3embree3 b/man/man3/rtcUpdateGeometryBuffer.3embree3 index c98f22c5a5..02bf091de9 100644 --- a/man/man3/rtcUpdateGeometryBuffer.3embree3 +++ b/man/man3/rtcUpdateGeometryBuffer.3embree3 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 1.17.0.3 +.\" Automatically generated by Pandoc 2.5 .\" .TH "rtcUpdateGeometryBuffer" "3" "" "" "Embree Ray Tracing Kernels 3" .hy @@ -6,39 +6,39 @@ .IP .nf \f[C] -rtcUpdateGeometryBuffer\ \-\ marks\ a\ buffer\ view\ bound\ to\ the\ geometry -\ \ as\ modified -\f[] +rtcUpdateGeometryBuffer \- marks a buffer view bound to the geometry + as modified +\f[R] .fi .SS SYNOPSIS .IP .nf \f[C] -#include\ +#include -void\ rtcUpdateGeometryBuffer( -\ \ RTCGeometry\ geometry, -\ \ enum\ RTCBufferType\ type, -\ \ unsigned\ int\ slot +void rtcUpdateGeometryBuffer( + RTCGeometry geometry, + enum RTCBufferType type, + unsigned int slot ); -\f[] +\f[R] .fi .SS DESCRIPTION .PP -The \f[C]rtcUpdateGeometryBuffer\f[] function marks the buffer view -bound to the specified buffer type and slot (\f[C]type\f[] and -\f[C]slot\f[] argument) of a geometry (\f[C]geometry\f[] argument) as +The \f[C]rtcUpdateGeometryBuffer\f[R] function marks the buffer view +bound to the specified buffer type and slot (\f[C]type\f[R] and +\f[C]slot\f[R] argument) of a geometry (\f[C]geometry\f[R] argument) as modified. .PP If a data buffer is changed by the application, the -\f[C]rtcUpdateGeometryBuffer\f[] call must be invoked for that buffer. +\f[C]rtcUpdateGeometryBuffer\f[R] call must be invoked for that buffer. Each buffer view assigned to a buffer slot is initially marked as modified, thus this function needs to be called only when doing buffer -modifications after the first \f[C]rtcCommitScene\f[]. +modifications after the first \f[C]rtcCommitScene\f[R]. .SS EXIT STATUS .PP On failure an error code is set that can be queried using -\f[C]rtcGetDeviceError\f[]. +\f[C]rtcGetDeviceError\f[R]. .SS SEE ALSO .PP [rtcNewGeometry], [rtcCommitScene] diff --git a/readme.pdf b/readme.pdf index 94ef601abf..01c869b1ca 100644 Binary files a/readme.pdf and b/readme.pdf differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..596848973d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +numpy +sympy +math diff --git a/scripts/bdba.sh b/scripts/bdba.sh new file mode 100755 index 0000000000..88308df194 --- /dev/null +++ b/scripts/bdba.sh @@ -0,0 +1,61 @@ +#!/bin/bash +## Copyright 2019-2021 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +files=$1 +jq_tool="$SHARED_TOOLS_PATH/jq-linux64" +logfile="bdba.log" +failed=0 +for file_path in $files ; do + echo -e "\n" >> $logfile + #upload file + upload_response=`curl -k -H "Authorization: Bearer $BDBA_TOKEN" -H "Group: $BDBA_GROUP" -T $file_path "$BDBA_SERVER/api/upload/"` + product_id=`echo "$upload_response" | $jq_tool -r '.results.product_id'` + if [ $product_id == "null" ]; then + echo "Cannot upload file $file_path" >> $logfile + failed=1 + continue + fi + report_url=`echo "$upload_response" | $jq_tool -r '.results.report_url'` + + echo "Scan upload of $file_path completed - product id: $product_id ($report_url)" >> $logfile + + set +e + MAX_RETRY=600 + + RETRY_COUNTER="0" + while [ $RETRY_COUNTER -lt $MAX_RETRY ]; do + response=`curl -s -X GET -H "Authorization: Bearer $BDBA_TOKEN" -k $BDBA_SERVER/api/product/$product_id/` + CMD_RETURN_CODE=$? + + status=`echo "$response" | $jq_tool -r '.results.status'` + verdict=`echo "$response" | $jq_tool -r '.results.summary.verdict.short'` + if [ $CMD_RETURN_CODE == 0 ] && [[ $status == "R" ]]; then + echo $response | python -m json.tool + echo "Verdict: $verdict" >> $logfile + if [ $verdict != "Pass" ] && [ $verdict != "N/A" ]; then + echo "There is a problem - please check report $report_url" >> $logfile + failed=1 + fi + # Download pdf report & components list + file_name=`basename "$file_path"` + echo "File name: $file_name" + curl -H "Authorization: Bearer $BDBA_TOKEN" -k $BDBA_SERVER/api/product/$product_id/pdf-report?cvss_version=3 -o ${file_name}_report.pdf + curl -H "Authorization: Bearer $BDBA_TOKEN" -k $BDBA_SERVER/api/product/$product_id/csv-libs -o ${file_name}_components.csv + break + fi + RETRY_COUNTER=$[$RETRY_COUNTER+1] + echo "Scan not finished yet, [$RETRY_COUNTER/$MAX_RETRY] - checking again ... " + sleep 20 + done + + set -e + if [ $RETRY_COUNTER -ge $MAX_RETRY ]; then + failed=62 + continue + fi +done + +cat $logfile + +exit $failed diff --git a/scripts/benchmark.py b/scripts/benchmark.py deleted file mode 100755 index a63201d618..0000000000 --- a/scripts/benchmark.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/python - -## Copyright 2009-2020 Intel Corporation -## SPDX-License-Identifier: Apache-2.0 - -import sys -import os -import re - -########################## configuration ########################## - -dash = '/' -statDir = 'stat' -name = '' -models = [] - -########################## rendering ########################## - -def baseName(name,model): - return name + '_' + model - -def render(name,modelname,model): - executable = tutorial - base = baseName(name,modelname) - os.system('mkdir -p ' + statDir) - logFile = statDir + dash + base + '.log' - if not os.path.exists(logFile): - command = executable - command += ' -c ' + model - for arg in args: - command += ' ' + arg - command += ' -rtcore verbose=2 -benchmark 8 32 > ' + logFile - os.system(command) - -def renderLoop(): - avgBase = baseName(name,'average') - memory [avgBase] = 0 - buildperf[avgBase] = 0 - buildperf_gain[avgBase] = 0 - sah [avgBase] = 0 - fps_avg [avgBase] = 0 - fps_sigma[avgBase] = 0 - fps_gain [avgBase] = 0 - printHeader() - for (modelname,model) in models: - sys.stdout.write(' ' + '{0:<55}'.format(modelname) + ' | ') - render(name,modelname,model) - extract(name,modelname,'') - printData(name,modelname) - -########################## data extraction ########################## - -memory = {} -memory_gain = {} -buildperf = {} -buildperf_gain = {} -sah = {} -sah_gain = {} -fps_avg = {} -fps_sigma = {} -fps_gain = {} - -def extract(name,modelname,prevname): - base = baseName(name,modelname) - prevBase = baseName(prevname,modelname) - avgBase = baseName(name,'average') - logFileName = statDir + dash + base + '.log' - memory [base] = 0 - memory_gain[base] = 0 - buildperf[base] = 0 - buildperf_gain[base] = 0 - sah [base] = 0 - sah_gain [base] = 0 - fps_avg [base] = 0 - fps_sigma[base] = 0 - fps_gain [base] = 0 - try: - logFile = open(logFileName, 'r') - for line in logFile: - if line.count('BENCHMARK_BUILD ') == 1: - numbers = line[(line.index('BENCHMARK_BUILD ')+16):].split(" ") - buildperf[base] += float(numbers[1]) - if (prevname != ''): - buildperf_gain[base] = 100.0*buildperf[base]/buildperf[prevBase]-100.0 - sah [base] += float(numbers[2]) - if (prevname != ''): - sah_gain[base] = 100.0*sah[base]/sah[prevBase]-100.0 - memory[base] += float(numbers[3]) - if (prevname != ''): - memory_gain[base] = 100.0*memory[base]/memory[prevBase]-100.0 - if line.count('BENCHMARK_RENDER_AVG ') == 1: - numbers = line[21:].split(" ") - fps_avg[base] = float(numbers[0]) - if (prevname != ''): - fps_gain[base] = 100.0*fps_avg[base]/fps_avg[prevBase]-100.0 - if line.count('BENCHMARK_RENDER_AVG_SIGMA ') == 1: - numbers = line[27:].split(" ") - fps_sigma[base] = float(numbers[0]) - except IOError : - print('cannot open ' + logFileName) - - memory [avgBase] += memory [base] / len(models) - buildperf[avgBase] += buildperf[base] / len(models) - sah [avgBase] += sah [base] / len(models) - fps_avg [avgBase] += fps_avg [base] / len(models) - fps_sigma[avgBase] += fps_sigma[base] / len(models) - if (prevname != ''): - sah_gain [avgBase] += sah_gain [base] / len(models) - memory_gain [avgBase] += memory_gain [base] / len(models) - fps_gain [avgBase] += fps_gain [base] / len(models) - buildperf_gain [avgBase] += buildperf_gain [base] / len(models) - -# Extract all data -def extractLoop(): - prevname = '' - for name in names: - avgBase = baseName(name,'average') - memory [avgBase] = 0 - memory_gain[avgBase] = 0 - buildperf[avgBase] = 0 - buildperf_gain [avgBase] = 0 - sah [avgBase] = 0 - sah_gain [avgBase] = 0 - fps_avg [avgBase] = 0 - fps_sigma[avgBase] = 0 - fps_gain [avgBase] = 0 - for (modelname,model) in models: - extract(name,modelname,prevname) - prevname = name - -def printData(name,modelname): - base = baseName(name,modelname) - line = (' %#6.1f MB' % (1E-6*memory[base])) - line += (' (%#+6.2f%%)' % memory_gain[base]) - line += (' %#8.2f M/s' % (1E-6*buildperf[base])) - line += (' (%#+6.2f%%)' % buildperf_gain[base]) - line += (' %#7.3f ' % sah[base]) - line += (' (%#+6.2f%%)' % sah_gain[base]) - line += (' %#7.3f fps' % fps_avg[base]) - line += (' +/-%#6.3f%% ' % (100.0*fps_sigma[base]/fps_avg[base])) - line += (' (%#+6.2f%%)' % fps_gain[base]) - line += '\n' - sys.stdout.write(line) - -def printHeader(): - tableWidth = 55 + 102 - line = ' ' + '{0:<55}'.format('') + ' | Memory Build SAH Render' - print(line) - line = '' - while (len(line) < tableWidth): line = line + '-' - print(line) - -def printDataLoop(): - print('') - printHeader() - for (modelname,model) in models: - print(modelname) - for name in names: - sys.stdout.write(' ' + '{0:<55}'.format(name) + ' | ') - printData(name,modelname) - if len(models) > 1: - print('average') - for name in names: - sys.stdout.write(' ' + '{0:<55}'.format(name) + ' | ') - printData(name,'average') - - print('') - -########################## command line parsing ########################## - -def printUsage(): - sys.stderr.write('Usage: ' + sys.argv[0] + ' run models name tutorialXX args\n') - sys.stderr.write(' ' + sys.argv[0] + ' print models name1 name2 ...\n') - sys.exit(1) - -def readModelsFile(models_file): - global models - path, basename = os.path.split(models_file) - with open(models_file, 'r') as f: - lines = f.readlines() - for line in lines: - line = line.strip('\n') - if line == "": continue; - if line.startswith("#"): continue; - (name,args) = line.split(' ',1); - args2 = os.path.join(path,args.lstrip(' ')) - models += [(name,args2)] - -if len(sys.argv) < 2: - printUsage() - sys.exit(1) - -if sys.argv[1] == 'run': - if len(sys.argv) < 4: - printUsage() - sys.exit(1) - models_file = sys.argv[2] - readModelsFile(models_file) - name = sys.argv[3] - tutorial = sys.argv[4] - args = sys.argv[5:] - renderLoop() - sys.exit(1) - -if sys.argv[1] == 'print': - if len(sys.argv) < 5: - printUsage() - sys.exit(1) - models_file = sys.argv[2] - readModelsFile(models_file) - names = sys.argv[3:] - extractLoop() - printDataLoop() - sys.exit(1) - -printUsage() -sys.exit(1) diff --git a/scripts/check_symbols.sh b/scripts/check_symbols.sh index d1a59332d3..d37dde97cc 100755 --- a/scripts/check_symbols.sh +++ b/scripts/check_symbols.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # check version of symbols diff --git a/scripts/cpp-patch.py b/scripts/cpp-patch.py index 9595203609..cdb8c67fe2 100755 --- a/scripts/cpp-patch.py +++ b/scripts/cpp-patch.py @@ -1,6 +1,6 @@ #!/usr/bin/python -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 import sys diff --git a/scripts/generate_motion_derivative_coefficients.py b/scripts/generate_motion_derivative_coefficients.py old mode 100644 new mode 100755 index 51c2e76f56..d2f8c579ad --- a/scripts/generate_motion_derivative_coefficients.py +++ b/scripts/generate_motion_derivative_coefficients.py @@ -1,6 +1,6 @@ -#!/usr/bin/python +#!/usr/bin/env python3 -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 import sympy as sp @@ -168,4 +168,4 @@ def _print_Pow(self, expr): P = sp.MatrixSymbol('p', len(params), 1) param_map = dict(zip(params, P)) B = A.xreplace(param_map) -codegen(('motion_derivative_coefficients', sp.Eq(R,B)), language='c', printer=customprinter, prefix='motion_derivative_coefficients', to_files=True) \ No newline at end of file +codegen(('motion_derivative_coefficients', sp.Eq(R,B)), language='c', printer=customprinter, prefix='motion_derivative_coefficients', to_files=True) diff --git a/scripts/install_linux/embree-vars.csh b/scripts/install_linux/embree-vars.csh index 0d1e58ffd4..7cffc3243f 100755 --- a/scripts/install_linux/embree-vars.csh +++ b/scripts/install_linux/embree-vars.csh @@ -1,6 +1,6 @@ #!/bin/tcsh -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 pushd . > /dev/null diff --git a/scripts/install_linux/embree-vars.sh b/scripts/install_linux/embree-vars.sh index 19068468c9..33cec20b92 100755 --- a/scripts/install_linux/embree-vars.sh +++ b/scripts/install_linux/embree-vars.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 pushd . > /dev/null diff --git a/scripts/install_macosx/embree-vars.csh b/scripts/install_macosx/embree-vars.csh index 85f656b6de..3d544762d0 100755 --- a/scripts/install_macosx/embree-vars.csh +++ b/scripts/install_macosx/embree-vars.csh @@ -1,6 +1,6 @@ #!/bin/tcsh -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 pushd . > /dev/null diff --git a/scripts/install_macosx/embree-vars.sh b/scripts/install_macosx/embree-vars.sh index a6d0be2cc5..a30f74abfd 100755 --- a/scripts/install_macosx/embree-vars.sh +++ b/scripts/install_macosx/embree-vars.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 pushd . > /dev/null diff --git a/scripts/install_macosx/uninstall.command b/scripts/install_macosx/uninstall.command deleted file mode 100755 index 7834d35d61..0000000000 --- a/scripts/install_macosx/uninstall.command +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -## Copyright 2009-2020 Intel Corporation -## SPDX-License-Identifier: Apache-2.0 - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR/../.. - -IFS=$'\n' -filter='opt/local/include/\|opt/local/lib/\|opt/local/share/man/\|Applications/Embree@EMBREE_VERSION_MAJOR@' -FILES+=($(pkgutil --files com.intel.embree-@EMBREE_VERSION@.examples | grep -e $filter | tail -r)) -FILES+=($(pkgutil --files com.intel.embree-@EMBREE_VERSION@.lib | grep -e $filter | tail -r)) -FILES+=($(pkgutil --files com.intel.embree-@EMBREE_VERSION@.devel | grep -e $filter | tail -r)) -unset IFS - -# exit if no files found -if [ ${#FILES[@]} -eq 0 ]; then - printf "Embree @EMBREE_VERSION@ not installed!\n" - exit -fi - -# first print all files that would get removed -echo Uninstalling Embree @EMBREE_VERSION@ will remove the following files: -PWD=`pwd` -if [ "$PWD" != "/" ]; then - PWD=$PWD/ -fi -for f in "${FILES[@]}"; do - printf " %s%s\n" $PWD "$f" -done - -echo "Do you wish to uninstall Embree @EMBREE_VERSION@ by removing these files?" -select yn in "Yes" "No"; do - case $yn in - Yes ) break;; - No ) exit;; - esac -done - -# now remove files -echo Uninstalling Embree @EMBREE_VERSION@ ... -for f in "${FILES[@]}"; do - sudo /bin/rm -vd "$f" -done - -sudo /usr/sbin/pkgutil --forget com.intel.embree-@EMBREE_VERSION@.examples -sudo /usr/sbin/pkgutil --forget com.intel.embree-@EMBREE_VERSION@.devel -sudo /usr/sbin/pkgutil --forget com.intel.embree-@EMBREE_VERSION@.lib diff --git a/scripts/klocwork_build.sh b/scripts/klocwork_build.sh index c122ea4bbf..c29be20b7b 100755 --- a/scripts/klocwork_build.sh +++ b/scripts/klocwork_build.sh @@ -1,20 +1,23 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set -e -KW_PATH=/NAS/tools/kw KW_SERVER_PATH=$KW_PATH/server KW_CLIENT_PATH=$KW_PATH/client export KLOCWORK_LTOKEN=/tmp/ltoken echo "$KW_SERVER_IP;$KW_SERVER_PORT;$KW_USER;$KW_LTOKEN" > $KLOCWORK_LTOKEN + +mkdir -p $CI_PROJECT_DIR/klocwork +log_file=$CI_PROJECT_DIR/klocwork/build.log + make clean > /dev/null -$KW_CLIENT_PATH/bin/kwinject -w -o buildspec.txt make -j 8 -$KW_SERVER_PATH/bin/kwbuildproject --force --url http://$KW_SERVER_IP:$KW_SERVER_PORT/embree buildspec.txt --tables-directory $CI_PROJECT_DIR/kw_tables -$KW_SERVER_PATH/bin/kwadmin --url http://$KW_SERVER_IP:$KW_SERVER_PORT/ load --force --name build-$CI_JOB_ID embree $CI_PROJECT_DIR/kw_tables +$KW_CLIENT_PATH/bin/kwinject -w -o buildspec.txt make -j 8 | tee -a $log_file +$KW_SERVER_PATH/bin/kwbuildproject --classic --force --url http://$KW_SERVER_IP:$KW_SERVER_PORT/embree buildspec.txt --tables-directory $CI_PROJECT_DIR/kw_tables | tee -a $log_file +$KW_SERVER_PATH/bin/kwadmin --url http://$KW_SERVER_IP:$KW_SERVER_PORT/ load --force --name build-$CI_JOB_ID $KW_PROJECT_NAME $CI_PROJECT_DIR/kw_tables | tee -a $log_file -# store kw build number for check status later -echo "build-$CI_JOB_ID" > ./kw_build_number +# Store kw build name for check status later +echo "build-$CI_JOB_ID" > $CI_PROJECT_DIR/klocwork/build_name diff --git a/scripts/klocwork_check.sh b/scripts/klocwork_check.sh index 94064dd462..1307aa725b 100755 --- a/scripts/klocwork_check.sh +++ b/scripts/klocwork_check.sh @@ -1,22 +1,21 @@ -#!/bin/bash - -## Copyright 2009-2020 Intel Corporation +#!/bin/bash -xe +## Copyright 2020-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 -set -e -export KW_BUILD_NUMBER=$(cat ./kw_build_number) -export KW_PROJECT_NAME=embree -export KW_CRITICAL_OUTPUT_PATH=./kw_critical.out +KW_ISSUES_FILE=/tmp/issues +KW_SERVER_API_URL=http://$KW_SERVER_IP:$KW_SERVER_PORT/review/api +KW_BUILD_NAME=$(cat $CI_PROJECT_DIR/klocwork/build_name) -echo "Checking for critical issues in $KW_BUILD_NUMBER ..." -no_proxy=$KW_SERVER_IP curl -f --data "action=search&project=$KW_PROJECT_NAME&query=build:'$KW_BUILD_NUMBER'%20severity:Critical%20status:Analyze,Fix&user=$KW_USER<oken=$KW_LTOKEN" http://$KW_SERVER_IP:$KW_SERVER_PORT/review/api -o $KW_CRITICAL_OUTPUT_PATH +echo "Checking for issues in $KW_BUILD_NAME ..." +curl -f --data "action=search&project=$KW_PROJECT_NAME&query=build:'$KW_BUILD_NAME'%20status:Analyze,Fix,Fix%20in%20Next%20Release,Fix%20in%20Later%20Release,Defer,Filter&user=$KW_USER<oken=$KW_LTOKEN" $KW_SERVER_API_URL -o $KW_ISSUES_FILE getCriticalCount() { - cat $KW_CRITICAL_OUTPUT_PATH | wc -l + cat $KW_ISSUES_FILE | wc -l } -if [ -f $KW_CRITICAL_OUTPUT_PATH ]; then - echo "****** ERROR ****** Critical issues found - $(getCriticalCount) in $KW_BUILD_NUMBER"; - cat $KW_CRITICAL_OUTPUT_PATH +if [ -f $KW_ISSUES_FILE ]; then + echo "Issues found - $(getCriticalCount) in $KW_BUILD_NAME"; + while IFS= read -r line; do echo $line | python -m json.tool; done < $KW_ISSUES_FILE exit 1; else - echo "****** PASS ****** No critical issues were found in $KW_BUILD_NUMBER" + echo "There are no issues which should be take care in $KW_BUILD_NAME" fi + diff --git a/scripts/klocwork_gen_report.sh b/scripts/klocwork_gen_report.sh new file mode 100755 index 0000000000..ec9f6af2ed --- /dev/null +++ b/scripts/klocwork_gen_report.sh @@ -0,0 +1,39 @@ +#!/bin/bash -xe +## Copyright 2020-2021 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +KW_SERVER_API_URL=http://$KW_SERVER_IP:$KW_SERVER_PORT/review/api +KW_BUILD_NAME=$(cat $CI_PROJECT_DIR/klocwork/build_name) +KW_BUILD_LOG_FILE=$CI_PROJECT_DIR/klocwork/build.log + +export PATH="$SHARED_TOOLS_PATH:$PATH" + +[ -f $KW_BUILD_LOG_FILE ] || (echo "Build log file not found. Expected to be in: $KW_BUILD_LOG_FILE." ; exit 1;) + +mkdir -p $CI_PROJECT_DIR/klocwork +report_file=$CI_PROJECT_DIR/klocwork/report.log +echo "------------------" >> $report_file +echo "Report generated at: "$(date '+%d/%m/%Y %H:%M:%S') >> $report_file +echo "Project source code url: $CI_PROJECT_URL" >> $report_file +echo "Project source code sha: $CI_COMMIT_SHA" >> $report_file +echo "Klocwork server: http://$KW_SERVER_IP:$KW_SERVER_PORT" >> $report_file +echo "------------------" >> $report_file + +echo -e "\n\n\n" >> $report_file + +# Get all issues list and put to report file +column_list=".id, .code, .severity, .state, .status, .taxonomyName, .owner, .url, .file, .line" +echo "------------------" >> $report_file +echo "Issues list:" >> $report_file +echo "------------------" >> $report_file +echo $column_list | sed 's/\\t/ ,/g' | column -t -s, >> $report_file +echo "------------------" >> $report_file +curl -f --data "action=search&project=$KW_PROJECT_NAME&query=build:'$KW_BUILD_NAME'&user=$KW_USER<oken=$KW_LTOKEN" $KW_SERVER_API_URL | jq-linux64 "[${column_list}] | @tsv" | sed 's/\\t/|/g' | column -t -s'|' | cut -d'"' -f2 >> $report_file + +echo -e "\n\n\n" >> $report_file + +# Attach build log to report file +echo "------------------" >> $report_file +echo "Build & scan log:" >> $report_file +echo "------------------" >> $report_file +cat $KW_BUILD_LOG_FILE >> $report_file diff --git a/scripts/ospray/CMakeLists.txt b/scripts/ospray/CMakeLists.txt index 322546365c..f1136f3422 100644 --- a/scripts/ospray/CMakeLists.txt +++ b/scripts/ospray/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ## Global settings ## @@ -27,9 +27,9 @@ include(ProcessorCount) ## Superbuild options ## -set(BUILD_OSPCOMMON_VERSION "v1.3.0" CACHE STRING "Which version of ospcommon to build?") -set(TBB_VERSION "2020.2" CACHE STRING "Which version of TBB to download?") -set(BUILD_OPENVKL_VERSION "v0.9.0" CACHE STRING "Which version of OpenVKL to build?") +set(BUILD_RKCOMMON_VERSION "v1.6.0" CACHE STRING "Which version of rkcommon to build?") +set(TBB_VERSION "2021.2.0" CACHE STRING "Which version of TBB to download?") +set(BUILD_OPENVKL_VERSION "v0.12.1" CACHE STRING "Which version of OpenVKL to build?") set(installDir ${CMAKE_INSTALL_PREFIX}) get_filename_component(INSTALL_DIR_ABSOLUTE ${installDir} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) @@ -45,14 +45,18 @@ endif() set(DEFAULT_BUILD_COMMAND cmake --build . --config release ${PARALLEL_JOBS_OPTS}) -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/ispc) +set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) # install all components in one directory +list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) +string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") +set(ISPC_VERSION "v1.15.0") +set(ISPC_BASE_URL "https://github.com/ispc/ispc/releases/download") if (APPLE) - set(ISPC_URL http://sdvis.org/ospray/download/dependencies/osx/ispc-v1.12.0-macOS.tar.gz) + set(ISPC_URL ${ISPC_BASE_URL}/${ISPC_VERSION}/ispc-${ISPC_VERSION}-macOS.tar.gz) elseif(WIN32) - set(ISPC_URL http://sdvis.org/ospray/download/dependencies/win/ispc-v1.12.0-windows.zip) + set(ISPC_URL ${ISPC_BASE_URL}/${ISPC_VERSION}/ispc-${ISPC_VERSION}-windows.zip) else() - set(ISPC_URL http://sdvis.org/ospray/download/dependencies/linux/ispc-v1.12.0-linux.tar.gz) + set(ISPC_URL ${ISPC_BASE_URL}/${ISPC_VERSION}/ispc-${ISPC_VERSION}-linux.tar.gz) endif() ExternalProject_Add(ispc @@ -72,14 +76,12 @@ ExternalProject_Add(ispc set(ISPC_PATH "${COMPONENT_PATH}/bin/ispc${CMAKE_EXECUTABLE_SUFFIX}") -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/tbb) - if (APPLE) - set(TBB_URL "http://github.com/intel/tbb/releases/download/v${TBB_VERSION}/tbb-${TBB_VERSION}-mac.tgz") + set(TBB_URL "http://github.com/intel/tbb/releases/download/v${TBB_VERSION}/oneapi-tbb-${TBB_VERSION}-mac.tgz") elseif (WIN32) - set(TBB_URL "http://github.com/intel/tbb/releases/download/v${TBB_VERSION}/tbb-${TBB_VERSION}-win.zip") + set(TBB_URL "http://github.com/intel/tbb/releases/download/v${TBB_VERSION}/oneapi-tbb-${TBB_VERSION}-win.zip") else() - set(TBB_URL "http://github.com/intel/tbb/releases/download/v${TBB_VERSION}/tbb-${TBB_VERSION}-lin.tgz") + set(TBB_URL "http://github.com/intel/tbb/releases/download/v${TBB_VERSION}/oneapi-tbb-${TBB_VERSION}-lin.tgz") endif() ExternalProject_Add(tbb @@ -93,23 +95,20 @@ ExternalProject_Add(tbb CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory - /tbb + ${COMPONENT_PATH} BUILD_ALWAYS OFF ) set(TBB_PATH "${COMPONENT_PATH}") - -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/ospcommon) - -ExternalProject_Add(ospcommon - PREFIX ospcommon - DOWNLOAD_DIR ospcommon - STAMP_DIR ospcommon/stamp - SOURCE_DIR ospcommon/src - BINARY_DIR ospcommon/build - URL "http://github.com/ospray/ospcommon/archive/${BUILD_OSPCOMMON_VERSION}.zip" +ExternalProject_Add(rkcommon + PREFIX rkcommon + DOWNLOAD_DIR rkcommon + STAMP_DIR rkcommon/stamp + SOURCE_DIR rkcommon/src + BINARY_DIR rkcommon/build + URL "http://github.com/ospray/rkcommon/archive/${BUILD_RKCOMMON_VERSION}.zip" DOWNLOAD_NO_PROGRESS ON CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} @@ -121,17 +120,12 @@ ExternalProject_Add(ospcommon -DCMAKE_BUILD_TYPE=Release -DINSTALL_DEPS=OFF -DBUILD_TESTING=OFF - -DOSPCOMMON_TBB_ROOT=${TBB_PATH} + -DRKCOMMON_TBB_ROOT=${TBB_PATH} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) -list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) -string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") - -ExternalProject_Add_StepDependencies(ospcommon configure tbb) - -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/embree) +ExternalProject_Add_StepDependencies(rkcommon configure tbb) ExternalProject_Add(embree PREFIX embree @@ -148,12 +142,6 @@ ExternalProject_Add(embree BUILD_ALWAYS OFF ) -list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) -string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") - - -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/openvkl) - ExternalProject_Add(openvkl PREFIX openvkl DOWNLOAD_DIR openvkl @@ -173,7 +161,7 @@ ExternalProject_Add(openvkl -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DCMAKE_BUILD_TYPE=Release - -DOSPCOMMON_TBB_ROOT=${TBB_PATH} + -DRKCOMMON_TBB_ROOT=${TBB_PATH} -DISPC_EXECUTABLE=${ISPC_PATH} -DBUILD_BENCHMARKS=OFF -DBUILD_EXAMPLES=OFF @@ -182,19 +170,13 @@ ExternalProject_Add(openvkl BUILD_ALWAYS ${ALWAYS_REBUILD} ) -list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) -string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") - ExternalProject_Add_StepDependencies(openvkl configure - ospcommon + rkcommon embree ispc ) - -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/glfw) - ExternalProject_Add(glfw PREFIX glfw DOWNLOAD_DIR glfw @@ -218,15 +200,9 @@ ExternalProject_Add(glfw BUILD_ALWAYS ${ALWAYS_REBUILD} ) -list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) -string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") - - -set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/ospray) - ExternalProject_Add(ospray PREFIX ospray - URL "https://github.com/ospray/ospray/archive/v2.1.0.tar.gz" + URL "https://github.com/ospray/ospray/archive/v2.5.0.tar.gz" DOWNLOAD_NO_PROGRESS ON GIT_SUBMODULES "" STAMP_DIR ospray/stamp @@ -250,19 +226,16 @@ ExternalProject_Add(ospray -DOSPRAY_STRICT_BUILD=ON -DOSPRAY_WARN_AS_ERRORS=OFF -DISPC_EXECUTABLE=${ISPC_PATH} - -DOSPCOMMON_TBB_ROOT=${TBB_PATH} + -DRKCOMMON_TBB_ROOT=${TBB_PATH} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS OFF ) ExternalProject_Add_StepDependencies(ospray configure - ospcommon + rkcommon embree openvkl glfw ispc ) - -list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) -string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") diff --git a/scripts/package_linux.sh b/scripts/package_linux.sh index 34edbeaf94..ead347ab42 100755 --- a/scripts/package_linux.sh +++ b/scripts/package_linux.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # terminate if some error occurs diff --git a/scripts/package_macosx.sh b/scripts/package_macosx.sh index 5ade18e99d..ab4eda07e4 100755 --- a/scripts/package_macosx.sh +++ b/scripts/package_macosx.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # terminate if some error occurs @@ -21,8 +21,8 @@ if [ ${PACKAGE: -4} == ".pkg" ]; then fi primary_bundle_id="com.intel.embree3" -user=$notarization_user -password="@env:notarization_password" +user=$MACOS_NOTARIZATION_USER +password=$MACOS_NOTARIZATION_PASSWORD xcrun altool --notarize-app --asc-provider 'IntelCorporationApps' --primary-bundle-id "$primary_bundle_id" --username "$user" --password "$password" --file $PACKAGE 2>&1 | tee notarization_request.log diff --git a/scripts/package_win.bat b/scripts/package_win.bat index df972f4903..7e97244165 100755 --- a/scripts/package_win.bat +++ b/scripts/package_win.bat @@ -1,3 +1,6 @@ +rem ## Copyright 2009-2021 Intel Corporation +rem ## SPDX-License-Identifier: Apache-2.0 + @echo off set build_type=%1 diff --git a/scripts/post_install_target.sh.in b/scripts/post_install_target.sh.in index 5785a102eb..ee4b475a4d 100755 --- a/scripts/post_install_target.sh.in +++ b/scripts/post_install_target.sh.in @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # get last argument to bash script diff --git a/scripts/print_size.py b/scripts/print_size.py index 9477ed93a3..165172381a 100755 --- a/scripts/print_size.py +++ b/scripts/print_size.py @@ -1,6 +1,6 @@ -#!/usr/bin/python +#!/usr/bin/env python3 -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 import sys @@ -62,13 +62,12 @@ def split_list(l,s): b=filter(lambda x: x[1].find(s) == -1,l) return (a,b) -(symbols_avx512skx, symbols) = split_list(symbols,"::avx512skx::") -(symbols_avx512knl, symbols) = split_list(symbols,"::avx512knl::") +(symbols_avx512, symbols) = split_list(symbols,"::avx512::") (symbols_avx2, symbols) = split_list(symbols,"::avx2::") (symbols_avx, symbols) = split_list(symbols,"::avx::") (symbols_sse42, symbols) = split_list(symbols,"::sse42::") (symbols_sse2, symbols) = split_list(symbols,"::sse2::") -isa_symbols = (symbols,symbols_sse2,symbols_sse42,symbols_avx,symbols_avx2,symbols_avx512knl,symbols_avx512skx) +isa_symbols = (symbols,symbols_sse2,symbols_sse42,symbols_avx,symbols_avx2,symbols_avx512) component_names=[ ("Intersectors", @@ -135,7 +134,7 @@ def add7((a0,a1,a2,a3,a4,a5,a6),(b0,b1,b2,b3,b4,b5,b6)): def print_header(): sys.stdout.write(' ' + '{0:<40}'.format("Component")) - sys.stdout.write(' NONE SSE2 SSE4.2 AVX AVX2 AVX512knl AVX512skx SUM\n') + sys.stdout.write(' NONE SSE2 SSE4.2 AVX AVX2 AVX512 SUM\n') def sum_component(c): if type(c) is tuple: diff --git a/scripts/regression.py b/scripts/regression.py index cc9557314d..02c475770b 100755 --- a/scripts/regression.py +++ b/scripts/regression.py @@ -1,6 +1,6 @@ -#!/usr/bin/python +#!/usr/bin/env python3 -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Embree Regression Test Script @@ -76,7 +76,7 @@ ISAs_win = ['SSE2', 'AVX', 'AVX2'] #ISAs_unix = ['AVX2'] #ISAs_unix = ['SSE2', 'AVX', 'AVX2'] -ISAs_unix = ['SSE2', 'AVX', 'AVX512KNL'] +ISAs_unix = ['SSE2', 'AVX', 'AVX512'] ISAs = [] supported_configurations = [ @@ -110,7 +110,6 @@ 'ICC_x64_RelWithDebInfo_SSE4.2', 'ICC_x64_RelWithDebInfo_AVX', 'ICC_x64_RelWithDebInfo_AVX2', - 'ICC_x64_RelWithDebInfo_AVX512KNL', 'GCC_x64_RelWithDebInfo_SSE2', 'GCC_x64_RelWithDebInfo_SSE4.2', diff --git a/scripts/release_linux.sh b/scripts/release_linux.sh deleted file mode 100755 index bc711ec633..0000000000 --- a/scripts/release_linux.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash - -## Copyright 2009-2020 Intel Corporation -## SPDX-License-Identifier: Apache-2.0 - -# to make sure we do not include nor link against wrong TBB -export CPATH= -export LIBRARY_PATH= -export LD_LIBRARY_PATH= -TBB_PATH_LOCAL=$PWD/tbb - -# check version of symbols -function check_symbols -{ - for sym in `nm $1 | grep $2_` - do - version=(`echo $sym | sed 's/.*@@\(.*\)$/\1/g' | grep -E -o "[0-9]+"`) - if [ ${#version[@]} -ne 0 ]; then - if [ ${#version[@]} -eq 1 ]; then version[1]=0; fi - if [ ${#version[@]} -eq 2 ]; then version[2]=0; fi - #echo $sym - #echo "version0 = " ${version[0]} - #echo "version1 = " ${version[1]} - #echo "version2 = " ${version[2]} - if [ ${version[0]} -gt $3 ]; then - echo "Error: problematic $2 symbol " $sym - exit 1 - fi - if [ ${version[0]} -lt $3 ]; then continue; fi - - if [ ${version[1]} -gt $4 ]; then - echo "Error: problematic $2 symbol " $sym - exit 1 - fi - if [ ${version[1]} -lt $4 ]; then continue; fi - - if [ ${version[2]} -gt $5 ]; then - echo "Error: problematic $2 symbol " $sym - exit 1 - fi - fi - done -} - -# read embree version -EMBREE_VERSION_MAJOR=`sed -n 's/#define RTC_VERSION_MAJOR \(.*\)/\1/p' include/embree2/rtcore_config.h` -EMBREE_VERSION_MINOR=`sed -n 's/#define RTC_VERSION_MINOR \(.*\)/\1/p' include/embree2/rtcore_config.h` -EMBREE_VERSION_PATCH=`sed -n 's/#define RTC_VERSION_PATCH \(.*\)/\1/p' include/embree2/rtcore_config.h` -EMBREE_VERSION=${EMBREE_VERSION_MAJOR}.${EMBREE_VERSION_MINOR}.${EMBREE_VERSION_PATCH} - -mkdir -p build -cd build -rm CMakeCache.txt # make sure to use default settings - -# set compiler settings -cmake \ --D CMAKE_C_COMPILER:FILEPATH=icc \ --D CMAKE_CXX_COMPILER:FILEPATH=icpc \ -.. - -# set release settings -cmake \ --D EMBREE_STACK_PROTECTOR=ON\ --D EMBREE_MAX_ISA=NONE \ --D EMBREE_ISA_SSE2=ON \ --D EMBREE_ISA_SSE42=ON \ --D EMBREE_ISA_AVX=ON \ --D EMBREE_ISA_AVX2=ON \ --D EMBREE_ISA_AVX512KNL=ON \ --D EMBREE_ISA_AVX512SKX=ON \ --D EMBREE_TUTORIALS_OPENIMAGEIO=OFF \ --D EMBREE_TUTORIALS_LIBJPEG=OFF \ --D EMBREE_TUTORIALS_LIBPNG=OFF \ -.. - -# create RPM files -cmake \ --D EMBREE_INSTALL_DEPENDENCIES=OFF \ --D EMBREE_ZIP_MODE=OFF \ --D CPACK_PACKAGING_INSTALL_PREFIX=/usr \ --D EMBREE_TBB_ROOT=/usr .. -make -j 16 preinstall - -check_symbols libembree.so GLIBC 2 4 0 -check_symbols libembree.so GLIBCXX 3 4 11 -check_symbols libembree.so CXXABI 1 3 0 -make -j 16 package - -tar czf embree-${EMBREE_VERSION}.x86_64.rpm.tar.gz embree-*-${EMBREE_VERSION}-*.rpm - -# create tar.gz files -cmake \ --D EMBREE_INSTALL_DEPENDENCIES=ON \ --D EMBREE_ZIP_MODE=ON \ --D CPACK_PACKAGING_INSTALL_PREFIX=/ \ --D CMAKE_INSTALL_INCLUDEDIR=include \ --D CMAKE_INSTALL_LIBDIR=lib \ --D CMAKE_INSTALL_DOCDIR=doc \ --D CMAKE_INSTALL_BINDIR=bin \ --D EMBREE_TBB_ROOT=$TBB_PATH_LOCAL .. -make -j 16 preinstall - -check_symbols libembree.so GLIBC 2 4 0 -check_symbols libembree.so GLIBCXX 3 4 11 -check_symbols libembree.so CXXABI 1 3 0 -make -j 16 package - -rm CMakeCache.txt # reset settings -cd .. diff --git a/scripts/release_macosx.sh b/scripts/release_macosx.sh deleted file mode 100755 index 8147bc1af6..0000000000 --- a/scripts/release_macosx.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - -## Copyright 2009-2020 Intel Corporation -## SPDX-License-Identifier: Apache-2.0 - -# to make sure we do not include nor link against wrong TBB -export CPATH= -export LIBRARY_PATH= -export DYLD_LIBRARY_PATH= -TBB_PATH_LOCAL=$PWD/tbb - -mkdir -p build -cd build -rm CMakeCache.txt # make sure to use default settings -rm version.h - -# set compiler -cmake \ --D CMAKE_C_COMPILER:FILEPATH=icc \ --D CMAKE_CXX_COMPILER:FILEPATH=icpc \ -.. - -# set release settings -cmake \ --D EMBREE_STACK_PROTECTOR=ON\ --D EMBREE_MAX_ISA=AVX2 \ --D EMBREE_TUTORIALS_OPENIMAGEIO=OFF \ --D EMBREE_TUTORIALS_LIBJPEG=OFF \ --D EMBREE_TUTORIALS_LIBPNG=OFF \ -.. - -# create installers -cmake \ --D EMBREE_INSTALL_DEPENDENCIES=OFF \ --D EMBREE_ZIP_MODE=OFF \ --D CMAKE_INSTALL_PREFIX=/opt/local \ --D CMAKE_INSTALL_INCLUDEDIR=include \ --D CMAKE_INSTALL_LIBDIR=lib \ --D CMAKE_INSTALL_DOCDIR=../../Applications/Embree3/doc \ --D CMAKE_INSTALL_BINDIR=../../Applications/Embree3/bin \ --D EMBREE_TBB_ROOT=/opt/local \ -.. -make -j 4 package - -# create ZIP files -cmake \ --D EMBREE_INSTALL_DEPENDENCIES=ON \ --D EMBREE_ZIP_MODE=ON \ --D CMAKE_MACOSX_RPATH=ON \ --D CMAKE_INSTALL_INCLUDEDIR=include \ --D CMAKE_INSTALL_LIBDIR=lib \ --D CMAKE_INSTALL_DOCDIR=doc \ --D CMAKE_INSTALL_BINDIR=bin \ --D EMBREE_TBB_ROOT=$TBB_PATH_LOCAL \ -.. -make -j 4 package - -rm CMakeCache.txt # reset settings -cd .. diff --git a/scripts/release_win.bat b/scripts/release_win.bat deleted file mode 100755 index 48fd29d241..0000000000 --- a/scripts/release_win.bat +++ /dev/null @@ -1,72 +0,0 @@ -rem ## ======================================================================== ## -rem ## Copyright 2009-2020 Intel Corporation ## -rem ## ## -rem ## Licensed under the Apache License, Version 2.0 (the "License"); ## -rem ## you may not use this file except in compliance with the License. ## -rem ## You may obtain a copy of the License at ## -rem ## ## -rem ## http://www.apache.org/licenses/LICENSE-2.0 ## -rem ## ## -rem ## Unless required by applicable law or agreed to in writing, software ## -rem ## distributed under the License is distributed on an "AS IS" BASIS, ## -rem ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## -rem ## See the License for the specific language governing permissions and ## -rem ## limitations under the License. ## -rem ## ======================================================================== ## - -@echo off - -setlocal -set TBB_PATH_LOCAL=%cd%\tbb - -mkdir build_x64 -cd build_x64 -del CMakeCache.txt # make sure to use default settings -del version.h - -REM set release settings -cmake -L ^ --G "Visual Studio 12 2013 Win64" ^ --T "Intel C++ Compiler 16.0" ^ --D EMBREE_STACK_PROTECTOR=ON ^ --D EMBREE_MAX_ISA=AVX512SKX ^ --D EMBREE_TBB_ROOT=%TBB_PATH_LOCAL% ^ --D ENABLE_XEON_PHI_SUPPORT=OFF ^ --D EMBREE_TUTORIALS_OPENIMAGEIO=OFF ^ --D EMBREE_TUTORIALS_LIBJPEG=OFF ^ --D EMBREE_TUTORIALS_LIBPNG=OFF ^ -.. - -REM compile -cmake --clean-first --build . --config Release --target PREINSTALL -- /m /nologo /verbosity:n - -REM create installers -cmake ^ --D EMBREE_INSTALL_DEPENDENCIES=ON ^ --D EMBREE_ZIP_MODE=OFF ^ --D CMAKE_INSTALL_INCLUDEDIR=include ^ --D CMAKE_INSTALL_LIBDIR=lib ^ --D CMAKE_INSTALL_DATAROOTDIR= ^ --D CMAKE_INSTALL_DOCDIR=doc ^ --D CMAKE_INSTALL_BINDIR=bin ^ -.. -cmake --build . --config Release --target PACKAGE -- /m /nologo /verbosity:n - -REM create ZIP files -cmake ^ --D EMBREE_INSTALL_DEPENDENCIES=ON ^ --D EMBREE_ZIP_MODE=ON ^ --D CMAKE_INSTALL_INCLUDEDIR=include ^ --D CMAKE_INSTALL_LIBDIR=lib ^ --D CMAKE_INSTALL_DATAROOTDIR= ^ --D CMAKE_INSTALL_DOCDIR=doc ^ --D CMAKE_INSTALL_BINDIR=bin ^ -.. -cmake --build . --config Release --target PACKAGE -- /m /nologo /verbosity:n - -del CMakeCache.txt -cd .. - -:abort -endlocal -:end diff --git a/scripts/run-benchmark.sh b/scripts/run-benchmark.sh new file mode 100755 index 0000000000..e1dcbc45c1 --- /dev/null +++ b/scripts/run-benchmark.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +## Copyright 2020 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +git log -1 + +# environment for benchmark client +source ~/benchmark_client.git/env.sh +source ~/system_token.sh + +# benchmark configuration +SOURCE_ROOT=`pwd` +PROJECT_NAME="Embree" + +NUMACTL="numactl --physcpubind=+0-27 --" +BENCHMARK="--benchmark 10 0 --benchmark_repetitions 11" +THREADS="--set_affinity 1" + +MODEL_DIR="${HOME}/embree-models" + +export LD_LIBRARY_PATH=`pwd`/build:${LD_LIBRARY_PATH} + +cd build +rm -f *.json + +BUILD_SCENES_FILE="../tutorials/models/build.bench" +TRACE_SCENES_FILE="../tutorials/models/trace.bench" + +RUN_BUILD_BENCHMARKS=true +RUN_TRACE_BENCHMARKS=true +RUN_TUT_BENCHMARKS=true + +################################# PLEASE READ ################################## +# +# Note that suites and subsuites must exist in the database _before_ attempting +# insertion of results. This is intentional! You should think carefully about +# your [suite -> subsuite -> benchmark] hierarchy and definitions. These should +# be stable over time (especially for suites and subsuites) to facilitate +# long-term comparisons. +# +# These can be inserted using the benchmark client, through the "insert suite" +# and "insert subsuite" commands. Ask for help if you have questions. +# +################################# PLEASE READ ################################### + +initContext() { + if [ -z "$HAVE_CONTEXT" ]; then + HAVE_CONTEXT=1 + benny insert code_context "${PROJECT_NAME}" ${SOURCE_ROOT} --save-json code_context.json + benny insert run_context ${TOKEN} ./code_context.json --save-json run_context.json + fi +} + +#################### +# build benchmarks # +#################### + +if ${RUN_BUILD_BENCHMARKS}; then + SUITE_NAME="Build" + benny insert suite ${PROJECT_NAME} ${SUITE_NAME} + + ## subsuites of build benchmarks + subsuites="update_dynamic_deformable \ + create_dynamic_dynamic \ + create_static_static \ + create_high_quality_static_static" + + while IFS= read -r line + do + IFS=' ' read -r -a array <<< "$line" + NAME="${array[0]}" + if [[ $NAME == '#'* ]]; then + continue + fi + SCENE=${MODEL_DIR}/"${array[1]}" + + unset "array[0]" + unset "array[1]" + + for i in ${subsuites} + do + SUBSUITE_NAME=$i + benny insert subsuite ${PROJECT_NAME} ${SUITE_NAME} ${SUBSUITE_NAME} + + initContext + + echo "${NUMACTL} ./buildbench --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} --benchmark_type ${SUBSUITE_NAME} -i ${SCENE} ${array[@]} ${THREADS}" + ${NUMACTL} ./buildbench --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} --benchmark_type ${SUBSUITE_NAME} -i ${SCENE} ${array[@]} ${THREADS} + benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json + done + done < "${BUILD_SCENES_FILE}" +fi + +#################### +# trace benchmarks # +#################### + +if ${RUN_TRACE_BENCHMARKS}; then + SUITE_NAME="Trace" + benny insert suite ${PROJECT_NAME} ${SUITE_NAME} + + while IFS= read -r line + do + IFS=' ' read -r -a array <<< "$line" + NAME="${array[0]}" + if [[ $NAME == '#'* ]]; then + continue + fi + SCENE=${MODEL_DIR}/"${array[1]}" + + unset "array[0]" + unset "array[1]" + + SUBSUITE_NAME="Viewer" + benny insert subsuite ${PROJECT_NAME} ${SUITE_NAME} ${SUBSUITE_NAME} + initContext + + echo "${NUMACTL} ./viewer --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} -c ${SCENE} ${array[@]} ${THREADS} --size 256 256" + ${NUMACTL} ./viewer --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} -c ${SCENE} ${array[@]} ${THREADS} + benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json + + SUBSUITE_NAME="Pathtracer" + benny insert subsuite ${PROJECT_NAME} ${SUITE_NAME} ${SUBSUITE_NAME} + initContext + + echo "${NUMACTL} ./pathtracer --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} -c ${SCENE} ${array[@]} ${THREADS} --size 256 256 --spp 32" + ${NUMACTL} ./pathtracer --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} -c ${SCENE} ${array[@]} ${THREADS} + benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json + + done < "${TRACE_SCENES_FILE}" + + if ${RUN_TUT_BENCHMARKS}; then + SUBSUITE_NAME="Tutorials" + benny insert subsuite ${PROJECT_NAME} ${SUITE_NAME} ${SUBSUITE_NAME} + initContext + + tutorials="triangle_geometry \ + grid_geometry \ + curve_geometry \ + displacement_geometry \ + hair_geometry \ + instanced_geometry \ + intersection_filter \ + point_geometry \ + subdivision_geometry \ + user_geometry" + + for i in ${tutorials} + do + ${NUMACTL} ./${i} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json ${BENCHMARK} ${THREADS} + benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json + done + fi +fi diff --git a/scripts/source_scan_protex.sh b/scripts/source_scan_protex.sh index 53af46d11b..c780b29fc9 100755 --- a/scripts/source_scan_protex.sh +++ b/scripts/source_scan_protex.sh @@ -1,34 +1,34 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 +# enable early exit on fail +set -e -PROTEX_ROOT=/NAS/tools/ip_protex/protex_v7.8 -BDSTOOL=$PROTEX_ROOT/bin/bdstool -PROTEX_PROJECT_NAME=c_embreeraytracingkernels_14283 -SERVER_URL=https://amrprotex003.devtools.intel.com/ -SRC_PATH=$CI_PROJECT_DIR/ +BDSTOOL=$PROTEX_PATH/bin/bdstool +PROTEX_PROJECT_NAME=$PROTEX_PROJECT_NAME +SERVER_URL=$PROTEX_SERVER_URL +SRC_PATH=$CI_PROJECT_DIR +LOG_FILE=/tmp/ip_protex.log -export _JAVA_OPTIONS=-Duser.home=$PROTEX_ROOT/home +export _JAVA_OPTIONS=-Duser.home=$PROTEX_PATH/home # enter source code directory before scanning cd $SRC_PATH -$BDSTOOL new-project --server $SERVER_URL $PROTEX_PROJECT_NAME |& tee ip_protex.log -if grep -q "fail\|error\|fatal\|not found" ip_protex.log; then - exit 1 -fi +$BDSTOOL new-project --server $SERVER_URL $PROTEX_PROJECT_NAME |& tee $LOG_FILE +$BDSTOOL analyze --server $SERVER_URL --path $SRC_PATH |& tee -a $LOG_FILE -$BDSTOOL analyze --server $SERVER_URL |& tee -a ip_protex.log -if grep -q "fail\|error\|fatal\|not found" ip_protex.log; then +if ! grep -E "^Files scanned successfully with no discoveries: [0-9]+$" $LOG_FILE; then + echo "Protex scan FAILED!" exit 1 fi -if grep -E "^Files pending identification: [0-9]+$" ip_protex.log; then - echo "Protex scan FAILED!" +if grep -E "^Files pending identification: [0-9]+$" $LOG_FILE; then + echo "Protex scan FAILED! Some pending identification found. Please check on $SERVER_URL" exit 1 fi echo "Protex scan PASSED!" -exit 0 \ No newline at end of file +exit 0 diff --git a/scripts/store_files.sh b/scripts/store_files.sh new file mode 100755 index 0000000000..56de756f59 --- /dev/null +++ b/scripts/store_files.sh @@ -0,0 +1,11 @@ +#!/bin/bash -xe +## Copyright 2019-2021 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 + +project_name=$1 +build_id=$2 +group_name=$3 +files=$4 +STORAGE_DIR=$STORAGE_PATH/$project_name/$build_id/$group_name/ +mkdir -p $STORAGE_DIR +cp $files $STORAGE_DIR/ diff --git a/scripts/test.cmake b/scripts/test.cmake index c816d56ad5..3d50bd8428 100755 --- a/scripts/test.cmake +++ b/scripts/test.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 message("CTEST_BUILD_OPTIONS = ${CTEST_BUILD_OPTIONS}") @@ -66,88 +66,82 @@ MACRO(update_test_models) check_return_code() ENDMACRO() -# increase default output sizes for test outputs -IF (NOT DEFINED CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE) - SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 100000) -ENDIF() -IF(NOT DEFINED CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE) - SET(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE 800000) -ENDIF() +################################## +# configure and build # +################################## +MACRO(build) -# enable testing in Embree -SET (CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -D BUILD_TESTING:BOOL=ON -D EMBREE_TESTING_MODEL_DIR:PATH=${TEST_MODELS_DIRECTORY}") + include(ProcessorCount) + ProcessorCount(numProcessors) + if(numProcessors EQUAL 0) + SET(numProcessors 1) + endif() -# set site based on this machine's hostname -SITE_NAME(HOSTNAME) -set(CTEST_SITE "${HOSTNAME}") + if (${THREADS} EQUAL 0) + SET(THREADS ${numProcessors}) + endif() -# drop location -set(CTEST_DROP_METHOD "http") -IF(NOT CTEST_DROP_SITE) - set(CTEST_DROP_SITE "10.123.110.90") -ENDIF() -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=${CTEST_PROJECT_NAME}") -set(CTEST_DROP_SITE_CDASH TRUE) - -# get OS and CPU information -#find_program(UNAME NAMES uname) -#macro(getuname name flag) -# exec_program("${UNAME}" ARGS "${flag}" OUTPUT_VARIABLE "${name}") -#endmacro(getuname) - -#getuname(osname -s) -#getuname(osrel -r) -#getuname(cpu -m) - -# build using as many processes as we have processors -include(ProcessorCount) -ProcessorCount(numProcessors) -if(numProcessors EQUAL 0) - SET(numProcessors 1) -endif() - -# set build name -#set(CTEST_BUILD_NAME "${osname}-${cpu}") -set(CTEST_CMAKE_GENERATOR "Unix Makefiles") -IF (WIN32) - set(CTEST_BUILD_COMMAND "${CMAKE_COMMAND} --build . --config ${CTEST_CONFIGURATION_TYPE} -- /m /t:rebuild ") -ELSE() - set(CTEST_BUILD_COMMAND "make -j ${numProcessors}") -ENDIF() + set(CTEST_CMAKE_GENERATOR "Unix Makefiles") + IF (WIN32) + set(CTEST_BUILD_COMMAND "${CMAKE_COMMAND} --build . -j ${THREADS} --config ${CTEST_CONFIGURATION_TYPE} ${BUILD_SUFFIX}") + ELSE() + set(CTEST_BUILD_COMMAND "make -j ${THREADS}") + ENDIF() -################### -# execute the test -################### + IF (NOT WIN32) + ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) + ENDIF() -# requires CMake 2.8 or higher for git!!! -#set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") + ctest_start("Continuous") -set(CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} ${CTEST_BUILD_OPTIONS} ..") + set(CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} ${CTEST_BUILD_OPTIONS} ..") + ctest_configure(RETURN_VALUE retval) + IF (NOT retval EQUAL 0) + message(FATAL_ERROR "test.cmake: configure failed") + ENDIF() -# start the test -IF (NOT WIN32) - ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) -ENDIF() -ctest_start("Continuous") -#ctest_update (RETURN_VALUE count) -IF (EMBREE_TESTING_INTENSITY GREATER 0) - update_test_models() -ENDIF() -ctest_configure() + ctest_build(RETURN_VALUE retval) + message("test.cmake: ctest_build return value = ${retval}") + IF (NOT retval EQUAL 0) + message(FATAL_ERROR "test.cmake: build failed") + ENDIF() +ENDMACRO() -ctest_build(RETURN_VALUE retval) -message("test.cmake: ctest_build return value = ${retval}") +################################## +# configure and execute the test # +################################## +MACRO(test) + ctest_start("Continuous") -IF (NOT retval EQUAL 0) - message(FATAL_ERROR "test.cmake: build failed") -ENDIF() + IF (EMBREE_UPDATE_MODELS AND EMBREE_TESTING_INTENSITY GREATER 0) + update_test_models() + ENDIF() -IF (EMBREE_TESTING_INTENSITY GREATER 0 OR EMBREE_TESTING_KLOCWORK) - ctest_test(RETURN_VALUE retval) - message("test.cmake: ctest_test return value = ${retval}") - IF (NOT retval EQUAL 0) - message(FATAL_ERROR "test.cmake: some tests failed") + set(CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} -DBUILD_TESTING:BOOL=ON -DEMBREE_TESTING_MODEL_DIR:PATH=${TEST_MODELS_DIRECTORY} -DEMBREE_TESTING_INTENSITY=${EMBREE_TESTING_INTENSITY} ..") + ctest_configure() + + IF (EMBREE_TESTING_INTENSITY GREATER 0 OR EMBREE_TESTING_KLOCWORK) + ctest_test(RETURN_VALUE retval) + message("test.cmake: ctest_test return value = ${retval}") + IF (NOT retval EQUAL 0) + message(FATAL_ERROR "test.cmake: some tests failed") + ENDIF() ENDIF() +ENDMACRO() + +# increase default output sizes for test outputs +IF (NOT DEFINED CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE) + SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 100000) +ENDIF() +IF(NOT DEFINED CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE) + SET(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE 800000) +ENDIF() + +IF (${STAGE} STREQUAL "build") + build() +ELSEIF (${STAGE} STREQUAL "test") + test() +ELSE () + message("unknown stage ${STAGE}. Should be \"build\" or \"test\"") ENDIF() -#ctest_submit() diff --git a/scripts/test.py b/scripts/test.py index 9a6c19793d..debaa410b2 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -1,23 +1,20 @@ -#!/usr/bin/python +#!/usr/bin/env python3 -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 import sys +import subprocess import os import ctypes -import time -import datetime -import json -import socket -import subprocess +import pickle +import re + +cwd = os.getcwd() -g_cdash = "" -g_config = {} -g_mode = "Experimental" -g_intensity = 2 g_debugMode = False -g_singleConfig = "" +g_benchmarkMode = False +g_intensity = 2 def escape(str): str = str.replace("\\",r"\\") @@ -27,40 +24,70 @@ def escape(str): def parse_version(v): return tuple(map(int, v.split("."))) +# change some CMake paths in the CMakeCache.txt file for execution of tests +# on potentially different machine (e.g, copied build dir in CI) +def fix_cmake_paths(): + with open('build/CMakeCache.txt', 'r') as file: + file_content = file.read() + + file_content = re.sub(r"(For build in directory: ).*", os.path.join(r"\1"+cwd, "build"), file_content) + file_content = re.sub(r"(embree[0-9]+_BINARY_DIR:STATIC=).*", os.path.join(r"\1"+cwd, "build"), file_content) + file_content = re.sub(r"(CMAKE_CACHEFILE_DIR:INTERNAL=).*", os.path.join(r"\1"+cwd, "build"), file_content) + + file_content = re.sub(r"(embree[0-9]+_SOURCE_DIR:STATIC=).*", r"\1"+cwd, file_content) + file_content = re.sub(r"(CMAKE_HOME_DIRECTORY:INTERNAL=).*", r"\1"+cwd, file_content) + + with open('build/CMakeCache.txt', 'w') as file: + file.write(file_content) + # detect platform if sys.platform.startswith("win"): - dash = '\\' SEM_FAILCRITICALERRORS = 0x0001 SEM_NOGPFAULTERRORBOX = 0x0002 SEM_NOOPENFILEERRORBOX = 0x8000 ctypes.windll.kernel32.SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); OS = "windows" elif sys.platform.startswith("cygwin"): - dash = '/' SEM_FAILCRITICALERRORS = 0x0001 SEM_NOGPFAULTERRORBOX = 0x0002 SEM_NOOPENFILEERRORBOX = 0x8000 ctypes.cdll.kernel32.SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); OS = "windows" elif sys.platform.startswith("linux"): - dash = '/' OS = "linux" elif sys.platform.startswith("darwin"): - dash = '/' OS = "macosx" else: print("unknown platform: "+ sys.platform); sys.exit(1) -# runs all tests for specified host machine +NAS = "" +if OS == "windows": + NAS = os.environ["NAS_WINDOWS"] +elif OS == "linux": + NAS = os.environ["NAS_LINUX"] +elif OS == "macosx": + NAS = os.environ["NAS_MACOSX"] + +# path of oneapi installation on windows machines +ONE_API_PATH_WINDOWS="C:\\Program Files (x86)\\Intel\\oneAPI\\compiler" + +# configures tests for specified host machine def runConfig(config): conf = [] # CMake configuration env = [] # shell environment - + rtcore = [] # rtcore configuration + build = config["build"] conf.append("-D CMAKE_BUILD_TYPE="+build+"") - + + cmake_build_suffix = "" + threads = "0" + + if "threads" in config: + threads = config["threads"] + if "memcheck" in config: conf.append("-D EMBREE_TESTING_MEMCHECK="+config["memcheck"]+"") @@ -69,9 +96,11 @@ def runConfig(config): if "addrsanitizer" in config: conf.append("-D EMBREE_ADDRESS_SANITIZER="+config["addrsanitizer"]+"") - + if "intensity" in config: - conf.append("-D EMBREE_TESTING_INTENSITY="+config["intensity"]) + g_intensity = config["intensity"] + else: + g_intensity = 2 if "klocwork" in config: conf.append("-D EMBREE_TESTING_KLOCWORK="+config["klocwork"]) @@ -84,13 +113,11 @@ def runConfig(config): #if "package" in config and OS == 'linux': # we need up to date cmake for RPMs to work properly # env.append("module load cmake") - - nas = "/NAS/packages/apps" - compiler = config["compiler"] platform = config["platform"] ispc_ext = "-vs2013" if OS == "windows": + cmake_build_suffix = "-- /m /t:rebuild" ext = "" if platform == "x64": ext = " Win64" @@ -154,54 +181,69 @@ def runConfig(config): conf.append("-G \"Visual Studio 15 2017"+ext+"\"") conf.append("-T \"v141_clang_c2\"") ispc_ext = "-vs2015" + elif (compiler.startswith("ICX")): + cmake_build_suffix = "" + ispc_ext = "-vs2015" + env.append('"'+ONE_API_PATH_WINDOWS+'\\'+compiler[3:]+'\\env\\vars.bat"') + conf.append("-G Ninja -D CMAKE_CXX_COMPILER=icx -DCMAKE_C_COMPILER=icx") else: raise ValueError('unknown compiler: ' + compiler + '') - + elif OS == "linux": if (compiler == "GCC"): conf.append("-D CMAKE_CXX_COMPILER=g++ -D CMAKE_C_COMPILER=gcc") elif (compiler == "CLANG"): conf.append("-D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang") + elif (compiler.startswith("ICX")): + env.append("source "+NAS+"/intel/"+compiler[3:]+"/compiler/latest/env/vars.sh") + conf.append("-D CMAKE_CXX_COMPILER=icpx -D CMAKE_C_COMPILER=icx") + elif (compiler.startswith("DPCPP")): + env.append("source "+NAS+"/intel/"+compiler[5:]+"/compiler/latest/env/vars.sh") + conf.append("-D CMAKE_CXX_COMPILER=dpcpp -D CMAKE_C_COMPILER=icx") elif (compiler.startswith("ICC")): - conf.append("-D CMAKE_CXX_COMPILER=/NAS/packages/apps/intel/"+compiler[3:]+"/bin/icpc -D CMAKE_C_COMPILER=/NAS/packages/apps/intel/"+compiler[3:]+"/bin/icc") + conf.append("-D CMAKE_CXX_COMPILER="+NAS+"/intel/"+compiler[3:]+"/bin/icpc -D CMAKE_C_COMPILER="+NAS+"/intel/"+compiler[3:]+"/bin/icc") elif (compiler.startswith("CLANG")): - conf.append("-D CMAKE_CXX_COMPILER=/NAS/packages/apps/clang/v"+compiler[5:]+"/bin/clang++ -D CMAKE_C_COMPILER=/NAS/packages/apps/clang/v"+compiler[5:]+"/bin/clang") + conf.append("-D CMAKE_CXX_COMPILER="+NAS+"/clang/v"+compiler[5:]+"/bin/clang++ -D CMAKE_C_COMPILER="+NAS+"/clang/v"+compiler[5:]+"/bin/clang") else: raise ValueError('unknown compiler: ' + compiler + '') - + else: if (compiler == "GCC"): conf.append("-D CMAKE_CXX_COMPILER=g++ -D CMAKE_C_COMPILER=gcc") elif (compiler == "CLANG"): conf.append("-D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang") elif (compiler.startswith("ICC")): - conf.append("-D CMAKE_CXX_COMPILER=/NAS/packages/apps/intel/"+compiler[3:]+"-osx/bin/icpc -D CMAKE_C_COMPILER=/NAS/packages/apps/intel/"+compiler[3:]+"-osx/bin/icc") + conf.append("-D CMAKE_CXX_COMPILER="+NAS+"/intel/"+compiler[3:]+"-osx/compiler/latest/mac/bin/intel64/icpc -D CMAKE_C_COMPILER="+NAS+"/intel/"+compiler[3:]+"-osx/compiler/latest/mac/bin/intel64/icc") else: raise ValueError('unknown compiler: ' + compiler + '') - ispc_compiler = config["ispc"] - if ispc_compiler.startswith("ispc"): - - ispc_version = ispc_compiler[4:] - - if ispc_version != "": - - if OS == "windows": bin_folder = "bin\\" - else : bin_folder = "bin/" - if parse_version(ispc_version) < parse_version("1.11.0"): bin_folder = "" - - if OS == "linux": - conf.append("-D EMBREE_ISPC_EXECUTABLE=/NAS/packages/apps/ispc/"+ispc_version+"-linux/"+bin_folder+"ispc") - elif OS == "macosx": - conf.append("-D EMBREE_ISPC_EXECUTABLE=/NAS/packages/apps/ispc/"+ispc_version+"-osx/"+bin_folder+"ispc") - elif OS == "windows": - conf.append("-D EMBREE_ISPC_EXECUTABLE=\\\\vis-nassie.an.intel.com\\NAS\\packages\\apps\\ispc\\"+ispc_version+"-windows"+ispc_ext+"\\"+bin_folder+"ispc.exe") - else: - sys.stderr.write("unknown operating system "+OS) - sys.exit(1) + if "ispc" in config: + conf.append("-D EMBREE_ISPC_SUPPORT=ON") + ispc_compiler = config["ispc"] + if ispc_compiler.startswith("ispc"): + + ispc_version = ispc_compiler[4:] + + if ispc_version != "": + + if OS == "windows": bin_folder = "bin\\" + else : bin_folder = "bin/" + if parse_version(ispc_version) < parse_version("1.11.0"): bin_folder = "" + + if OS == "linux": + conf.append("-D EMBREE_ISPC_EXECUTABLE="+NAS + "/ispc/"+ispc_version+"-linux/"+bin_folder+"ispc") + elif OS == "macosx": + conf.append("-D EMBREE_ISPC_EXECUTABLE="+NAS + "/ispc/"+ispc_version+"-osx/"+bin_folder+"ispc") + elif OS == "windows": + conf.append("-D EMBREE_ISPC_EXECUTABLE="+NAS+"\\ispc\\"+ispc_version+"-windows"+ispc_ext+"\\"+bin_folder+"ispc.exe") + else: + sys.stderr.write("unknown operating system "+OS) + sys.exit(1) + else: + raise ValueError('unknown ISPC compiler: ' + ispc_compiler + '') else: - raise ValueError('unknown ISPC compiler: ' + ispccompiler + '') - + conf.append("-D EMBREE_ISPC_SUPPORT=OFF") + isa = config["isa"] if type(isa) == str: conf.append("-D EMBREE_MAX_ISA="+isa+"") @@ -215,10 +257,8 @@ def runConfig(config): else : conf.append("-D EMBREE_ISA_AVX=OFF") if "AVX2" in isa: conf.append("-D EMBREE_ISA_AVX2=ON") else : conf.append("-D EMBREE_ISA_AVX2=OFF") - if "AVX512KNL" in isa: conf.append("-D EMBREE_ISA_AVX512KNL=ON") - else : conf.append("-D EMBREE_ISA_AVX512KNL=OFF") - if "AVX512SKX" in isa: conf.append("-D EMBREE_ISA_AVX512SKX=ON") - else : conf.append("-D EMBREE_ISA_AVX512SKX=OFF") + if "AVX512" in isa: conf.append("-D EMBREE_ISA_AVX512=ON") + else : conf.append("-D EMBREE_ISA_AVX512=OFF") if "tasking" in config: tasking = config["tasking"] @@ -233,37 +273,35 @@ def runConfig(config): if tasking == "TBB": conf.append("-D EMBREE_TBB_ROOT=/usr") elif tasking.startswith("TBB"): - conf.append("-D EMBREE_TBB_ROOT=/NAS/packages/apps/tbb/tbb-"+tasking[3:]+"-linux") + conf.append("-D EMBREE_TBB_ROOT="+NAS+"/tbb/tbb-"+tasking[3:]+"-linux") else: raise ValueError('unknown tasking system: ' + tasking + '') - + elif OS == "macosx": if tasking == "TBB": conf.append("-D EMBREE_TBB_ROOT=/opt/local") + elif tasking == "TBB_HOMEBREW": + conf.append("-D EMBREE_TBB_ROOT=/opt/homebrew") elif tasking.startswith("TBB"): - conf.append("-D EMBREE_TBB_ROOT=/NAS/packages/apps/tbb/tbb-"+tasking[3:]+"-osx") - else: - raise ValueError('unknown tasking system: ' + tasking + '') - - elif OS == "windows": - if tasking.startswith("TBB"): - tbb_path = "\\\\vis-nassie.an.intel.com\\NAS\\packages\\apps\\tbb\\tbb-"+tasking[3:]+"-windows" + conf.append("-D EMBREE_TBB_ROOT="+NAS+"/tbb/tbb-"+tasking[3:]+"-osx") else: raise ValueError('unknown tasking system: ' + tasking + '') + elif OS == "windows": + tbb_path = ""+NAS+"\\tbb\\tbb-"+tasking[3:]+"-windows" conf.append("-D EMBREE_TBB_ROOT="+tbb_path) - + if platform == "x64": - env.append("set PATH="+tbb_path+"\\bin\\intel64\\vc12;"+tbb_path+"\\bin\\intel64\\vc14;%PATH%") + env.append("set PATH="+tbb_path+"\\bin\\intel64\\vc12;"+tbb_path+"\\bin\\intel64\\vc14;"+tbb_path+"\\redist\\intel64\\vc12;"+tbb_path+"\\redist\\intel64\\vc14;%PATH%") else: - env.append("set PATH="+tbb_path+"\\bin\\ia32\\vc12;"+tbb_path+"\\bin\\ia32\\vc14;%PATH%") + env.append("set PATH="+tbb_path+"\\bin\\ia32\\vc12;"+tbb_path+"\\bin\\ia32\\vc14;"+tbb_path+"\\redist\\ia32\\vc12;"+tbb_path+"\\redist\\ia32\\vc14;%PATH%") else: sys.stderr.write("unknown operating system "+OS) sys.exit(1) - + else: - raise ValueError('unknown tasking system: ' + tasking) + raise ValueError('unknown tasking system: ' + tasking) if "api_namespace" in config: conf.append("-D EMBREE_API_NAMESPACE="+config["api_namespace"]) @@ -277,6 +315,8 @@ def runConfig(config): conf.append("-D EMBREE_TUTORIALS="+config["TUTORIALS"]) if "BACKFACE_CULLING" in config: conf.append("-D EMBREE_BACKFACE_CULLING="+config["BACKFACE_CULLING"]) + if "BACKFACE_CULLING_CURVES" in config: + conf.append("-D EMBREE_BACKFACE_CULLING_CURVES="+config["BACKFACE_CULLING_CRUVES"]) if "IGNORE_INVALID_RAYS" in config: conf.append("-D EMBREE_IGNORE_INVALID_RAYS="+config["IGNORE_INVALID_RAYS"]) if "FILTER_FUNCTION" in config: @@ -309,6 +349,8 @@ def runConfig(config): conf.append("-D EMBREE_MIN_WIDTH="+config["MIN_WIDTH"]) if "GLFW" in config: conf.append("-D EMBREE_TUTORIALS_GLFW="+config["GLFW"]) + if "frequency_level" in config: + rtcore.append("frequency_level="+config["frequency_level"]) if "package" in config: conf.append("-D EMBREE_TESTING_PACKAGE=ON") @@ -316,7 +358,7 @@ def runConfig(config): conf.append("-D EMBREE_TUTORIALS_LIBJPEG=OFF") conf.append("-D EMBREE_TUTORIALS_LIBPNG=OFF") if OS == "linux" and config["package"] == "ZIP": - conf.append("-D EMBREE_SIGN_FILE=/NAS/packages/apps/signfile/linux/SignFile") + conf.append("-D EMBREE_SIGN_FILE="+NAS+"/signfile/linux/SignFile") conf.append("-D EMBREE_INSTALL_DEPENDENCIES=ON") conf.append("-D EMBREE_ZIP_MODE=ON") conf.append("-D CMAKE_SKIP_INSTALL_RPATH=OFF") @@ -324,15 +366,8 @@ def runConfig(config): conf.append("-D CMAKE_INSTALL_LIBDIR=lib") conf.append("-D CMAKE_INSTALL_DOCDIR=doc") conf.append("-D CMAKE_INSTALL_BINDIR=bin") - elif OS == "linux" and config["package"] == "RPM": - conf.append("-D EMBREE_SIGN_FILE=/NAS/packages/apps/signfile/linux/SignFile") - conf.append("-D EMBREE_INSTALL_DEPENDENCIES=OFF") - conf.append("-D EMBREE_ZIP_MODE=OFF") - conf.append("-D CMAKE_SKIP_INSTALL_RPATH=OFF") - conf.append("-D CMAKE_INSTALL_PREFIX=/usr") - conf.append("-D EMBREE_TBB_ROOT=/usr") elif OS == "macosx" and config["package"] == "ZIP": - conf.append("-D EMBREE_SIGN_FILE=/NAS/packages/apps/signfile/mac/SignFile") + conf.append("-D EMBREE_SIGN_FILE="+NAS+"/signfile/mac/SignFile") conf.append("-D EMBREE_INSTALL_DEPENDENCIES=ON") conf.append("-D EMBREE_ZIP_MODE=ON") conf.append("-D CMAKE_SKIP_INSTALL_RPATH=OFF") @@ -341,19 +376,8 @@ def runConfig(config): conf.append("-D CMAKE_INSTALL_LIBDIR=lib") conf.append("-D CMAKE_INSTALL_DOCDIR=doc") conf.append("-D CMAKE_INSTALL_BINDIR=bin") - elif OS == "macosx" and config["package"] == "PKG": - conf.append("-D EMBREE_SIGN_FILE=/NAS/packages/apps/signfile/mac/SignFile") - conf.append("-D EMBREE_INSTALL_DEPENDENCIES=OFF") - conf.append("-D EMBREE_ZIP_MODE=OFF") - conf.append("-D CMAKE_SKIP_INSTALL_RPATH=OFF") - conf.append("-D CMAKE_MACOSX_RPATH=ON") - conf.append("-D CMAKE_INSTALL_PREFIX=/opt/local") - conf.append("-D CMAKE_INSTALL_INCLUDEDIR=include") - conf.append("-D CMAKE_INSTALL_LIBDIR=lib") - conf.append("-D CMAKE_INSTALL_DOCDIR=../../Applications/Embree3/doc") - conf.append("-D CMAKE_INSTALL_BINDIR=../../Applications/Embree3/bin") elif OS == "windows" and config["package"] == "ZIP": - conf.append("-D EMBREE_SIGN_FILE=\\\\vis-nassie.an.intel.com\\NAS\\packages\\apps\\signfile\\windows\\SignFile.exe") + conf.append("-D EMBREE_SIGN_FILE="+NAS+"\\signfile\\windows\\SignFile.exe") conf.append("-D EMBREE_INSTALL_DEPENDENCIES=ON") conf.append("-D EMBREE_ZIP_MODE=ON") conf.append("-D CMAKE_INSTALL_INCLUDEDIR=include") @@ -361,71 +385,79 @@ def runConfig(config): conf.append("-D CMAKE_INSTALL_DATAROOTDIR=") conf.append("-D CMAKE_INSTALL_DOCDIR=doc") conf.append("-D CMAKE_INSTALL_BINDIR=bin") - elif OS == "windows" and config["package"] == "MSI": - conf.append("-D EMBREE_SIGN_FILE=\\\\vis-nassie.an.intel.com\\NAS\\packages\\apps\\signfile\\windows\\SignFile.exe") - conf.append("-D EMBREE_INSTALL_DEPENDENCIES=ON") - conf.append("-D EMBREE_ZIP_MODE=OFF") - conf.append("-D CMAKE_INSTALL_INCLUDEDIR=include") - conf.append("-D CMAKE_INSTALL_LIBDIR=lib") - conf.append("-D CMAKE_INSTALL_DATAROOTDIR=") - conf.append("-D CMAKE_INSTALL_DOCDIR=doc") - conf.append("-D CMAKE_INSTALL_BINDIR=bin") else: sys.stderr.write("unknown package mode: "+OS+":"+config["package"]) sys.exit(1) - ctest = "ctest -VV -S scripts/test.cmake" - if g_cdash != "": ctest += " -D CTEST_DROP_SITE="+g_cdash - ctest += " -D EMBREE_TESTING_INTENSITY="+str(g_intensity) + if rtcore: + conf.append("-D EMBREE_CONFIG="+(",".join(rtcore))) + + if g_benchmarkMode and OS == "linux": + conf.append("-D EMBREE_USE_GOOGLE_BENCHMARK=ON") + conf.append("-D benchmark_DIR:PATH="+NAS+"/google-benchmark/vis-perf-x8280-1/lib64/cmake/benchmark") + + ctest_suffix = "" + ctest_suffix += " -D EMBREE_TESTING_INTENSITY="+str(g_intensity) if "klocwork" in config: - ctest += " -D EMBREE_TESTING_KLOCWORK="+config["klocwork"] - ctest += " -D CTEST_CONFIGURATION_TYPE=\""+build+"\"" - ctest += " -D CTEST_BUILD_OPTIONS=\"" + escape(" ".join(conf))+"\"" - if g_debugMode: - for e in env: print(' '+e) - print(' '+ctest+'\n') + ctest_suffix += " -D EMBREE_TESTING_KLOCWORK="+config["klocwork"] + if "update_models" in config: + ctest_suffix += " -D EMBREE_UPDATE_MODELS="+config["update_models"] else: - cmd = "" - for e in env: cmd += e + " && " - cmd += ctest+"\n" - if OS == "windows": - try: + ctest_suffix += " -D EMBREE_UPDATE_MODELS=ON" + + ctest_suffix += " -D CTEST_CONFIGURATION_TYPE=\""+build+"\"" + ctest_suffix += " -D CTEST_BUILD_OPTIONS=\"" + escape(" ".join(conf))+"\"" + ctest_env = "" + for e in env: + ctest_env += e + " && " + + ctest_conf = [ctest_env, ctest_suffix, cmake_build_suffix, threads] + pickle.dump(ctest_conf, open(".ctest_conf", "wb"), 0) + +# builds or runs tests for specified host machine +def run(mode): + if not (mode == "build" or mode=="test"): + sys.stderr.write("unknown mode: "+mode+". should be 'build' or 'test'") + sys.exit(1) + + [ctest_env, ctest_suffix, cmake_build_suffix, threads] = pickle.load(open(".ctest_conf", "rb")) + cmd = ctest_env + "ctest -VV -S "+ os.path.join("scripts","test.cmake -DSTAGE="+mode+" -DTHREADS="+threads+" -DBUILD_SUFFIX=\""+cmake_build_suffix+"\"") + ctest_suffix + + if mode == "test" and not OS == "windows": + fix_cmake_paths() + + # execute step + if (g_debugMode): + print(cmd) + else: + try: + if OS == "windows": subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=True) - except subprocess.CalledProcessError as e: - sys.stderr.write("windows test invokation failed with return code "+str(e.returncode)) - sys.exit(1) - else: - # need to use bash shell as we configured environment modules only for bash - process = subprocess.Popen(['bash','-l'], stdin=subprocess.PIPE) - process.communicate(input=cmd.encode("utf-8")) - if process.returncode != 0: - sys.stderr.write("test invokation failed with return code "+str(process.returncode)) - sys.exit(1) - + else: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=True, executable='/bin/bash') + except subprocess.CalledProcessError as e: + sys.stderr.write("windows test invocation failed with return code "+str(e.returncode)) + sys.exit(1) + +g_config = {} def parseCommandLine(argv): - global g_cdash - global g_docker global g_config - global g_mode - global g_intensity global g_debugMode + global g_benchmarkMode if len(argv) == 0: + #printUsage() return; - elif len(argv)>=2 and argv[0] == "--cdash": - g_cdash = argv[1] - parseCommandLine(argv[2:len(argv)]) - elif len(argv)>=2 and argv[0] == "--mode": - g_mode = argv[1] elif len(argv)>=1 and argv[0] == "--debug": g_debugMode = True parseCommandLine(argv[1:len(argv)]) + elif len(argv)>=1 and argv[0] == "--benchmark": + g_benchmarkMode = True + parseCommandLine(argv[1:len(argv)]) elif len(argv)>=1 and argv[0] == "--help": - printUsage() - return; + #printUsage() + return elif ':' in argv[0]: p = argv[0].split(":") - if p[0] == "intensity": - g_intensity = int(p[1]) if p[0] == "isas": g_config["isa"] = p[1].split('-') else: @@ -434,6 +466,25 @@ def parseCommandLine(argv): else: sys.stderr.write("unknown command line option: "+argv[0]) sys.exit(1) - -parseCommandLine(sys.argv[1:len(sys.argv)]) -runConfig(g_config) + +argv = sys.argv +g_mode = "" +if len(argv) < 2: + #printUsage() + sys.exit(1) +else: + g_mode = argv[1] + if not (g_mode == "configure" or g_mode == "build" or g_mode == "test"): + #printUsage() + sys.exit(1) + parseCommandLine(argv[2:len(argv)]) + +if (g_mode == "configure"): + runConfig(g_config) +elif (g_mode == "build"): + run("build") +elif (g_mode == "test"): + run("test") +else: + sys.stderr.write("unknown mode: "+g_mode+". should be 'configure', 'build', or 'test'") + sys.exit(1) diff --git a/third-party-programs.txt b/third-party-programs.txt index c73d86324f..7e36c69cca 100644 --- a/third-party-programs.txt +++ b/third-party-programs.txt @@ -1,17 +1,8 @@ Intel(R) Embree Third Party Programs File -This file contains the list of third party software (third party -programs) contained in the Intel software and their required notices -and/or license terms. This third party software, even if included with -the distribution of the Intel software, may be governed by separate -license terms, including without limitation, third party license -terms, other Intel software license terms, and open source software -license terms. These separate license terms govern your use of the -third party programs as set forth in the third-party-programs.txt or -other similarly-named text file. - -Third party programs and their corresponding required notices and/or -license terms are listed below. +This file contains the list of third party software (third party programs) contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the third-party-programs.txt or other similarly-named text file. + +Third party programs and their corresponding required notices and/or license terms are listed below. ------------------------------------------------------------- @@ -251,7 +242,8 @@ tree and in the comment header of each source file. 3. imgui Copyright (c) 2014-2020 Omar Cornut - + SSE2NEON + The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy @@ -337,64 +329,21 @@ DEALINGS IN THE SOFTWARE. ------------------------------------------------------------- 6. Visual C++ Redistributables for Visual Studio -1. License. This software package from Intel (the Software Package) -contains code from Microsoft (the Distributable Code). You are -provided a non-transferable, non-exclusive, non-sublicensable, limited -right and license only to use the Distributable Code as part of this -Software Package. You are not allowed to copy, modify, remove the -Distributable Code from the Software Package or redistribute the -Distributable Code. - -2. Restrictions. The Distributable Code is licensed, not sold. You are -only provided the above rights to use the Distributable Code. Intel -and Microsoft reserve all other rights. Unless applicable law gives -you more rights, you may use the Distributable Code only as expressly -permitted in these terms. In using the Distributable Code, you must -comply with any technical limitations in the Distributable Code that -only allow you to use it in certain ways. You may not: - - work around any technical limitations in the Distributable Code; - - reverse engineer, decompile or disassemble the software, or - otherwise attempt to derive the source code for the Distributable - Code, except and to the extent required by third party licensing - terms governing use of certain open source components that may be - included in the Distributable Code; - - remove, minimize, block or modify any notices of Intel, Microsoft or - its suppliers in the Distributable Code; - - use the Distributable Code in any way that is against the law; or - share, publish, rent or lease the software, or provide the - Distributable Code as a stand-alone offering for others to use. - -3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED AS IS WITHOUT ANY -EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF -MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. - -4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, -MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU -CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST -PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. This limitation -applies to (a) anything related to the Distributable Code; and (b) -claims for breach of contract, breach of warranty, guarantee or -condition, strict liability, negligence, or other tort to the extent -permitted by applicable law. It also applies even if Intel or -Microsoft knew or should have known about the possibility of the -damages. The above limitation or exclusion may not apply to you -because your state or country may not allow the exclusion or -limitation of incidental, consequential or other damages. - -5. Export Restrictions. You must comply with all domestic and -international export laws and regulations that apply to the software, -which include restrictions on destinations, end users, and end -use. For further information on export restrictions, visit -www.microsoft.com/exporting. +1. License. This software package from Intel (the “Software Package”) contains code from Microsoft (the “Distributable Code”). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code. +2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: +• work around any technical limitations in the Distributable Code; +• reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; +• remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; +• use the Distributable Code in any way that is against the law; or +• share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. +3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS” WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. +4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. +This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. +5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. ------------------------------------------------------------- -The following third party programs have their own third party program -files. These additional third party program files are as follows: +The following third party programs have their own third party program files. These additional third party program files are as follows: 1. Intel(R) Threading Building Blocks licenses located in the third-party-programs-TBB.txt file. diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index fbfef6adb4..1fa8fb2c38 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -1,39 +1,39 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 include(CMakeDependentOption) OPTION(EMBREE_TUTORIALS "Enable to build Embree tutorials" ON) -ADD_SUBDIRECTORY(common/image) CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_GLFW "Enables GLFW usage in tutorials. When disabled tutorial can only render to disk." ON "EMBREE_TUTORIALS" OFF) IF (EMBREE_TUTORIALS) +ADD_SUBDIRECTORY(common/image) IF (EMBREE_TUTORIALS_GLFW) IF (NOT WIN32 OR EMBREE_EXTERNAL_GLFW) - + FIND_PACKAGE(glfw3 REQUIRED) SET(GLFW_LIBRARY glfw) SET(GLFW_INCLUDE_DIRS) - + ELSE() - + # detect and select Win32 or x64 IF (CMAKE_SIZEOF_VOID_P EQUAL 8) SET(ARCH x64) ELSE() SET(ARCH Win32) ENDIF() - + # detect Visual Studio version IF (MSVC12) SET(VCVER vc12) ELSE() SET(VCVER vc14) ENDIF() - + FIND_PATH(GLFW_INCLUDE_DIRS NAMES GLFW/glfw3.h PATHS common/glfw/include) FIND_LIBRARY(GLFW_LIBRARY glfw3 common/glfw/${ARCH}/${VCVER}) MARK_AS_ADVANCED( diff --git a/tutorials/Makefile b/tutorials/Makefile index d7e272d746..bce621cbe5 100644 --- a/tutorials/Makefile +++ b/tutorials/Makefile @@ -1,5 +1,9 @@ +## Copyright 2009-2021 Intel Corporation +## SPDX-License-Identifier: Apache-2.0 -ispc2cpp: +ispc2cpp: common triangle_geometry point_geometry dynamic_scene user_geometry viewer viewer_stream viewer_anim instanced_geometry intersection_filter pathtracer hair_geometry subdivision_geometry displacement_geometry lazy_geometry motion_blur_geometry interpolation_geometry curve_geometry grid_geometry quaternion_motion_blur + +common: FORCE @./ispc2cpp.sh common/tutorial/tutorial_device.isph common/tutorial/tutorial_device.h @./ispc2cpp.sh common/tutorial/tutorial_device.ispc common/tutorial/tutorial_device.cpp @./ispc2cpp.sh common/core/differential_geometry.isph common/core/differential_geometry.h @@ -16,29 +20,52 @@ ispc2cpp: @./ispc2cpp.sh common/texture/texture2d.isph common/texture/texture2d.h @./ispc2cpp.sh common/texture/texture2d.ispc common/texture/texture2d.cpp @./ispc2cpp.sh common/texture/texture_param.isph common/texture/texture_param.h + +triangle_geometry: FORCE @./ispc2cpp.sh triangle_geometry/triangle_geometry_device.isph triangle_geometry/triangle_geometry_device.h @./ispc2cpp.sh triangle_geometry/triangle_geometry_device.ispc triangle_geometry/triangle_geometry_device.cpp +point_geometry: FORCE @./ispc2cpp.sh point_geometry/point_geometry_device.isph point_geometry/point_geometry_device.h @./ispc2cpp.sh point_geometry/point_geometry_device.ispc point_geometry/point_geometry_device.cpp +dynamic_scene: FORCE @./ispc2cpp.sh dynamic_scene/dynamic_scene_device.ispc dynamic_scene/dynamic_scene_device.cpp +user_geometry: FORCE + @./ispc2cpp.sh user_geometry/user_geometry_device.isph user_geometry/user_geometry_device.h @./ispc2cpp.sh user_geometry/user_geometry_device.ispc user_geometry/user_geometry_device.cpp +viewer: FORCE @./ispc2cpp.sh viewer/viewer_device.isph viewer/viewer_device.h @./ispc2cpp.sh viewer/viewer_device.ispc viewer/viewer_device.cpp +viewer_stream: FORCE @./ispc2cpp.sh viewer_stream/viewer_stream_device.ispc viewer_stream/viewer_stream_device.cpp +viewer_anim: FORCE @./ispc2cpp.sh viewer_anim/viewer_anim_device.ispc viewer_anim/viewer_anim_device.cpp +instanced_geometry: FORCE + @./ispc2cpp.sh instanced_geometry/instanced_geometry_device.isph instanced_geometry/instanced_geometry_device.h @./ispc2cpp.sh instanced_geometry/instanced_geometry_device.ispc instanced_geometry/instanced_geometry_device.cpp +intersection_filter: FORCE @./ispc2cpp.sh intersection_filter/intersection_filter_device.isph intersection_filter/intersection_filter_device.h @./ispc2cpp.sh intersection_filter/intersection_filter_device.ispc intersection_filter/intersection_filter_device.cpp +pathtracer: FORCE @./ispc2cpp.sh pathtracer/pathtracer_device.ispc pathtracer/pathtracer_device.cpp +hair_geometry: FORCE @./ispc2cpp.sh hair_geometry/hair_geometry_device.ispc hair_geometry/hair_geometry_device.cpp +subdivision_geometry: FORCE @./ispc2cpp.sh subdivision_geometry/subdivision_geometry_device.ispc subdivision_geometry/subdivision_geometry_device.cpp +displacement_geometry: FORCE @./ispc2cpp.sh displacement_geometry/displacement_geometry_device.ispc displacement_geometry/displacement_geometry_device.cpp +lazy_geometry: FORCE @./ispc2cpp.sh lazy_geometry/lazy_geometry_device.ispc lazy_geometry/lazy_geometry_device.cpp +motion_blur_geometry: FORCE @./ispc2cpp.sh motion_blur_geometry/motion_blur_geometry_device.isph motion_blur_geometry/motion_blur_geometry_device.h @./ispc2cpp.sh motion_blur_geometry/motion_blur_geometry_device.ispc motion_blur_geometry/motion_blur_geometry_device.cpp +interpolation_geometry: FORCE + @./ispc2cpp.sh interpolation/interpolation_device.isph interpolation/interpolation_device.h @./ispc2cpp.sh interpolation/interpolation_device.ispc interpolation/interpolation_device.cpp +curve_geometry: FORCE @./ispc2cpp.sh curve_geometry/curve_geometry_device.ispc curve_geometry/curve_geometry_device.cpp +grid_geometry: FORCE @./ispc2cpp.sh grid_geometry/grid_geometry_device.ispc grid_geometry/grid_geometry_device.cpp +quaternion_motion_blur: FORCE @./ispc2cpp.sh quaternion_motion_blur/quaternion_motion_blur_device.ispc quaternion_motion_blur/quaternion_motion_blur_device.cpp osp2emb: @@ -59,3 +86,5 @@ osp2emb: @echo "export void dummy() {} // just to avoid linker warning under MacOSX" >> common/lights/light.ispc all: osp2emb ispc2cpp + +FORCE: diff --git a/tutorials/buildbench/CMakeLists.txt b/tutorials/buildbench/CMakeLists.txt index 116e23a236..3a2a039251 100644 --- a/tutorials/buildbench/CMakeLists.txt +++ b/tutorials/buildbench/CMakeLists.txt @@ -1,6 +1,6 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(EMBREE_ISPC_SUPPORT OFF) INCLUDE(tutorial) -ADD_TUTORIAL(buildbench) +ADD_TUTORIAL(buildbench) \ No newline at end of file diff --git a/tutorials/buildbench/buildbench.cpp b/tutorials/buildbench/buildbench.cpp index 54e44932b3..c874b33150 100644 --- a/tutorials/buildbench/buildbench.cpp +++ b/tutorials/buildbench/buildbench.cpp @@ -1,16 +1,24 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 +#include "buildbench.h" + #include "../common/tutorial/tutorial.h" +#include +#include +#include + +RTC_NAMESPACE_USE; + namespace embree { uint32_t g_num_user_threads = 0; - + struct Tutorial : public SceneLoadingTutorialApplication { Tutorial() - : SceneLoadingTutorialApplication("build_bench",FEATURE_RTCORE) + : SceneLoadingTutorialApplication("build_bench",FEATURE_RTCORE) { interactive = false; @@ -21,19 +29,64 @@ namespace embree rtcore += ",start_threads=0,set_affinity=0"; }, "--user_threads : invokes user thread benchmark with specified number of application provided build threads"); } - + void postParseCommandLine() override { /* load default scene if none specified */ - if (sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/cornell_box.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } } }; + std::unique_ptr tutorial {}; + + static void buildBench(BenchState& state, BenchParams& params, BuildBenchParams& buildParams, int argc, char** argv) + { + if (!tutorial) { + tutorial.reset(new Tutorial()); + tutorial->main(argc,argv); + } + + if (buildParams.userThreads == 0) + { + /* set error handler */ + if (buildParams.buildBenchType & BuildBenchType::UPDATE_DYNAMIC_DEFORMABLE) { + Benchmark_Dynamic_Update(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_REFIT); + } + if (buildParams.buildBenchType & BuildBenchType::UPDATE_DYNAMIC_DYNAMIC) { + Benchmark_Dynamic_Update(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_LOW); + } + if (buildParams.buildBenchType & BuildBenchType::UPDATE_DYNAMIC_STATIC) { + Benchmark_Dynamic_Update(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_MEDIUM); + } + if (buildParams.buildBenchType & BuildBenchType::CREATE_DYNAMIC_DEFORMABLE) { + Benchmark_Dynamic_Create(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_REFIT); + } + if (buildParams.buildBenchType & BuildBenchType::CREATE_DYNAMIC_DYNAMIC) { + Benchmark_Dynamic_Create(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_LOW); + } + if (buildParams.buildBenchType & BuildBenchType::CREATE_DYNAMIC_STATIC) { + Benchmark_Dynamic_Create(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_MEDIUM); + } + if (buildParams.buildBenchType & BuildBenchType::CREATE_STATIC_STATIC) { + Benchmark_Static_Create(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_MEDIUM,RTC_BUILD_QUALITY_MEDIUM); + } + if (buildParams.buildBenchType & BuildBenchType::CREATE_HIGH_QUALITY_STATIC_STATIC) { + Benchmark_Static_Create(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_MEDIUM,RTC_BUILD_QUALITY_HIGH); + } + } + else + { + if (buildParams.buildBenchType & BuildBenchType::CREATE_USER_THREADS_STATIC_STATIC) { + Benchmark_Static_Create_UserThreads(state, params, buildParams, tutorial->ispc_scene.get(), RTC_BUILD_QUALITY_MEDIUM,RTC_BUILD_QUALITY_MEDIUM); + } + } + } } -int main(int argc, char** argv) { - return embree::Tutorial().main(argc,argv); +int main(int argc, char **argv) +{ + return embree::TutorialBuildBenchmark(embree::buildBench).main(argc, argv); } diff --git a/tutorials/buildbench/buildbench.h b/tutorials/buildbench/buildbench.h new file mode 100644 index 0000000000..92fea313a2 --- /dev/null +++ b/tutorials/buildbench/buildbench.h @@ -0,0 +1,23 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "../common/tutorial/benchmark.h" + +#include "../../include/embree3/rtcore_common.h" + +namespace embree { + struct ISPCScene; + +#if defined(RTC_NAMESPACE) + using RTC_NAMESPACE::RTCBuildQuality; +#endif + + void Benchmark_Dynamic_Update(BenchState& state, BenchParams& params, BuildBenchParams& buildParams, ISPCScene* ispc_scene, RTCBuildQuality quality = RTCBuildQuality::RTC_BUILD_QUALITY_LOW); + void Benchmark_Dynamic_Create(BenchState& state, BenchParams& params, BuildBenchParams& buildParams, ISPCScene* ispc_scene, RTCBuildQuality quality); + void Benchmark_Static_Create(BenchState& state, BenchParams& params, BuildBenchParams& buildParams, ISPCScene* ispc_scene, RTCBuildQuality quality, RTCBuildQuality qflags); + void Benchmark_Static_Create_UserThreads(BenchState& state, BenchParams& params, BuildBenchParams& buildParams, ISPCScene* ispc_scene, RTCBuildQuality quality, RTCBuildQuality qflags); + + size_t getNumPrimitives(ISPCScene* scene_in); +} \ No newline at end of file diff --git a/tutorials/buildbench/buildbench_device.cpp b/tutorials/buildbench/buildbench_device.cpp index a4da03627a..d0deba1992 100644 --- a/tutorials/buildbench/buildbench_device.cpp +++ b/tutorials/buildbench/buildbench_device.cpp @@ -1,26 +1,29 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 +#include "buildbench.h" + #include "../common/tutorial/tutorial_device.h" #include "../common/tutorial/scene_device.h" + +#ifdef USE_GOOGLE_BENCHMARK +#include +#endif + #include namespace embree { extern uint32_t g_num_user_threads; + + RTCScene g_scene; // do not use! - static const MAYBE_UNUSED size_t skip_iterations = 5; + // for legacy reasons static const MAYBE_UNUSED size_t iterations_dynamic_deformable = 200; static const MAYBE_UNUSED size_t iterations_dynamic_dynamic = 200; static const MAYBE_UNUSED size_t iterations_dynamic_static = 50; static const MAYBE_UNUSED size_t iterations_static_static = 30; - - extern "C" ISPCScene* g_ispc_scene; - - /* scene data */ - RTCScene g_scene = nullptr; - - + void convertTriangleMesh(ISPCTriangleMesh* mesh, RTCScene scene_out, RTCBuildQuality quality) { RTCGeometry geom = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_TRIANGLE); @@ -31,7 +34,7 @@ namespace embree { } rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, mesh->triangles, 0, sizeof(ISPCTriangle), mesh->numTriangles); rtcCommitGeometry(geom); - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); rtcReleaseGeometry(geom); } @@ -45,7 +48,7 @@ namespace embree { } rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT4, mesh->quads, 0, sizeof(ISPCQuad), mesh->numQuads); rtcCommitGeometry(geom); - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); rtcReleaseGeometry(geom); } @@ -68,7 +71,7 @@ namespace embree { rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT, 0, RTC_FORMAT_FLOAT, mesh->vertex_crease_weights, 0, sizeof(float), mesh->numVertexCreases); rtcSetGeometrySubdivisionMode(geom, 0, mesh->position_subdiv_mode); rtcCommitGeometry(geom); - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); rtcReleaseGeometry(geom); } @@ -85,7 +88,7 @@ namespace embree { if (hair->type != RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE) rtcSetGeometryTessellationRate(geom,(float)hair->tessellation_rate); rtcCommitGeometry(geom); - hair->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); rtcReleaseGeometry(geom); } @@ -120,7 +123,7 @@ namespace embree { assert(false); } } - + size_t getNumPrimitives(ISPCScene* scene_in) { size_t numPrimitives = 0; @@ -151,44 +154,55 @@ namespace embree { return scene_in->numGeometries; } - void updateObjects(ISPCScene* scene_in, RTCScene scene_out) // FIXME: geomID can be accessed easier now + void updateObjects(ISPCScene* scene_in, RTCScene scene_out) { size_t numGeometries = scene_in->numGeometries; for (size_t i=0; igeometries[i]; - RTCGeometry geom = rtcGetGeometry(scene_out,geometry->geomID); + RTCGeometry geom = rtcGetGeometry(scene_out,i); rtcUpdateGeometryBuffer(geom,RTC_BUFFER_TYPE_VERTEX, 0); rtcCommitGeometry(geom); } } - void deleteObjects(ISPCScene* scene_in, RTCScene scene_out) // FIXME: geomID can be accessed easier now + void deleteObjects(ISPCScene* scene_in, RTCScene scene_out) { size_t numGeometries = scene_in->numGeometries; for (size_t i=0; igeometries[i]; - rtcDetachGeometry(scene_out,geometry->geomID); - } + rtcDetachGeometry(scene_out,i); } - - void Benchmark_Dynamic_Update(ISPCScene* scene_in, size_t benchmark_iterations, RTCBuildQuality quality = RTC_BUILD_QUALITY_LOW) + +#ifdef USE_GOOGLE_BENCHMARK + inline void addCounter(BenchState& state, size_t numPrims, size_t numObjects) { - assert(g_scene == nullptr); - g_scene = createScene(RTC_SCENE_FLAG_DYNAMIC, RTC_BUILD_QUALITY_LOW); - convertScene(g_scene, scene_in, quality); + state.state->SetItemsProcessed(state.state->iterations() * numPrims); + state.state->counters["Prims"] = ::benchmark::Counter(numPrims); + state.state->counters["Objects"] = ::benchmark::Counter(numObjects); + } +#endif + + void Benchmark_Dynamic_Update_Legacy(ISPCScene* scene_in, BenchParams& params, RTCBuildQuality quality = RTC_BUILD_QUALITY_LOW) + { + size_t benchmark_iterations = params.minTimeOrIterations; + if (benchmark_iterations <= 0) { + benchmark_iterations = (quality == RTC_BUILD_QUALITY_MEDIUM) + ? iterations_dynamic_static + : iterations_dynamic_dynamic; + } + + RTCScene scene = createScene(RTC_SCENE_FLAG_DYNAMIC, RTC_BUILD_QUALITY_LOW); + convertScene(scene, scene_in, quality); size_t primitives = getNumPrimitives(scene_in); size_t objects = getNumObjects(scene_in); size_t iterations = 0; double time = 0.0; - for(size_t i=0;i= skip_iterations) + if (i >= params.skipIterations) { time += t1 - t0; iterations++; @@ -204,31 +218,79 @@ namespace embree { else FATAL("unknown flags"); - std::cout << primitives << " primitives, " << objects << " objects, " + if (iterations == 0) iterations = 1; + std::cout << iterations << " iterations, " << primitives << " primitives, " << objects << " objects, " << time/iterations << " s, " << 1.0 / (time/iterations) * primitives / 1000000.0 << " Mprims/s" << std::endl; - rtcReleaseScene (g_scene); - g_scene = nullptr; + rtcReleaseScene (scene); } + + void Benchmark_Dynamic_Update( + BenchState& state, + BenchParams& params, + BuildBenchParams& buildParams, + ISPCScene* ispc_scene, + RTCBuildQuality quality) + { +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + Benchmark_Dynamic_Update_Legacy(ispc_scene, params, quality); + return; + } + + RTCScene scene = createScene(RTC_SCENE_FLAG_DYNAMIC, RTC_BUILD_QUALITY_LOW); + convertScene(scene, ispc_scene, quality); + const size_t primitives = getNumPrimitives(ispc_scene); + const size_t objects = getNumObjects(ispc_scene); + + // warm-up + for (int i = 0; i < params.minTimeOrIterations; ++i) { + updateObjects(ispc_scene,scene); + rtcCommitScene(scene); + } - void Benchmark_Dynamic_Create(ISPCScene* scene_in, size_t benchmark_iterations, RTCBuildQuality quality = RTC_BUILD_QUALITY_MEDIUM) + for (auto _ : *state.state) { + state.state->PauseTiming(); + + updateObjects(ispc_scene,scene); + + state.state->ResumeTiming(); + + rtcCommitScene (scene); + } + + addCounter(state, primitives, objects); + + rtcReleaseScene (scene); +#else + Benchmark_Dynamic_Update_Legacy(ispc_scene, params, quality); +#endif + } + + void Benchmark_Dynamic_Create_Legacy(ISPCScene* scene_in, BenchParams& params, RTCBuildQuality quality = RTC_BUILD_QUALITY_MEDIUM) { - assert(g_scene == nullptr); - g_scene = createScene(RTC_SCENE_FLAG_DYNAMIC, RTC_BUILD_QUALITY_LOW); - convertScene(g_scene, scene_in,quality); + size_t benchmark_iterations = params.minTimeOrIterations; + if (benchmark_iterations <= 0) { + benchmark_iterations = (quality == RTC_BUILD_QUALITY_MEDIUM) + ? iterations_dynamic_static + : iterations_dynamic_dynamic; + } + + RTCScene scene = createScene(RTC_SCENE_FLAG_DYNAMIC, RTC_BUILD_QUALITY_LOW); + convertScene(scene, scene_in,quality); size_t primitives = getNumPrimitives(scene_in); size_t objects = getNumObjects(scene_in); size_t iterations = 0; double time = 0.0; - for(size_t i=0;i= skip_iterations) + if (i >= params.skipIterations) { time += t1 - t0; iterations++; @@ -244,41 +306,87 @@ namespace embree { else FATAL("unknown flags"); - std::cout << primitives << " primitives, " << objects << " objects, " + if (iterations == 0) iterations = 1; + std::cout << iterations << " iterations, " << primitives << " primitives, " << objects << " objects, " << time/iterations << " s, " << 1.0 / (time/iterations) * primitives / 1000000.0 << " Mprims/s" << std::endl; - rtcReleaseScene (g_scene); - g_scene = nullptr; + rtcReleaseScene (scene); + } + + void Benchmark_Dynamic_Create( + BenchState& state, + BenchParams& params, + BuildBenchParams& buildParams, + ISPCScene* ispc_scene, + RTCBuildQuality quality) + { +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + Benchmark_Dynamic_Create_Legacy(ispc_scene, params, quality); + return; + } + + RTCScene scene = createScene(RTC_SCENE_FLAG_DYNAMIC, RTC_BUILD_QUALITY_LOW); + convertScene(scene, ispc_scene, quality); + const size_t primitives = getNumPrimitives(ispc_scene); + const size_t objects = getNumObjects(ispc_scene); + + // warm-up + for (int i = 0; i < params.minTimeOrIterations; ++i) { + deleteObjects(ispc_scene, scene); + convertScene(scene, ispc_scene, quality); + rtcCommitScene(scene); + } + + for (auto _ : *state.state) { + state.state->PauseTiming(); + + deleteObjects(ispc_scene, scene); + convertScene(scene, ispc_scene, quality); + + state.state->ResumeTiming(); + + rtcCommitScene(scene); + } + + addCounter(state, primitives, objects); + + rtcReleaseScene (scene); +#else + Benchmark_Dynamic_Create_Legacy(ispc_scene, params, quality); +#endif } - void Benchmark_Static_Create(ISPCScene* scene_in, size_t benchmark_iterations, RTCBuildQuality quality, RTCBuildQuality qflags) + void Benchmark_Static_Create_Legacy(ISPCScene* scene_in, BenchParams& params, RTCBuildQuality quality, RTCBuildQuality qflags) { - assert(g_scene == nullptr); + size_t benchmark_iterations = params.minTimeOrIterations; + if (benchmark_iterations <= 0) + benchmark_iterations = iterations_static_static; + size_t primitives = getNumPrimitives(scene_in); size_t objects = getNumObjects(scene_in); size_t iterations = 0; double time = 0.0; - - for(size_t i=0;i threads; threads.reserve(numThreads); double t0 = getSeconds(); - rtcCommitScene (g_scene); + rtcCommitScene (scene); double t1 = getSeconds(); - if (i >= skip_iterations) + if (i >= params.skipIterations) { time += t1 - t0; iterations++; } - rtcReleaseScene (g_scene); + rtcReleaseScene (scene); } if (qflags == RTC_BUILD_QUALITY_HIGH) @@ -295,37 +403,97 @@ namespace embree { else FATAL("unknown flags"); - std::cout << primitives << " primitives, " << objects << " objects, " + if (iterations == 0) iterations = 1; + std::cout << iterations << " iterations, " << primitives << " primitives, " << objects << " objects, " << time/iterations << " s, " << 1.0 / (time/iterations) * primitives / 1000000.0 << " Mprims/s" << std::endl; - - g_scene = nullptr; } - BarrierSys barrier; - volatile bool term = false; - - void perform_work(size_t threadID) + void Benchmark_Static_Create( + BenchState& state, + BenchParams& params, + BuildBenchParams& buildParams, + ISPCScene* ispc_scene, + RTCBuildQuality quality, + RTCBuildQuality qflags) { - setAffinity(threadID); - while (true) { - barrier.wait(); - if (term) return; - rtcJoinCommitScene(g_scene); - barrier.wait(); +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + Benchmark_Static_Create_Legacy(ispc_scene, params, quality, qflags); + return; } + + const size_t primitives = getNumPrimitives(ispc_scene); + const size_t objects = getNumObjects(ispc_scene); + + // warm-up + for (int i = 0; i < params.minTimeOrIterations; ++i) { + RTCScene scene = createScene(RTC_SCENE_FLAG_NONE, qflags); + convertScene(scene, ispc_scene, quality); + const size_t numThreads = TaskScheduler::threadCount(); + std::vector threads; + threads.reserve(numThreads); + rtcCommitScene(scene); + rtcReleaseScene(scene); + } + + for(auto _ : *state.state) { + state.state->PauseTiming(); + + RTCScene scene = createScene(RTC_SCENE_FLAG_NONE, qflags); + convertScene(scene, ispc_scene, quality); + + const size_t numThreads = TaskScheduler::threadCount(); + std::vector threads; + threads.reserve(numThreads); + + state.state->ResumeTiming(); + + rtcCommitScene(scene); + + state.state->PauseTiming(); + + rtcReleaseScene(scene); + + state.state->ResumeTiming(); + } + + addCounter(state, primitives, objects); +#else + Benchmark_Static_Create_Legacy(ispc_scene, params, quality, qflags); +#endif } + struct Helper { + BarrierSys barrier; + volatile bool term = false; + RTCScene scene; + + void perform_work(size_t threadID) { + setAffinity(threadID); + while (true) { + barrier.wait(); + if (term) + return; + rtcJoinCommitScene(scene); + barrier.wait(); + } + } + } helper; - void Benchmark_Static_Create_UserThreads(ISPCScene* scene_in, size_t benchmark_iterations, RTCBuildQuality quality, RTCBuildQuality qflags) + void Benchmark_Static_Create_UserThreads_Legacy(ISPCScene* scene_in, BenchParams& params, RTCBuildQuality quality, RTCBuildQuality qflags) { - assert(g_scene == nullptr); + size_t benchmark_iterations = params.minTimeOrIterations; + if (benchmark_iterations <= 0) + benchmark_iterations = iterations_static_static; + size_t primitives = getNumPrimitives(scene_in); size_t objects = getNumObjects(scene_in); size_t iterations = 0; double time = 0.0; const size_t numThreads = g_num_user_threads; - barrier.init(numThreads); + Helper helper; + helper.barrier.init(numThreads); std::vector threads; threads.reserve(numThreads); @@ -333,36 +501,38 @@ namespace embree { /* ramp up threads */ setAffinity(0); for (size_t i=1; i= skip_iterations) + if (i >= params.skipIterations) { time += t1 - t0; iterations++; } + + if (iterations == 0) iterations = 1; std::cout << primitives << " primitives, " << objects << " objects, " << time/iterations << " s, " << 1.0 / (time/iterations) * primitives / 1000000.0 << " Mprims/s" << std::endl; - rtcReleaseScene (g_scene); + rtcReleaseScene(helper.scene); } /* terminate task loop */ - term = true; - barrier.wait(); + helper.term = true; + helper.barrier.wait(); for (auto& thread: threads) thread.join(); @@ -380,50 +550,85 @@ namespace embree { else FATAL("unknown flags"); - std::cout << primitives << " primitives, " << objects << " objects, " + if (iterations == 0) iterations = 1; + std::cout << iterations << " iterations, " << primitives << " primitives, " << objects << " objects, " << time/iterations << " s, " << 1.0 / (time/iterations) * primitives / 1000000.0 << " Mprims/s" << std::endl; - - g_scene = nullptr; } - - void Pause() + void Benchmark_Static_Create_UserThreads( + BenchState& state, + BenchParams& params, + BuildBenchParams& buildParams, + ISPCScene* ispc_scene, + RTCBuildQuality quality, + RTCBuildQuality qflags) { - std::cout << "sleeping..." << std::flush; - sleepSeconds(3); - std::cout << "done" << std::endl; - } +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + Benchmark_Static_Create_UserThreads_Legacy(ispc_scene, params, quality, qflags); + return; + } + + size_t primitives = getNumPrimitives(ispc_scene); + const size_t objects = getNumObjects(ispc_scene); + const size_t numThreads = g_num_user_threads; + Helper helper; + helper.barrier.init(numThreads); - /* called by the C++ code for initialization */ - extern "C" void device_init (char* cfg) - { - if (g_num_user_threads == 0) - { - /* set error handler */ - Benchmark_Dynamic_Update(g_ispc_scene,iterations_dynamic_dynamic,RTC_BUILD_QUALITY_REFIT); - Pause(); - Benchmark_Dynamic_Update(g_ispc_scene,iterations_dynamic_dynamic,RTC_BUILD_QUALITY_LOW); - Pause(); - Benchmark_Dynamic_Update(g_ispc_scene,iterations_dynamic_static ,RTC_BUILD_QUALITY_MEDIUM); - Pause(); - Benchmark_Dynamic_Create(g_ispc_scene,iterations_dynamic_dynamic,RTC_BUILD_QUALITY_REFIT); - Pause(); - Benchmark_Dynamic_Create(g_ispc_scene,iterations_dynamic_dynamic,RTC_BUILD_QUALITY_LOW); - Pause(); - Benchmark_Dynamic_Create(g_ispc_scene,iterations_dynamic_static ,RTC_BUILD_QUALITY_MEDIUM); - Pause(); - Benchmark_Static_Create(g_ispc_scene,iterations_static_static,RTC_BUILD_QUALITY_MEDIUM,RTC_BUILD_QUALITY_MEDIUM); - Pause(); - Benchmark_Static_Create(g_ispc_scene,iterations_static_static,RTC_BUILD_QUALITY_MEDIUM,RTC_BUILD_QUALITY_HIGH); + std::vector threads; + threads.reserve(numThreads); + + /* ramp up threads */ + setAffinity(0); + for (size_t i=1; iPauseTiming(); + + helper.scene = createScene(RTC_SCENE_FLAG_NONE,qflags); + convertScene(helper.scene,ispc_scene,quality); + + state.state->ResumeTiming(); + + helper.barrier.wait(); + rtcJoinCommitScene(helper.scene); + helper.barrier.wait(); + + state.state->PauseTiming(); + + rtcReleaseScene(helper.scene); + + state.state->ResumeTiming(); } + + /* terminate task loop */ + helper.term = true; + helper.barrier.wait(); + for (auto& thread: threads) + thread.join(); + + addCounter(state, primitives, objects); +#else + Benchmark_Static_Create_UserThreads_Legacy(ispc_scene, params, quality, qflags); +#endif } + extern "C" void device_init (char* cfg) + { + } void renderFrameStandard (int* pixels, const unsigned int width, diff --git a/tutorials/bvh_access/CMakeLists.txt b/tutorials/bvh_access/CMakeLists.txt index 62d627c9c5..4935c869a7 100644 --- a/tutorials/bvh_access/CMakeLists.txt +++ b/tutorials/bvh_access/CMakeLists.txt @@ -1,11 +1,12 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_EXECUTABLE(bvh_access ../../kernels/embree.rc bvh_access.cpp) -TARGET_LINK_LIBRARIES(bvh_access embree math sys tasking ${GLFW_LIBRARY}) +TARGET_LINK_LIBRARIES(bvh_access embree math sys tasking tutorial ${GLFW_LIBRARY}) + SET_PROPERTY(TARGET bvh_access PROPERTY FOLDER tutorials/single) SET_PROPERTY(TARGET bvh_access APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -INSTALL(TARGETS bvh_access DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) +INSTALL(TARGETS bvh_access DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) SIGN_TARGET(bvh_access) IF (BUILD_TESTING AND EMBREE_TESTING_INTENSITY GREATER 0) diff --git a/tutorials/bvh_access/bvh_access.cpp b/tutorials/bvh_access/bvh_access.cpp index 929aecdfdc..cf84e21d0c 100644 --- a/tutorials/bvh_access/bvh_access.cpp +++ b/tutorials/bvh_access/bvh_access.cpp @@ -1,10 +1,10 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" #include "../common/tutorial/tutorial_device.h" #include "../../include/embree3/rtcore.h" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE #include "../../kernels/bvh/bvh.h" #include "../../kernels/geometry/trianglev.h" @@ -233,6 +233,10 @@ namespace embree /* cleanup */ rtcReleaseScene (scene); rtcReleaseDevice(device); + + /* wait for user input under Windows when opened in separate window */ + waitForKeyPressedUnderWindows(); + return 0; } } diff --git a/tutorials/bvh_builder/CMakeLists.txt b/tutorials/bvh_builder/CMakeLists.txt index 484f5961ae..f57a04944c 100644 --- a/tutorials/bvh_builder/CMakeLists.txt +++ b/tutorials/bvh_builder/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(EMBREE_ISPC_SUPPORT OFF) diff --git a/tutorials/bvh_builder/bvh_builder.cpp b/tutorials/bvh_builder/bvh_builder.cpp index 700dd5377b..0d5198f1f0 100644 --- a/tutorials/bvh_builder/bvh_builder.cpp +++ b/tutorials/bvh_builder/bvh_builder.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" @@ -16,6 +16,12 @@ namespace embree } -int main(int argc, char** argv) { - return embree::Tutorial().main(argc,argv); +int main(int argc, char** argv) +{ + int code = embree::Tutorial().main(argc,argv); + + /* wait for user input under Windows when opened in separate window */ + embree::waitForKeyPressedUnderWindows(); + + return code; } diff --git a/tutorials/bvh_builder/bvh_builder_device.cpp b/tutorials/bvh_builder/bvh_builder_device.cpp index c782a76831..a35d698408 100644 --- a/tutorials/bvh_builder/bvh_builder_device.cpp +++ b/tutorials/bvh_builder/bvh_builder_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/closest_point/CMakeLists.txt b/tutorials/closest_point/CMakeLists.txt index 826409a7a5..a76c3fb2ea 100644 --- a/tutorials/closest_point/CMakeLists.txt +++ b/tutorials/closest_point/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/closest_point/closest_point.cpp b/tutorials/closest_point/closest_point.cpp index 0cc50fc2da..cc036d5b5f 100644 --- a/tutorials/closest_point/closest_point.cpp +++ b/tutorials/closest_point/closest_point.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/closest_point/closest_point_device.cpp b/tutorials/closest_point/closest_point_device.cpp index ebf444972b..499f989349 100644 --- a/tutorials/closest_point/closest_point_device.cpp +++ b/tutorials/closest_point/closest_point_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" @@ -47,7 +47,7 @@ Vec3f g_sphere_locations[2*g_num_point_queries] = { Vec3f( 5.50f, 0.50f, -6.50f), Vec3f(0.0f), Vec3f( 7.25f, -3.00f, -1.00f), Vec3f(0.0f), Vec3f(-0.25f, -0.50f, -4.25f), Vec3f(0.0f), -}; // consequtive pairs of (query point, closest point) +}; // consecutive pairs of (query point, closest point) RTCGeometry g_spheres = nullptr; RTCGeometry g_lines = nullptr; unsigned int g_spheres_geomID = 111111; @@ -154,7 +154,7 @@ inline void pushInstanceIdAndTransform(RTCPointQueryContext* context, { context->instID[context->instStackSize] = id; - // local copies of const references to fullfill alignment constraints + // local copies of const references to fulfill alignment constraints AffineSpace3fa w2i = w2i_in; AffineSpace3fa i2w = i2w_in; @@ -294,14 +294,14 @@ bool closestPointFunc(RTCPointQueryFunctionArguments* args) if (stackSize > 0 && args->similarityScale > 0) { // Instance transform is a similarity transform, therefore we - // can comute distance insformation in instance space. Therefore, + // can compute distance insformation in instance space. Therefore, // transform query position into local instance space. AffineSpace3fa const& m = (*(AffineSpace3fa*)context->world2inst[stackPtr]); q = xfmPoint(m, q); } else if (stackSize > 0) { - // Instance transform is not a similarity tranform. We have to transform the + // Instance transform is not a similarity transform. We have to transform the // primitive data into world space and perform distance computations in // world space to ensure correctness. v0 = xfmPoint(inst2world, v0); diff --git a/tutorials/closest_point/closest_point_device.ispc b/tutorials/closest_point/closest_point_device.ispc index 7e4e925d48..8fff30b504 100644 --- a/tutorials/closest_point/closest_point_device.ispc +++ b/tutorials/closest_point/closest_point_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" @@ -160,14 +160,14 @@ unmasked bool closestPointFunc(RTCPointQueryFunctionArguments* uniform args) if (stackSize > 0 && args->similarityScale > 0) { // Instance transform is a similarity transform, therefore we - // can comute distance insformation in instance space. Therefore, + // can compute distance insformation in instance space. Therefore, // transform query position into local instance space. uniform AffineSpace3f m = from_raw(context->world2inst[stackPtr]); q = xfmPoint(m, q); } else if (stackSize > 0) { - // Instance transform is not a similarity tranform. We have to transform the + // Instance transform is not a similarity transform. We have to transform the // primitive data into world space and perform distance computations in // world space to ensure correctness. v0 = xfmPoint(inst2world, v0); @@ -213,7 +213,7 @@ inline void pushInstanceIdAndTransform(uniform RTCPointQueryContext* uniform con { context->instID[context->instStackSize] = id; - // local copies of const references to fullfill alignment constraints + // local copies of const references to fulfill alignment constraints uniform AffineSpace3f w2i = w2i_in; uniform AffineSpace3f i2w = i2w_in; diff --git a/tutorials/collide/CMakeLists.txt b/tutorials/collide/CMakeLists.txt index d45751bee3..f48c208cfe 100644 --- a/tutorials/collide/CMakeLists.txt +++ b/tutorials/collide/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/collide/clothModel.h b/tutorials/collide/clothModel.h index 0d98054140..a99d9128be 100644 --- a/tutorials/collide/clothModel.h +++ b/tutorials/collide/clothModel.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/collide/collide.cpp b/tutorials/collide/collide.cpp index 0c575c6bdd..ae0664467b 100644 --- a/tutorials/collide/collide.cpp +++ b/tutorials/collide/collide.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" #include "../common/tutorial/statistics.h" #include #include "../../common/sys/mutex.h" @@ -188,5 +189,8 @@ void triangle_intersect_func(const RTCIntersectFunctionNArguments* args) } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "collide"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/collide/collide_device.cpp b/tutorials/collide/collide_device.cpp index e050575b26..70eb5fe380 100644 --- a/tutorials/collide/collide_device.cpp +++ b/tutorials/collide/collide_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.h" diff --git a/tutorials/collide/constraints.cpp b/tutorials/collide/constraints.cpp index 9f9ab7b06f..867f032a0f 100644 --- a/tutorials/collide/constraints.cpp +++ b/tutorials/collide/constraints.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "constraints.h" diff --git a/tutorials/collide/constraints.h b/tutorials/collide/constraints.h index c672a46420..9c27fe3dbc 100644 --- a/tutorials/collide/constraints.h +++ b/tutorials/collide/constraints.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/collide/pbd.h b/tutorials/collide/pbd.h index 4bdadfabc7..592ca0ae90 100644 --- a/tutorials/collide/pbd.h +++ b/tutorials/collide/pbd.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/CMakeLists.txt b/tutorials/common/CMakeLists.txt index 3655dea516..28e16eaf82 100644 --- a/tutorials/common/CMakeLists.txt +++ b/tutorials/common/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (EMBREE_TUTORIALS_GLFW) diff --git a/tutorials/common/common.isph b/tutorials/common/common.isph index 36e0c87b2d..678c4a1e35 100644 --- a/tutorials/common/common.isph +++ b/tutorials/common/common.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/core/differential_geometry.h b/tutorials/common/core/differential_geometry.h index 75e78278e8..1730a28f9c 100644 --- a/tutorials/common/core/differential_geometry.h +++ b/tutorials/common/core/differential_geometry.h @@ -1,15 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "../../../include/embree3/rtcore.h" #include "../math/vec.h" namespace embree { struct DifferentialGeometry { - unsigned int instID; + unsigned int instIDs[RTC_MAX_INSTANCE_LEVEL_COUNT]; unsigned int geomID; unsigned int primID; float u,v; diff --git a/tutorials/common/core/differential_geometry.isph b/tutorials/common/core/differential_geometry.isph index 0203c966f6..934288cb41 100644 --- a/tutorials/common/core/differential_geometry.isph +++ b/tutorials/common/core/differential_geometry.isph @@ -1,13 +1,14 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "../../../include/embree3/rtcore.isph" #include "../math/vec.isph" struct DifferentialGeometry { - unsigned int instID; + unsigned int instIDs[RTC_MAX_INSTANCE_LEVEL_COUNT]; unsigned int geomID; unsigned int primID; float u,v; diff --git a/tutorials/common/core/ray.h b/tutorials/common/core/ray.h index c9866b0b52..ffd70bd26d 100644 --- a/tutorials/common/core/ray.h +++ b/tutorials/common/core/ray.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/core/ray.isph b/tutorials/common/core/ray.isph index 858f3eaeea..c0a2e51568 100644 --- a/tutorials/common/core/ray.isph +++ b/tutorials/common/core/ray.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/default.h b/tutorials/common/default.h index d3f713ff15..ff26ce5396 100644 --- a/tutorials/common/default.h +++ b/tutorials/common/default.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/image/CMakeLists.txt b/tutorials/common/image/CMakeLists.txt index 752b79328f..68da888696 100644 --- a/tutorials/common/image/CMakeLists.txt +++ b/tutorials/common/image/CMakeLists.txt @@ -1,25 +1,25 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 -SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH}) +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" ${CMAKE_MODULE_PATH}) INCLUDE(CMakeDependentOption) SET(ADDITIONAL_SOURCES) -FIND_PACKAGE(OpenImageIO) -MARK_AS_ADVANCED( - OPENIMAGEIO_ROOT -) -CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_OPENIMAGEIO "Enables BMP, GIF, PNG, TGA, TIFF image codecs." OFF "EMBREE_TUTORIALS AND OPENIMAGEIO_FOUND" OFF) -IF (EMBREE_TUTORIALS_OPENIMAGEIO) - ADD_DEFINITIONS(-DUSE_OPENIMAGEIO) - INCLUDE_DIRECTORIES(${OPENIMAGEIO_INCLUDE_DIRS}) - SET(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} ${OPENIMAGEIO_LIBRARIES}) - SET(ADDITIONAL_SOURCES ${ADDITIONAL_SOURCES} oiio.cpp) -ENDIF (EMBREE_TUTORIALS_OPENIMAGEIO) +# FIND_PACKAGE(OpenImageIO) +# MARK_AS_ADVANCED( +# OPENIMAGEIO_ROOT +# ) +# CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_OPENIMAGEIO "Enables BMP, GIF, PNG, TGA, TIFF image codecs." OFF "EMBREE_TUTORIALS AND OPENIMAGEIO_FOUND" OFF) +# IF (EMBREE_TUTORIALS_OPENIMAGEIO) +# ADD_DEFINITIONS(-DUSE_OPENIMAGEIO) +# INCLUDE_DIRECTORIES(${OPENIMAGEIO_INCLUDE_DIRS}) +# SET(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} ${OPENIMAGEIO_LIBRARIES}) +# SET(ADDITIONAL_SOURCES ${ADDITIONAL_SOURCES} oiio.cpp) +# ENDIF (EMBREE_TUTORIALS_OPENIMAGEIO) FIND_PACKAGE(JPEG) -CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_LIBJPEG "Enables JPEG image codec." ON "EMBREE_TUTORIALS AND JPEG_FOUND" OFF) +CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_LIBJPEG "Enables JPEG image codec." OFF "EMBREE_TUTORIALS AND JPEG_FOUND" OFF) IF (EMBREE_TUTORIALS_LIBJPEG) ADD_DEFINITIONS(-DEMBREE_TUTORIALS_LIBJPEG) INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR}) @@ -28,7 +28,7 @@ IF (EMBREE_TUTORIALS_LIBJPEG) ENDIF (EMBREE_TUTORIALS_LIBJPEG) FIND_PACKAGE(PNG) -CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_LIBPNG "Enables PNG image codecs." ON "EMBREE_TUTORIALS AND PNG_FOUND" OFF) +CMAKE_DEPENDENT_OPTION(EMBREE_TUTORIALS_LIBPNG "Enables PNG image codecs." OFF "EMBREE_TUTORIALS AND PNG_FOUND" OFF) IF (EMBREE_TUTORIALS_LIBPNG) ADD_DEFINITIONS(-DEMBREE_TUTORIALS_LIBPNG) INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR}) diff --git a/tutorials/common/image/image.cpp b/tutorials/common/image/image.cpp index 992753a61a..b83f755ae5 100644 --- a/tutorials/common/image/image.cpp +++ b/tutorials/common/image/image.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "image.h" diff --git a/tutorials/common/image/image.h b/tutorials/common/image/image.h index a72cff131e..61e5292ca3 100644 --- a/tutorials/common/image/image.h +++ b/tutorials/common/image/image.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/image/jpeg.cpp b/tutorials/common/image/jpeg.cpp index d0bc9241ac..d879af4062 100644 --- a/tutorials/common/image/jpeg.cpp +++ b/tutorials/common/image/jpeg.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef EMBREE_TUTORIALS_LIBJPEG diff --git a/tutorials/common/image/oiio.cpp b/tutorials/common/image/oiio.cpp index b631b1810a..566df88b2e 100644 --- a/tutorials/common/image/oiio.cpp +++ b/tutorials/common/image/oiio.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef USE_OPENIMAGEIO @@ -15,7 +15,7 @@ namespace embree { Ref loadOIIO(const FileName& fileName) { - std::unique_ptr in = ImageInput::open(fileName.str().c_str()); + std::unique_ptr in(ImageInput::open(fileName.str().c_str())); if (!in) THROW_RUNTIME_ERROR("error opening file " + fileName.str()); @@ -46,7 +46,7 @@ namespace embree void storeOIIO(const Ref& img, const FileName& fileName) { - std::unique_ptr out = ImageOutput::create(fileName.c_str()); + std::unique_ptr out(ImageOutput::create(fileName.c_str())); if (!out) THROW_RUNTIME_ERROR("unsupported output file format " + fileName.str()); std::vector pixels(img->width*img->height*3); diff --git a/tutorials/common/image/pfm.cpp b/tutorials/common/image/pfm.cpp index 69a4c1cbb7..4033bcf01f 100644 --- a/tutorials/common/image/pfm.cpp +++ b/tutorials/common/image/pfm.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "image.h" diff --git a/tutorials/common/image/png.cpp b/tutorials/common/image/png.cpp index ef3211be83..f63b0d6dac 100644 --- a/tutorials/common/image/png.cpp +++ b/tutorials/common/image/png.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef EMBREE_TUTORIALS_LIBPNG diff --git a/tutorials/common/image/ppm.cpp b/tutorials/common/image/ppm.cpp index ce0c09fbf0..e580514bdf 100644 --- a/tutorials/common/image/ppm.cpp +++ b/tutorials/common/image/ppm.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "image.h" diff --git a/tutorials/common/image/tga.cpp b/tutorials/common/image/tga.cpp index e32574cd7d..345a6f9009 100644 --- a/tutorials/common/image/tga.cpp +++ b/tutorials/common/image/tga.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "image.h" diff --git a/tutorials/common/imgui/CMakeLists.txt b/tutorials/common/imgui/CMakeLists.txt index 29b46e5bea..323a6f4480 100644 --- a/tutorials/common/imgui/CMakeLists.txt +++ b/tutorials/common/imgui/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(imgui STATIC diff --git a/tutorials/common/imgui/README.md b/tutorials/common/imgui/README.md index b087c83486..a30e5cc3f2 100644 --- a/tutorials/common/imgui/README.md +++ b/tutorials/common/imgui/README.md @@ -249,7 +249,7 @@ See the FAQ in imgui.cpp for answers. You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad`). -You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC using Synergy 1.x. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). +You can share your computer mouse seamlessly with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the preferred solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC using Synergy 1.x. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). For touch inputs, you can increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimising for screen real-estate and precision. diff --git a/tutorials/common/imgui/imgui.cpp b/tutorials/common/imgui/imgui.cpp index dff5391aba..99e4fecf97 100644 --- a/tutorials/common/imgui/imgui.cpp +++ b/tutorials/common/imgui/imgui.cpp @@ -124,7 +124,7 @@ - Call ImGui::NewFrame() to begin the frame - You can use any ImGui function you want between NewFrame() and Render() - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler. - (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwhise some features will break) + (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwise some features will break) - All rendering information are stored into command-lists until ImGui::Render() is called. - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases @@ -272,7 +272,7 @@ - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. - - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. + - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. @@ -433,7 +433,7 @@ perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to NewFrameUpdateHoveredWindowAndCaptureFlags(). Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs - were targetted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) + were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) Q: How can I display an image? What is ImTextureID, how does it works? A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. @@ -775,7 +775,7 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); // Context //----------------------------------------------------------------------------- -// Current context pointer. Implicitely used by all ImGui functions. Always assumed to be != NULL. +// Current context pointer. Implicitly used by all ImGui functions. Always assumed to be != NULL. // CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext(). // If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file. // ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can: @@ -2494,7 +2494,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) if (window->DC.ItemFlags & ImGuiItemFlags_Disabled) return false; - // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case. + // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect that case. if (window->DC.LastItemId == window->MoveId && window->WriteAccessed) return false; return true; @@ -5457,7 +5457,7 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents) ImVec2 size_auto_fit; if ((flags & ImGuiWindowFlags_Tooltip) != 0) { - // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose. + // Tooltip always resize. We keep the spacing symmetric on both axes for aesthetic purpose. size_auto_fit = size_contents; } else @@ -8001,7 +8001,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) if (flags & ImGuiTreeNodeFlags_Leaf) return true; - // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) + // We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiStorage* storage = window->DC.StateStorage; @@ -11427,7 +11427,7 @@ static inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b) } // NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. -// I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether. +// I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether. void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/tutorials/common/imgui/imgui.h b/tutorials/common/imgui/imgui.h index 088d3bdb05..cdc6f9a53a 100644 --- a/tutorials/common/imgui/imgui.h +++ b/tutorials/common/imgui/imgui.h @@ -231,7 +231,7 @@ namespace ImGui IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); IMGUI_API void PopStyleVar(int count = 1); - IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwhise use GetColorU32() to get style color with style alpha baked in. + IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in. IMGUI_API ImFont* GetFont(); // get current font IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API @@ -556,7 +556,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window - ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically) + ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically) ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set. ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame @@ -566,7 +566,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state - ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) + ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programmatically giving it focus) ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) @@ -1209,7 +1209,7 @@ class ImVector // Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. struct ImNewDummy {}; inline void* operator new(size_t, ImNewDummy, void* ptr) { return ptr; } -inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symetrical new() +inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symmetrical new() #define IM_PLACEMENT_NEW(_PTR) new(ImNewDummy(), _PTR) #define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE template void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } } @@ -1405,7 +1405,7 @@ struct ImGuiPayload #define IM_COL32_BLACK IM_COL32(0,0,0,255) // Opaque black #define IM_COL32_BLACK_TRANS IM_COL32(0,0,0,0) // Transparent black = 0x00000000 -// Helper: ImColor() implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) +// Helper: ImColor() implicitly converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) // Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API. // **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. MAY OBSOLETE. // **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed. diff --git a/tutorials/common/imgui/imgui_draw.cpp b/tutorials/common/imgui/imgui_draw.cpp index e1a0e878be..b9d66552b6 100644 --- a/tutorials/common/imgui/imgui_draw.cpp +++ b/tutorials/common/imgui/imgui_draw.cpp @@ -692,7 +692,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 idx1 = idx2; } - // Add vertexes + // Add vertices for (int i = 0; i < points_count; i++) { _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; @@ -751,7 +751,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 idx1 = idx2; } - // Add vertexes + // Add vertices for (int i = 0; i < points_count; i++) { _VtxWritePtr[0].pos = temp_points[i*4+0]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col_trans; diff --git a/tutorials/common/imgui/imgui_internal.h b/tutorials/common/imgui/imgui_internal.h index 9892e7cb17..355c1570ba 100644 --- a/tutorials/common/imgui/imgui_internal.h +++ b/tutorials/common/imgui/imgui_internal.h @@ -430,7 +430,7 @@ struct ImGuiPopupRef ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* ParentWindow; // Set on OpenPopup() int OpenFrameCount; // Set on OpenPopup() - ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) + ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup }; diff --git a/tutorials/common/imgui/stb_rect_pack.h b/tutorials/common/imgui/stb_rect_pack.h index 2b07dcc82c..3906cd8a30 100644 --- a/tutorials/common/imgui/stb_rect_pack.h +++ b/tutorials/common/imgui/stb_rect_pack.h @@ -309,7 +309,7 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0 if (node->y > min_y) { // raise min_y higher. // we've accounted for all waste up to min_y, - // but we'll now add more waste for everything we've visted + // but we'll now add more waste for everything we've visited waste_area += visited_width * (node->y - min_y); min_y = node->y; // the first time through, visited_width might be reduced diff --git a/tutorials/common/imgui/stb_textedit.h b/tutorials/common/imgui/stb_textedit.h index 7324fb6b4a..1840495004 100644 --- a/tutorials/common/imgui/stb_textedit.h +++ b/tutorials/common/imgui/stb_textedit.h @@ -669,7 +669,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) { if (STB_TEXT_HAS_SELECTION(state)) { - stb_textedit_delete_selection(str,state); // implicity clamps + stb_textedit_delete_selection(str,state); // implicitly clamps state->has_preferred_x = 0; return 1; } @@ -717,7 +717,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, state->has_preferred_x = 0; } } else { - stb_textedit_delete_selection(str,state); // implicity clamps + stb_textedit_delete_selection(str,state); // implicitly clamps if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { stb_text_makeundo_insert(state, state->cursor, 1); ++state->cursor; diff --git a/tutorials/common/imgui/stb_truetype.h b/tutorials/common/imgui/stb_truetype.h index f65deb5034..f92d7d7f17 100644 --- a/tutorials/common/imgui/stb_truetype.h +++ b/tutorials/common/imgui/stb_truetype.h @@ -75,7 +75,7 @@ // // USAGE // -// Include this file in whatever places neeed to refer to it. In ONE C/C++ +// Include this file in whatever places need to refer to it. In ONE C/C++ // file, write: // #define STB_TRUETYPE_IMPLEMENTATION // before the #include of this file. This expands out the actual @@ -247,11 +247,11 @@ // Documentation & header file 520 LOC \___ 660 LOC documentation // Sample code 140 LOC / // Truetype parsing 620 LOC ---- 620 LOC TrueType -// Software rasterization 240 LOC \ . -// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation +// Software rasterization 240 LOC \ +// Curve tessellation 120 LOC \__ 550 LOC Bitmap creation // Bitmap management 100 LOC / // Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 +// Font name matching & access 150 LOC ---- 150 // C runtime library abstraction 60 LOC ---- 60 // // @@ -694,7 +694,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // file will only define one font and it always be at offset 0, so it will // return '0' for index 0, and -1 for all other indices. -// The following structure is defined publically so you can declare one on +// The following structure is defined publicly so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. struct stbtt_fontinfo { @@ -820,7 +820,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s // returns # of vertices and fills *vertices with the pointer to them // these are expressed in "unscaled" coordinates // -// The shape is a series of countours. Each one starts with +// The shape is a series of contours. Each one starts with // a STBTT_moveto, then consists of a series of mixed // STBTT_lineto and STBTT_curveto segments. A lineto // draws a line from previous endpoint to its x,y; a curveto @@ -916,7 +916,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); // These functions compute a discretized SDF field for a single character, suitable for storing // in a single-channel texture, sampling with bilinear filtering, and testing against -// larger than some threshhold to produce scalable fonts. +// larger than some threshold to produce scalable fonts. // info -- the font // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap // glyph/codepoint -- the character to generate the SDF for @@ -3230,7 +3230,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) { - /* threshhold for transitioning to insertion sort */ + /* threshold for transitioning to insertion sort */ while (n > 12) { stbtt__edge t; int c01,c12,c,m,i,j; @@ -3365,7 +3365,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y) points[n].y = y; } -// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) { // midpoint diff --git a/tutorials/common/lights/CMakeLists.txt b/tutorials/common/lights/CMakeLists.txt index 08b6419cbc..e20d0c1c45 100644 --- a/tutorials/common/lights/CMakeLists.txt +++ b/tutorials/common/lights/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(lights STATIC diff --git a/tutorials/common/lights/ambient_light.cpp b/tutorials/common/lights/ambient_light.cpp index 9034d9fc45..7651b6bf33 100644 --- a/tutorials/common/lights/ambient_light.cpp +++ b/tutorials/common/lights/ambient_light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.h" diff --git a/tutorials/common/lights/ambient_light.h b/tutorials/common/lights/ambient_light.h index 29755e5061..42b5afaf97 100644 --- a/tutorials/common/lights/ambient_light.h +++ b/tutorials/common/lights/ambient_light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/ambient_light.ispc b/tutorials/common/lights/ambient_light.ispc index b8fb8179b7..4a3cfec88d 100644 --- a/tutorials/common/lights/ambient_light.ispc +++ b/tutorials/common/lights/ambient_light.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.isph" diff --git a/tutorials/common/lights/directional_light.cpp b/tutorials/common/lights/directional_light.cpp index 97bd79bf20..ec013bc59f 100644 --- a/tutorials/common/lights/directional_light.cpp +++ b/tutorials/common/lights/directional_light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.h" diff --git a/tutorials/common/lights/directional_light.h b/tutorials/common/lights/directional_light.h index 641e8d0e05..c2ae4e7fd8 100644 --- a/tutorials/common/lights/directional_light.h +++ b/tutorials/common/lights/directional_light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/directional_light.ispc b/tutorials/common/lights/directional_light.ispc index 9f1d8ba9fa..d446b72d28 100644 --- a/tutorials/common/lights/directional_light.ispc +++ b/tutorials/common/lights/directional_light.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.isph" diff --git a/tutorials/common/lights/light.cpp b/tutorials/common/lights/light.cpp index 0cf4757cf0..a64bfa2da0 100644 --- a/tutorials/common/lights/light.cpp +++ b/tutorials/common/lights/light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.h" diff --git a/tutorials/common/lights/light.h b/tutorials/common/lights/light.h index 91ecb00e94..6fe169a8fb 100644 --- a/tutorials/common/lights/light.h +++ b/tutorials/common/lights/light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/light.ispc b/tutorials/common/lights/light.ispc index 253f93d451..97ddb38198 100644 --- a/tutorials/common/lights/light.ispc +++ b/tutorials/common/lights/light.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.isph" diff --git a/tutorials/common/lights/light.isph b/tutorials/common/lights/light.isph index d54cb22813..cacd77c594 100644 --- a/tutorials/common/lights/light.isph +++ b/tutorials/common/lights/light.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/point_light.cpp b/tutorials/common/lights/point_light.cpp index b89c64868d..7b93173a01 100644 --- a/tutorials/common/lights/point_light.cpp +++ b/tutorials/common/lights/point_light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.h" diff --git a/tutorials/common/lights/point_light.h b/tutorials/common/lights/point_light.h index 35231e8987..7f464c288b 100644 --- a/tutorials/common/lights/point_light.h +++ b/tutorials/common/lights/point_light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/point_light.ispc b/tutorials/common/lights/point_light.ispc index 66e7dfdbc1..5079d5b9f0 100644 --- a/tutorials/common/lights/point_light.ispc +++ b/tutorials/common/lights/point_light.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.isph" diff --git a/tutorials/common/lights/quad_light.cpp b/tutorials/common/lights/quad_light.cpp index 4711449bf5..714dfebe67 100644 --- a/tutorials/common/lights/quad_light.cpp +++ b/tutorials/common/lights/quad_light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.h" diff --git a/tutorials/common/lights/quad_light.h b/tutorials/common/lights/quad_light.h index 9a5006bc73..68633a20f2 100644 --- a/tutorials/common/lights/quad_light.h +++ b/tutorials/common/lights/quad_light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/quad_light.ispc b/tutorials/common/lights/quad_light.ispc index b8ab5dcf53..6c4f94581b 100644 --- a/tutorials/common/lights/quad_light.ispc +++ b/tutorials/common/lights/quad_light.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.isph" diff --git a/tutorials/common/lights/spot_light.cpp b/tutorials/common/lights/spot_light.cpp index 7e274ff903..90bf033d3f 100644 --- a/tutorials/common/lights/spot_light.cpp +++ b/tutorials/common/lights/spot_light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.h" diff --git a/tutorials/common/lights/spot_light.h b/tutorials/common/lights/spot_light.h index 6c616f0ad2..0027b2e902 100644 --- a/tutorials/common/lights/spot_light.h +++ b/tutorials/common/lights/spot_light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/lights/spot_light.ispc b/tutorials/common/lights/spot_light.ispc index 1045bf54b6..ee6eed98b7 100644 --- a/tutorials/common/lights/spot_light.ispc +++ b/tutorials/common/lights/spot_light.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "light.isph" diff --git a/tutorials/common/math/affinespace.h b/tutorials/common/math/affinespace.h index a29c18ee49..e06d597d73 100644 --- a/tutorials/common/math/affinespace.h +++ b/tutorials/common/math/affinespace.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/affinespace.isph b/tutorials/common/math/affinespace.isph index bbae566149..9b40d0cc4a 100644 --- a/tutorials/common/math/affinespace.isph +++ b/tutorials/common/math/affinespace.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/closest_point.h b/tutorials/common/math/closest_point.h index 76efaab1b5..2046c0197f 100644 --- a/tutorials/common/math/closest_point.h +++ b/tutorials/common/math/closest_point.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/closest_point.isph b/tutorials/common/math/closest_point.isph index 01aa5faae3..a09b266b25 100644 --- a/tutorials/common/math/closest_point.isph +++ b/tutorials/common/math/closest_point.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/linearspace.h b/tutorials/common/math/linearspace.h index 1646f17125..6b237fa78b 100644 --- a/tutorials/common/math/linearspace.h +++ b/tutorials/common/math/linearspace.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/linearspace.isph b/tutorials/common/math/linearspace.isph index b02740bf55..e933d8783a 100644 --- a/tutorials/common/math/linearspace.isph +++ b/tutorials/common/math/linearspace.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/math.h b/tutorials/common/math/math.h index 0d27f93698..04439e4c1b 100644 --- a/tutorials/common/math/math.h +++ b/tutorials/common/math/math.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/math.isph b/tutorials/common/math/math.isph index 85414b7929..09f62c3c28 100644 --- a/tutorials/common/math/math.isph +++ b/tutorials/common/math/math.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/quaternion.h b/tutorials/common/math/quaternion.h index ff518b744b..9bea383966 100644 --- a/tutorials/common/math/quaternion.h +++ b/tutorials/common/math/quaternion.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/quaternion.isph b/tutorials/common/math/quaternion.isph index 07f296e971..6021f79e45 100644 --- a/tutorials/common/math/quaternion.isph +++ b/tutorials/common/math/quaternion.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/random_sampler.h b/tutorials/common/math/random_sampler.h index fd5bc327b8..0f472d9898 100644 --- a/tutorials/common/math/random_sampler.h +++ b/tutorials/common/math/random_sampler.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/random_sampler.isph b/tutorials/common/math/random_sampler.isph index 5103ccd58d..38b4c0326d 100644 --- a/tutorials/common/math/random_sampler.isph +++ b/tutorials/common/math/random_sampler.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/sampling.h b/tutorials/common/math/sampling.h index 2e6a7080e1..378e023d23 100644 --- a/tutorials/common/math/sampling.h +++ b/tutorials/common/math/sampling.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/sampling.isph b/tutorials/common/math/sampling.isph index 8f9ed8dc1b..2a0931852d 100644 --- a/tutorials/common/math/sampling.isph +++ b/tutorials/common/math/sampling.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/vec.h b/tutorials/common/math/vec.h index a4b11a5721..bbe911aa78 100644 --- a/tutorials/common/math/vec.h +++ b/tutorials/common/math/vec.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/math/vec.isph b/tutorials/common/math/vec.isph index 42dbd907ca..31b0ed1fe3 100644 --- a/tutorials/common/math/vec.isph +++ b/tutorials/common/math/vec.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/CMakeLists.txt b/tutorials/common/scenegraph/CMakeLists.txt index 29d5c93239..adda0d90cf 100644 --- a/tutorials/common/scenegraph/CMakeLists.txt +++ b/tutorials/common/scenegraph/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(scenegraph STATIC diff --git a/tutorials/common/scenegraph/corona_loader.cpp b/tutorials/common/scenegraph/corona_loader.cpp index a39b9c94d9..03286b9187 100644 --- a/tutorials/common/scenegraph/corona_loader.cpp +++ b/tutorials/common/scenegraph/corona_loader.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "corona_loader.h" diff --git a/tutorials/common/scenegraph/corona_loader.h b/tutorials/common/scenegraph/corona_loader.h index 23ac3020ad..493eea103f 100644 --- a/tutorials/common/scenegraph/corona_loader.h +++ b/tutorials/common/scenegraph/corona_loader.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/geometry_creation.cpp b/tutorials/common/scenegraph/geometry_creation.cpp index 5fb9706dcf..0a41c7758f 100644 --- a/tutorials/common/scenegraph/geometry_creation.cpp +++ b/tutorials/common/scenegraph/geometry_creation.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry_creation.h" diff --git a/tutorials/common/scenegraph/geometry_creation.h b/tutorials/common/scenegraph/geometry_creation.h index d295f4582c..f7f1d59e37 100644 --- a/tutorials/common/scenegraph/geometry_creation.h +++ b/tutorials/common/scenegraph/geometry_creation.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/lights.h b/tutorials/common/scenegraph/lights.h index 9830eee9da..16ff73a6dc 100644 --- a/tutorials/common/scenegraph/lights.h +++ b/tutorials/common/scenegraph/lights.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -20,7 +20,7 @@ namespace embree LIGHT_QUAD, }; - class Light : public RefCount + class Light { ALIGNED_CLASS_(16) @@ -28,7 +28,6 @@ namespace embree Light(LightType type) : type(type) {} LightType getType() const { return type; } - virtual Ref transform(const AffineSpace3fa& space) const = 0; private: LightType type; @@ -40,8 +39,12 @@ namespace embree AmbientLight (const Vec3fa& L) : Light(LIGHT_AMBIENT), L(L) {} - Ref transform(const AffineSpace3fa& space) const { - return new AmbientLight(L); + AmbientLight transform(const AffineSpace3fa& space) const { + return AmbientLight(L); + } + + static AmbientLight lerp(const AmbientLight& light0, const AmbientLight& light1, const float f) { + return AmbientLight(embree::lerp(light0.L,light1.L,f)); } public: @@ -54,8 +57,14 @@ namespace embree PointLight (const Vec3fa& P, const Vec3fa& I) : Light(LIGHT_POINT), P(P), I(I) {} - Ref transform(const AffineSpace3fa& space) const { - return new PointLight(xfmPoint(space,P),I); + PointLight transform(const AffineSpace3fa& space) const { + return PointLight(xfmPoint(space,P),I); + } + + static PointLight lerp(const PointLight& light0, const PointLight& light1, const float f) + { + return PointLight(embree::lerp(light0.P,light1.P,f), + embree::lerp(light0.I,light1.I,f)); } public: @@ -69,8 +78,14 @@ namespace embree DirectionalLight (const Vec3fa& D, const Vec3fa& E) : Light(LIGHT_DIRECTIONAL), D(D), E(E) {} - Ref transform(const AffineSpace3fa& space) const { - return new DirectionalLight(xfmVector(space,D),E); + DirectionalLight transform(const AffineSpace3fa& space) const { + return DirectionalLight(xfmVector(space,D),E); + } + + static DirectionalLight lerp(const DirectionalLight& light0, const DirectionalLight& light1, const float f) + { + return DirectionalLight(embree::lerp(light0.D,light1.D,f), + embree::lerp(light0.E,light1.E,f)); } public: @@ -84,8 +99,17 @@ namespace embree SpotLight (const Vec3fa& P, const Vec3fa& D, const Vec3fa& I, float angleMin, float angleMax) : Light(LIGHT_SPOT), P(P), D(D), I(I), angleMin(angleMin), angleMax(angleMax) {} - Ref transform(const AffineSpace3fa& space) const { - return new SpotLight(xfmPoint(space,P),xfmVector(space,D),I,angleMin,angleMax); + SpotLight transform(const AffineSpace3fa& space) const { + return SpotLight(xfmPoint(space,P),xfmVector(space,D),I,angleMin,angleMax); + } + + static SpotLight lerp(const SpotLight& light0, const SpotLight& light1, const float f) + { + return SpotLight(embree::lerp(light0.P,light1.P,f), + embree::lerp(light0.D,light1.D,f), + embree::lerp(light0.I,light1.I,f), + embree::lerp(light0.angleMin,light1.angleMin,f), + embree::lerp(light0.angleMax,light1.angleMax,f)); } public: @@ -101,8 +125,15 @@ namespace embree DistantLight (const Vec3fa& D, const Vec3fa& L, const float halfAngle) : Light(LIGHT_DISTANT), D(D), L(L), halfAngle(halfAngle), radHalfAngle(deg2rad(halfAngle)), cosHalfAngle(cos(deg2rad(halfAngle))) {} - Ref transform(const AffineSpace3fa& space) const { - return new DistantLight(xfmVector(space,D),L,halfAngle); + DistantLight transform(const AffineSpace3fa& space) const { + return DistantLight(xfmVector(space,D),L,halfAngle); + } + + static DistantLight lerp(const DistantLight& light0, const DistantLight& light1, const float f) + { + return DistantLight(embree::lerp(light0.D,light1.D,f), + embree::lerp(light0.L,light1.L,f), + embree::lerp(light0.halfAngle,light1.halfAngle,f)); } public: @@ -119,8 +150,16 @@ namespace embree TriangleLight (const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& L) : Light(LIGHT_TRIANGLE), v0(v0), v1(v1), v2(v2), L(L) {} - Ref transform(const AffineSpace3fa& space) const { - return new TriangleLight(xfmPoint(space,v0),xfmPoint(space,v1),xfmPoint(space,v2),L); + TriangleLight transform(const AffineSpace3fa& space) const { + return TriangleLight(xfmPoint(space,v0),xfmPoint(space,v1),xfmPoint(space,v2),L); + } + + static TriangleLight lerp(const TriangleLight& light0, const TriangleLight& light1, const float f) + { + return TriangleLight(embree::lerp(light0.v0,light1.v0,f), + embree::lerp(light0.v1,light1.v1,f), + embree::lerp(light0.v2,light1.v2,f), + embree::lerp(light0.L,light1.L,f)); } public: @@ -136,8 +175,17 @@ namespace embree QuadLight (const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& v3, const Vec3fa& L) : Light(LIGHT_QUAD), v0(v0), v1(v1), v2(v2), v3(v3), L(L) {} - Ref transform(const AffineSpace3fa& space) const { - return new QuadLight(xfmPoint(space,v0),xfmPoint(space,v1),xfmPoint(space,v2),xfmPoint(space,v3),L); + QuadLight transform(const AffineSpace3fa& space) const { + return QuadLight(xfmPoint(space,v0),xfmPoint(space,v1),xfmPoint(space,v2),xfmPoint(space,v3),L); + } + + static QuadLight lerp(const QuadLight& light0, const QuadLight& light1, const float f) + { + return QuadLight(embree::lerp(light0.v0,light1.v0,f), + embree::lerp(light0.v1,light1.v1,f), + embree::lerp(light0.v2,light1.v2,f), + embree::lerp(light0.v3,light1.v3,f), + embree::lerp(light0.L,light1.L,f)); } public: diff --git a/tutorials/common/scenegraph/materials.h b/tutorials/common/scenegraph/materials.h index 32c9f9e683..f528784d2d 100644 --- a/tutorials/common/scenegraph/materials.h +++ b/tutorials/common/scenegraph/materials.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #if defined (CPPTUTORIAL) && !defined(_MATERIALS_H_CPPTUTORIAL) || !defined(_MATERIALS_H_) diff --git a/tutorials/common/scenegraph/obj_loader.cpp b/tutorials/common/scenegraph/obj_loader.cpp index 502589de52..a84c2f7862 100644 --- a/tutorials/common/scenegraph/obj_loader.cpp +++ b/tutorials/common/scenegraph/obj_loader.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "obj_loader.h" @@ -459,7 +459,7 @@ namespace embree unsigned int OBJLoader::fix_vt(int index) { return (index > 0 ? index - 1 : (index == 0 ? 0 : (int) vt.size() + index)); } unsigned int OBJLoader::fix_vn(int index) { return (index > 0 ? index - 1 : (index == 0 ? 0 : (int) vn.size() + index)); } - /*! Parse differently formated triplets like: n0, n0/n1/n2, n0//n2, n0/n1. */ + /*! Parse differently formatted triplets like: n0, n0/n1/n2, n0//n2, n0/n1. */ /*! All indices are converted to C-style (from 0). Missing entries are assigned -1. */ Vertex OBJLoader::getUInt3(const char*& token) { diff --git a/tutorials/common/scenegraph/obj_loader.h b/tutorials/common/scenegraph/obj_loader.h index f2aff1f0df..a4157798f5 100644 --- a/tutorials/common/scenegraph/obj_loader.h +++ b/tutorials/common/scenegraph/obj_loader.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/ply_loader.cpp b/tutorials/common/scenegraph/ply_loader.cpp index e3703dff58..be31c81140 100644 --- a/tutorials/common/scenegraph/ply_loader.cpp +++ b/tutorials/common/scenegraph/ply_loader.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ply_loader.h" diff --git a/tutorials/common/scenegraph/ply_loader.h b/tutorials/common/scenegraph/ply_loader.h index 337b72d102..12f7578549 100644 --- a/tutorials/common/scenegraph/ply_loader.h +++ b/tutorials/common/scenegraph/ply_loader.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/scenegraph.cpp b/tutorials/common/scenegraph/scenegraph.cpp index 5fcabff879..5de1647f45 100644 --- a/tutorials/common/scenegraph/scenegraph.cpp +++ b/tutorials/common/scenegraph/scenegraph.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scenegraph.h" @@ -11,6 +11,8 @@ namespace embree { extern "C" RTCDevice g_device; + + void (*SceneGraph::opaque_geometry_destruction)(void*) = nullptr; Ref SceneGraph::load(const FileName& filename, const bool singleObject) { @@ -21,10 +23,10 @@ namespace embree else throw std::runtime_error("unknown scene format: " + filename.ext()); } - void SceneGraph::store(Ref root, const FileName& filename, bool embedTextures, bool referenceMaterials) + void SceneGraph::store(Ref root, const FileName& filename, bool embedTextures, bool referenceMaterials, bool binaryFormat) { if (toLowerCase(filename.ext()) == std::string("xml")) { - storeXML(root,filename,embedTextures,referenceMaterials); + storeXML(root,filename,embedTextures,referenceMaterials,binaryFormat); } else throw std::runtime_error("unknown scene format: " + filename.ext()); @@ -35,12 +37,31 @@ namespace embree } void SceneGraph::PerspectiveCameraNode::print(std::ostream& cout, int depth) { - cout << "PerspectiveCameraNode { closed = " << closed << " }" << std::endl; + cout << "PerspectiveCameraNode @ " << this << " { " << std::endl; + if (name != "") { + tab(cout, depth+1); cout << "name = " << name << std::endl; + } + tab(cout, depth+1); cout << "from = " << data.from << std::endl; + tab(cout, depth+1); cout << "to = " << data.to << std::endl; + tab(cout, depth+1); cout << "up = " << data.up << std::endl; + tab(cout, depth+1); cout << "fov = " << data.fov << std::endl; + tab(cout, depth); cout << "}" << std::endl; + } + + void SceneGraph::AnimatedPerspectiveCameraNode::print(std::ostream& cout, int depth) { + cout << "AnimatedPerspectiveCameraNode @ " << this << " { " << std::endl; + if (name != "") { + tab(cout, depth+1); cout << "name = " << name << std::endl; + } + for (size_t i=0; iprint(cout,depth+1); + } + tab(cout, depth); cout << "}" << std::endl; } void SceneGraph::TransformNode::print(std::ostream& cout, int depth) { - cout << "TransformNode { " << std::endl; + cout << "TransformNode @ " << this << " { " << std::endl; tab(cout, depth+1); cout << "closed = " << closed << std::endl; tab(cout, depth+1); cout << "numTimeSteps = " << spaces.size() << std::endl; tab(cout, depth+1); cout << "child = "; child->print(cout,depth+1); @@ -49,7 +70,7 @@ namespace embree void SceneGraph::GroupNode::print(std::ostream& cout, int depth) { - cout << "GroupNode { " << std::endl; + cout << "GroupNode @ " << this << " { " << std::endl; tab(cout, depth+1); cout << "closed = " << closed << std::endl; for (size_t i=0; i mesh = node.dynamicCast()) { mesh->time_range = time_range; } + else if (Ref mesh = node.dynamicCast()) { + mesh->time_range = time_range; + } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } @@ -1746,14 +1785,15 @@ namespace embree SceneGraphFlattener (Ref in, SceneGraph::InstancingMode instancing) { - in->calculateInDegree(); - in->calculateClosed(instancing == SceneGraph::INSTANCING_GROUP); + in->calculateInDegree(); + in->calculateClosed(instancing == SceneGraph::INSTANCING_GROUP); std::vector> geometries; if (instancing != SceneGraph::INSTANCING_NONE) { - if (instancing == SceneGraph::INSTANCING_FLATTENED) convertFlattenedInstances(geometries,in); - else convertInstances(geometries,in,one); + if (instancing == SceneGraph::INSTANCING_FLATTENED ) convertFlattenedInstances(geometries,in); + else if (instancing == SceneGraph::INSTANCING_MULTI_LEVEL) convertMultiLevelInstances(geometries,in); + else convertInstances(geometries,in,one); convertLightsAndCameras(geometries,in,one); } else @@ -1790,11 +1830,40 @@ namespace embree else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertLightsAndCameras(group,child,spaces); } - else if (Ref lightNode = node.dynamicCast()) { - group.push_back(new SceneGraph::LightNode(lightNode->light->transform(spaces[0]))); + else if (Ref lightNode = node.dynamicCast()) { + if (spaces.size() != 1) throw std::runtime_error("animated lights cannot get instantiated with a transform animation"); + group.push_back(lightNode->transform(spaces[0]).dynamicCast()); } - else if (Ref cameraNode = node.dynamicCast()) { - group.push_back(new SceneGraph::PerspectiveCameraNode(cameraNode,spaces[0],makeUniqueID(cameraNode->name))); + else if (Ref lightNode = node.dynamicCast()) + { + if (spaces.size() == 1) + group.push_back(lightNode->transform(spaces[0]).dynamicCast()); + else + { + std::vector> lights(spaces.size()); + for (size_t i=0; itransform(spaces[i]); + + group.push_back(new SceneGraph::AnimatedLightNode(std::move(lights),spaces.time_range)); + } + } + else if (Ref cameraNode = node.dynamicCast()) + { + if (spaces.size() != 1) throw std::runtime_error("animated cameras cannot get instantiated with a transform animation"); + group.push_back(new SceneGraph::AnimatedPerspectiveCameraNode(cameraNode,spaces[0],makeUniqueID(cameraNode->name))); + } + else if (Ref cameraNode = node.dynamicCast()) + { + if (spaces.size() == 1) + group.push_back(new SceneGraph::PerspectiveCameraNode(cameraNode,spaces[0],makeUniqueID(cameraNode->name))); + else + { + std::vector> cameras(spaces.size()); + for (size_t i=0; iname))); + } } } @@ -1852,6 +1921,53 @@ namespace embree } } + void convertMultiLevelInstances(std::vector>& group, const Ref& node) + { + if (Ref groupNode = node.dynamicCast()) { + for (const auto& child : groupNode->children) convertMultiLevelInstances(group,child); + } + else if (node.dynamicCast()) { + group.push_back(node); + } + else if (node.dynamicCast()) { + group.push_back(node); + } + else if (node.dynamicCast()) { + group.push_back(node); + } + else if (node.dynamicCast()) { + group.push_back(node); + } + else if (node.dynamicCast()) { + group.push_back(node); + } + else if (node.dynamicCast()) { + group.push_back(node); + } + else if (object_mapping.find(node) != object_mapping.end()) { + group.push_back(object_mapping[node]); + } + else if (Ref xfmNode = node.dynamicCast()) + { + auto new_node = new SceneGraph::TransformNode(xfmNode->spaces,convertMultiLevelInstances(xfmNode->child)); + object_mapping[node] = new_node; + group.push_back(new_node); + } + } + + Ref convertMultiLevelInstances(const Ref& node) + { + if (object_mapping.find(node) != object_mapping.end()) { + return object_mapping[node]; + } + + std::vector> group; + convertMultiLevelInstances(group,node); + auto new_node = new SceneGraph::GroupNode(group); + object_mapping[node] = new_node; + return new_node; + } + void convertFlattenedInstances(std::vector>& group, const Ref& node) { if (Ref xfmNode = node.dynamicCast()) { diff --git a/tutorials/common/scenegraph/scenegraph.h b/tutorials/common/scenegraph/scenegraph.h index 7bbfd50736..c6e6aeb49a 100644 --- a/tutorials/common/scenegraph/scenegraph.h +++ b/tutorials/common/scenegraph/scenegraph.h @@ -1,11 +1,11 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "lights.h" #include "../../../include/embree3/rtcore.h" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE #include "../math/random_sampler.h" namespace embree @@ -22,7 +22,7 @@ namespace embree struct GridMeshNode; Ref load(const FileName& fname, bool singleObject = false); - void store(Ref root, const FileName& fname, bool embedTextures, bool referenceMaterials); + void store(Ref root, const FileName& fname, bool embedTextures, bool referenceMaterials, bool binaryFormat); void extend_animation(Ref node0, Ref node1); void optimize_animation(Ref node0); void set_motion_vector(Ref node, const Vec3fa& dP); @@ -47,6 +47,8 @@ namespace embree Ref remove_mblur(Ref node, bool mblur); void convert_mblur_to_nonmblur(Ref node); + extern void (*opaque_geometry_destruction)(void*); + struct Statistics { Statistics () @@ -104,6 +106,11 @@ namespace embree Node (const std::string& name) : name(name), indegree(0), closed(false), id(-1), geometry(nullptr) {} + ~Node() { + if (opaque_geometry_destruction) + opaque_geometry_destruction(geometry); + } + /* prints scenegraph */ virtual void print(std::ostream& cout, int depth = 0) = 0; @@ -528,26 +535,100 @@ namespace embree return normals_out; } + struct PerspectiveCameraData + { + PerspectiveCameraData() + : from(1,0,0), to(0,0,0), up(0,1,0), fov(30) {} + + PerspectiveCameraData (const Vec3fa& from, const Vec3fa& to, const Vec3fa& up, const float fov) + : from(from), to(to), up(up), fov(fov) {} + + PerspectiveCameraData (const PerspectiveCameraData& other, const AffineSpace3fa& space) + : from(xfmPoint(space,other.from)), to(xfmPoint(space,other.to)), up(xfmVector(space,other.up)), fov(other.fov) {} + + friend PerspectiveCameraData lerp(const PerspectiveCameraData& a, const PerspectiveCameraData& b, const float t) + { + const Vec3fa from = embree::lerp(a.from, b.from, t); + const Vec3fa to = embree::lerp(a.to , b.to , t); + const Vec3fa up = embree::lerp(a.up , b.up , t); + const float fov = embree::lerp(a.fov , b.fov , t); + return PerspectiveCameraData(from,to,up,fov); + } + + public: + Vec3fa from; //!< position of camera + Vec3fa to; //!< look at point + Vec3fa up; //!< up vector + float fov; //!< vertical field of view + }; + struct PerspectiveCameraNode : public Node { ALIGNED_STRUCT_(16); + PerspectiveCameraNode (std::string name = "") + : Node(name) {} + PerspectiveCameraNode (const Vec3fa& from, const Vec3fa& to, const Vec3fa& up, const float fov) - : from(from), to(to), up(up), fov(fov) {} + : data(from, to, up, fov) {} - PerspectiveCameraNode (const Ref& other, const AffineSpace3fa& space, const std::string& id) - : Node(id), from(xfmPoint(space,other->from)), to(xfmPoint(space,other->to)), up(xfmVector(space,other->up)), fov(other->fov) {} + PerspectiveCameraNode (const Ref& other, const AffineSpace3fa& space, const std::string& id = "") + : Node(id), data(other->data,space) {} + + virtual bool isAnimated() const { + return false; + } + virtual PerspectiveCameraData get(float time) const { + return data; + } + virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual bool calculateClosed(bool group_instancing); public: - Vec3fa from; //!< position of camera - Vec3fa to; //!< look at point - Vec3fa up; //!< up vector - float fov; //!< vertical field of view + PerspectiveCameraData data; + }; + + struct AnimatedPerspectiveCameraNode : public PerspectiveCameraNode + { + AnimatedPerspectiveCameraNode (std::vector>&& cameras, BBox1f time_range, const std::string& id = "") + : time_range(time_range), cameras(cameras) {} + + AnimatedPerspectiveCameraNode (const Ref& other, const AffineSpace3fa& space, const std::string& id) + : PerspectiveCameraNode(id), time_range(other->time_range) + { + cameras.resize(other->size()); + for (size_t i=0; isize(); i++) + cameras[i] = new PerspectiveCameraNode(other->cameras[i],space); + } + + virtual bool isAnimated() const { + return true; + } + + virtual PerspectiveCameraData get(float time) const + { + time = frac((time-time_range.lower)/time_range.size()); + time = (cameras.size()-1)*time; + int itime = (int)floor(time); + itime = min(max(itime,0),(int)cameras.size()-2); + float ftime = time - (float)itime; + return lerp(cameras[itime+0]->get(time), cameras[itime+1]->get(time), ftime); + } + + virtual void print(std::ostream& cout, int depth); + + virtual void calculateStatistics(Statistics& stat); + virtual bool calculateClosed(bool group_instancing); + + size_t size() const { return cameras.size(); } + + public: + BBox1f time_range; + std::vector> cameras; }; struct TransformNode : public Node @@ -589,6 +670,25 @@ namespace embree return child->numPrimitives(); } + virtual AffineSpace3ff get(float time) const + { + if (spaces.size() <= 1) return spaces[0]; + + int numTimeSteps = spaces.size(); + + BBox1f time_range = spaces.time_range; + time = frac((time-time_range.lower)/time_range.size()); + time = (numTimeSteps-1)*time; + int itime = (int)floor(time); + itime = min(max(itime,0),(int)numTimeSteps-2); + float ftime = time - (float)itime; + + const AffineSpace3ff xfm0 = spaces[itime+0]; + const AffineSpace3ff xfm1 = spaces[itime+1]; + const AffineSpace3ff xfm = lerp(xfm0,xfm1,ftime); + return xfm; + } + public: Transformations spaces; Ref child; @@ -726,18 +826,87 @@ namespace embree public: std::vector > children; }; - + struct LightNode : public Node { - LightNode (Ref light) - : light(light) {} - virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual bool calculateClosed(bool group_instancing); + + virtual LightType getType() const = 0; + virtual Ref transform(const AffineSpace3fa& space) const = 0; + virtual Ref lerp(const Ref& light1_in, float f) const = 0; + virtual Ref get(float time) const = 0; + }; + + template + struct LightNodeImpl : public LightNode + { + ALIGNED_STRUCT_(16); - Ref light; + LightNodeImpl (const Light& light) + : light(light) {} + + virtual LightType getType() const { + return light.getType(); + } + + virtual Ref transform(const AffineSpace3fa& space) const { + return new LightNodeImpl(light.transform(space)); + } + + virtual Ref get(float time) const { + return (LightNode*) this; + } + + virtual Ref lerp(const Ref& light1_in, float f) const + { + const Ref> light1 = light1_in.dynamicCast>(); + assert(light1); + return new LightNodeImpl(Light::lerp(light,light1->light,f)); + } + + Light light; + }; + + struct AnimatedLightNode : public LightNode + { + AnimatedLightNode (const std::vector>&& lights, BBox1f time_range) + : lights(lights), time_range(time_range) {} + + virtual LightType getType() const { + return lights[0]->getType(); + } + + virtual Ref transform(const AffineSpace3fa& space) const + { + std::vector> xfm_lights(lights.size()); + for (size_t i=0; itransform(space); + return new AnimatedLightNode(std::move(xfm_lights), time_range); + } + + virtual Ref get(float time) const + { + time = frac((time-time_range.lower)/time_range.size()); + time = (lights.size()-1)*time; + int itime = (int)floor(time); + itime = min(max(itime,0),(int)lights.size()-2); + float ftime = time - (float)itime; + Ref light0 = lights[itime+0]->get(time); + Ref light1 = lights[itime+1]->get(time); + return light0->lerp(light1,ftime); + } + + virtual Ref lerp(const Ref& light1_in, float f) const { + assert(false); return nullptr; + } + + public: + std::vector> lights; + BBox1f time_range; }; + struct MaterialNode : public Node { @@ -1345,7 +1514,7 @@ namespace embree }; - enum InstancingMode { INSTANCING_NONE, INSTANCING_GEOMETRY, INSTANCING_GROUP, INSTANCING_FLATTENED }; + enum InstancingMode { INSTANCING_NONE, INSTANCING_GEOMETRY, INSTANCING_GROUP, INSTANCING_FLATTENED, INSTANCING_MULTI_LEVEL }; Ref flatten(Ref node, InstancingMode mode); Ref flatten(Ref node, InstancingMode mode); diff --git a/tutorials/common/scenegraph/texture.cpp b/tutorials/common/scenegraph/texture.cpp index 0cb890c7da..802c0a5cbb 100644 --- a/tutorials/common/scenegraph/texture.cpp +++ b/tutorials/common/scenegraph/texture.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "texture.h" diff --git a/tutorials/common/scenegraph/texture.h b/tutorials/common/scenegraph/texture.h index 48acf24e57..5e3e866345 100644 --- a/tutorials/common/scenegraph/texture.h +++ b/tutorials/common/scenegraph/texture.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/xml_loader.cpp b/tutorials/common/scenegraph/xml_loader.cpp index f9ebf00100..8410405cc4 100644 --- a/tutorials/common/scenegraph/xml_loader.cpp +++ b/tutorials/common/scenegraph/xml_loader.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "xml_loader.h" @@ -229,6 +229,8 @@ namespace embree Ref loadTriangleLight(const Ref& xml); Ref loadQuadLight(const Ref& xml); Ref loadHDRILight(const Ref& xml); + Ref loadLight(const Ref& xml); + Ref loadAnimatedLight(const Ref& xml); Ref loadTriangleMesh(const Ref& xml); Ref loadQuadMesh(const Ref& xml); @@ -240,6 +242,7 @@ namespace embree private: Ref loadPerspectiveCamera(const Ref& xml); + Ref loadAnimatedPerspectiveCamera(const Ref& xml); Ref loadMaterial(const Ref& xml); Ref loadTransformNode(const Ref& xml); Ref loadMultiTransformNode(const Ref& xml); @@ -662,8 +665,8 @@ namespace embree const AffineSpace3fa space = load(xml->child("AffineSpace")); const Vec3fa I = load(xml->child("I")); const Vec3fa P = Vec3fa(zero); - const Ref light = new SceneGraph::PointLight(P,I); - return new SceneGraph::LightNode(light->transform(space)); + const SceneGraph::PointLight light = SceneGraph::PointLight(P,I); + return new SceneGraph::LightNodeImpl(light.transform(space)); } Ref XMLLoader::loadSpotLight(const Ref& xml) @@ -674,8 +677,8 @@ namespace embree const Vec3fa D = Vec3fa(0,0,1); const float angleMin = load(xml->child("angleMin")); const float angleMax = load(xml->child("angleMax")); - const Ref light = new SceneGraph::SpotLight(P,D,I,angleMin,angleMax); - return new SceneGraph::LightNode(light->transform(space)); + const SceneGraph::SpotLight light = SceneGraph::SpotLight(P,D,I,angleMin,angleMax); + return new SceneGraph::LightNodeImpl(light.transform(space)); } Ref XMLLoader::loadDirectionalLight(const Ref& xml) @@ -683,8 +686,8 @@ namespace embree const AffineSpace3fa space = load(xml->child("AffineSpace")); const Vec3fa E = load(xml->child("E")); const Vec3fa D = Vec3fa(0,0,1); - const Ref light = new SceneGraph::DirectionalLight(D,E); - return new SceneGraph::LightNode(light->transform(space)); + const SceneGraph::DirectionalLight light = SceneGraph::DirectionalLight(D,E); + return new SceneGraph::LightNodeImpl(light.transform(space)); } Ref XMLLoader::loadDistantLight(const Ref& xml) @@ -693,14 +696,14 @@ namespace embree const Vec3fa L = load(xml->child("L")); const Vec3fa D = Vec3fa(0,0,1); const float halfAngle = load(xml->child("halfAngle")); - const Ref light = new SceneGraph::DistantLight(D,L,halfAngle); - return new SceneGraph::LightNode(light->transform(space)); + const SceneGraph::DistantLight light = SceneGraph::DistantLight(D,L,halfAngle); + return new SceneGraph::LightNodeImpl(light.transform(space)); } Ref XMLLoader::loadAmbientLight(const Ref& xml) { const Vec3fa L = load(xml->child("L")); - return new SceneGraph::LightNode(new SceneGraph::AmbientLight(L)); + return new SceneGraph::LightNodeImpl(SceneGraph::AmbientLight(L)); } Ref XMLLoader::loadTriangleLight(const Ref& xml) @@ -710,7 +713,7 @@ namespace embree const Vec3fa v0 = xfmPoint(space, Vec3fa(1, 0, 0)); const Vec3fa v1 = xfmPoint(space, Vec3fa(0, 1, 0)); const Vec3fa v2 = xfmPoint(space, Vec3fa(0, 0, 0)); - return new SceneGraph::LightNode(new SceneGraph::TriangleLight(v0,v1,v2,L)); + return new SceneGraph::LightNodeImpl(SceneGraph::TriangleLight(v0,v1,v2,L)); } Ref XMLLoader::loadQuadLight(const Ref& xml) @@ -721,7 +724,43 @@ namespace embree const Vec3fa v1 = xfmPoint(space, Vec3fa(0, 1, 0)); const Vec3fa v2 = xfmPoint(space, Vec3fa(1, 1, 0)); const Vec3fa v3 = xfmPoint(space, Vec3fa(1, 0, 0)); - return new SceneGraph::LightNode(new SceneGraph::QuadLight(v0,v1,v2,v3,L)); + return new SceneGraph::LightNodeImpl(SceneGraph::QuadLight(v0,v1,v2,v3,L)); + } + + Ref XMLLoader::loadLight(const Ref& xml) + { + const std::string id = xml->parm("id"); + if (xml->name == "PointLight" ) return state.sceneMap[id] = loadPointLight (xml); + else if (xml->name == "SpotLight" ) return state.sceneMap[id] = loadSpotLight (xml); + else if (xml->name == "DirectionalLight") return state.sceneMap[id] = loadDirectionalLight(xml); + else if (xml->name == "DistantLight" ) return state.sceneMap[id] = loadDistantLight (xml); + else if (xml->name == "AmbientLight" ) return state.sceneMap[id] = loadAmbientLight (xml); + else if (xml->name == "TriangleLight" ) return state.sceneMap[id] = loadTriangleLight (xml); + else if (xml->name == "AnimatedLight" ) return state.sceneMap[id] = loadAnimatedLight (xml); + else if (xml->name == "QuadLight" ) return state.sceneMap[id] = loadQuadLight (xml); + else THROW_RUNTIME_ERROR(xml->loc.str()+": invalid light node: "+xml->name); + } + + Ref XMLLoader::loadAnimatedLight(const Ref& xml) + { + size_t numLights = xml->size(); + if (numLights == 0) + return nullptr; + + /* load list of lights */ + std::vector> lights(numLights); + for (size_t i=0; ichild(i)).dynamicCast(); + + /* check that all lights are of same type */ + auto light_type = lights[0]->getType(); + for (size_t i=1; igetType()) + THROW_RUNTIME_ERROR(xml->loc.str()+": light types do not match"); + } + + const Vec2f time_range = xml->parm_Vec2f("time_range"); + return new SceneGraph::AnimatedLightNode(std::move(lights),BBox1f(time_range.x,time_range.y)); } std::shared_ptr XMLLoader::loadTextureParm(const Ref& xml) @@ -765,6 +804,21 @@ namespace embree return new SceneGraph::PerspectiveCameraNode(from,to,up,fov); } + Ref XMLLoader::loadAnimatedPerspectiveCamera(const Ref& xml) + { + size_t numCameras = xml->size(); + if (numCameras == 0) + return nullptr; + + std::vector> cameras(numCameras); + + for (size_t i=0; ichild(i)).dynamicCast(); + + const Vec2f time_range = xml->parm_Vec2f("time_range"); + return new SceneGraph::AnimatedPerspectiveCameraNode(std::move(cameras),BBox1f(time_range.x,time_range.y)); + } + Parms XMLLoader::loadMaterialParms(const Ref& parms) { Parms material; @@ -1378,6 +1432,7 @@ namespace embree else if (xml->name == "DistantLight" ) node = state.sceneMap[id] = loadDistantLight (xml); else if (xml->name == "AmbientLight" ) node = state.sceneMap[id] = loadAmbientLight (xml); else if (xml->name == "TriangleLight" ) node = state.sceneMap[id] = loadTriangleLight (xml); + else if (xml->name == "AnimatedLight" ) node = state.sceneMap[id] = loadAnimatedLight (xml); else if (xml->name == "QuadLight" ) node = state.sceneMap[id] = loadQuadLight (xml); else if (xml->name == "TriangleMesh" ) node = state.sceneMap[id] = loadTriangleMesh (xml); else if (xml->name == "QuadMesh" ) node = state.sceneMap[id] = loadQuadMesh (xml); @@ -1388,6 +1443,7 @@ namespace embree else if (xml->name == "Hair" ) node = state.sceneMap[id] = loadBezierCurves (xml,SceneGraph::FLAT_CURVE); else if (xml->name == "LineSegments" ) node = state.sceneMap[id] = loadCurves (xml,RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE); else if (xml->name == "RoundLineSegments") node = state.sceneMap[id] = loadCurves (xml,RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE); + else if (xml->name == "ConeSegments") node = state.sceneMap[id] = loadCurves (xml,RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE); else if (xml->name == "BezierHair" ) node = state.sceneMap[id] = loadBezierCurves (xml,SceneGraph::FLAT_CURVE); else if (xml->name == "BSplineHair" ) node = state.sceneMap[id] = loadCurves (xml,RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE); else if (xml->name == "BezierCurves" ) node = state.sceneMap[id] = loadBezierCurves (xml,SceneGraph::ROUND_CURVE); @@ -1470,6 +1526,7 @@ namespace embree node = state.sceneMap[id] = loadCurves(xml,type); } else if (xml->name == "PerspectiveCamera") node = state.sceneMap[id] = loadPerspectiveCamera(xml); + else if (xml->name == "AnimatedPerspectiveCamera") node = state.sceneMap[id] = loadAnimatedPerspectiveCamera(xml); else if (xml->name == "Group" ) node = state.sceneMap[id] = loadGroupNode (xml); else if (xml->name == "Transform" ) node = state.sceneMap[id] = loadTransformNode (xml); else if (xml->name == "MultiTransform" ) node = state.sceneMap[id] = loadMultiTransformNode(xml); diff --git a/tutorials/common/scenegraph/xml_loader.h b/tutorials/common/scenegraph/xml_loader.h index f2b888abc3..5a9de0e2b8 100644 --- a/tutorials/common/scenegraph/xml_loader.h +++ b/tutorials/common/scenegraph/xml_loader.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/xml_parser.cpp b/tutorials/common/scenegraph/xml_parser.cpp index 9459c8e2ae..92f079b61b 100644 --- a/tutorials/common/scenegraph/xml_parser.cpp +++ b/tutorials/common/scenegraph/xml_parser.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "xml_parser.h" diff --git a/tutorials/common/scenegraph/xml_parser.h b/tutorials/common/scenegraph/xml_parser.h index 74a86a88b1..6fe9267cff 100644 --- a/tutorials/common/scenegraph/xml_parser.h +++ b/tutorials/common/scenegraph/xml_parser.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/scenegraph/xml_writer.cpp b/tutorials/common/scenegraph/xml_writer.cpp index e73bfcf449..548cbaed5d 100644 --- a/tutorials/common/scenegraph/xml_writer.cpp +++ b/tutorials/common/scenegraph/xml_writer.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "xml_writer.h" @@ -9,7 +9,7 @@ namespace embree { public: - XMLWriter(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials); + XMLWriter(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials, bool binaryFormat); public: void tab(); @@ -20,9 +20,27 @@ namespace embree void store(const char* name, const char* str); void store(const char* name, const float& v); void store(const char* name, const Vec3fa& v); - template void store(const char* name, const std::vector& vec); - void store(const char* name, const avector& vec); - void store4f(const char* name, const avector& vec); + + void store_array_elt(const int& v); + void store_array_elt(const Vec2f& v); + void store_array_elt(const Vec3f& v); + void store_array_elt(const Vec3fa& v); + void store_array_elt(const Vec3ff& v); + void store_array_elt(const SceneGraph::TriangleMeshNode::Triangle& v); + void store_array_elt(const SceneGraph::QuadMeshNode::Quad& v); + + template void store_array_text (const char* name, const std::vector& vec); + template void store_array_binary(const char* name, const std::vector& vec); + template void store (const char* name, const std::vector& vec); + + void store_array_text (const char* name, const avector& vec); + void store_array_binary(const char* name, const avector& vec); + void store (const char* name, const avector& vec); + + void store_array_text (const char* name, const avector& vec); + void store_array_binary(const char* name, const avector& vec); + void store (const char* name, const avector& vec); + void store_parm(const char* name, const float& v); void store_parm(const char* name, const Vec3fa& v); void store_parm(const char* name, const std::shared_ptr tex); @@ -36,6 +54,7 @@ namespace embree void store(const SceneGraph::TriangleLight& light, ssize_t id); void store(const SceneGraph::QuadLight& light, ssize_t id); void store(Ref light, ssize_t id); + void store(Ref light, ssize_t id); void store(Ref material, ssize_t id); void store(Ref material, ssize_t id); @@ -54,6 +73,7 @@ namespace embree void store(Ref hair, ssize_t id); void store(Ref camera, ssize_t id); + void store(Ref camera, ssize_t id); void store(Ref node, ssize_t id); void store(std::vector> nodes); void store(Ref group, ssize_t id); @@ -70,6 +90,7 @@ namespace embree std::map, size_t> textureMap; // FIXME: use Ref bool embedTextures; bool referenceMaterials; + bool binaryFormat; }; ////////////////////////////////////////////////////////////////////////////// @@ -113,26 +134,101 @@ namespace embree tab(); xml << "<" << name << ">" << v.x << " " << v.y << " " << v.z << "" << std::endl; } + void XMLWriter::store_array_elt(const int& v) { + xml << v << std::endl; + } + + void XMLWriter::store_array_elt(const Vec2f& v) { + xml << v.x << " " << v.y << std::endl; + } + + void XMLWriter::store_array_elt(const Vec3f& v) { + xml << v.x << " " << v.y << " " << v.z << std::endl; + } + + void XMLWriter::store_array_elt(const Vec3fa& v) { + xml << v.x << " " << v.y << " " << v.z << std::endl; + } + + void XMLWriter::store_array_elt(const Vec3ff& v) { + xml << v.x << " " << v.y << " " << v.z << " " << v.w << std::endl; + } + + void XMLWriter::store_array_elt(const SceneGraph::TriangleMeshNode::Triangle& v) { + xml << v.v0 << " " << v.v1 << " " << v.v2 << std::endl; + } + + void XMLWriter::store_array_elt(const SceneGraph::QuadMeshNode::Quad& v) { + xml << v.v0 << " " << v.v1 << " " << v.v2 << " " << v.v3 << std::endl; + } + template - void XMLWriter::store(const char* name, const std::vector& vec) + void XMLWriter::store_array_text(const char* name, const std::vector& vec) + { + open(name); + for (size_t i=0; i + void XMLWriter::store_array_binary(const char* name, const std::vector& vec) { std::streampos offset = bin.tellg(); tab(); xml << "<" << name << " ofs=\"" << offset << "\" size=\"" << vec.size() << "\"/>" << std::endl; if (vec.size()) bin.write((char*)vec.data(),vec.size()*sizeof(T)); } - void XMLWriter::store(const char* name, const avector& vec) + template + void XMLWriter::store(const char* name, const std::vector& vec) + { + if (binaryFormat) store_array_binary(name,vec); + else store_array_text (name,vec); + } + + void XMLWriter::store_array_text(const char* name, const avector& vec) + { + open(name); + for (size_t i=0; i& vec) { std::streampos offset = bin.tellg(); tab(); xml << "<" << name << " ofs=\"" << offset << "\" size=\"" << vec.size() << "\"/>" << std::endl; for (size_t i=0; i& vec) + void XMLWriter::store(const char* name, const avector& vec) + { + if (binaryFormat) store_array_binary(name,vec); + else store_array_text (name,vec); + } + + void XMLWriter::store_array_text(const char* name, const avector& vec) + { + open(name); + for (size_t i=0; i& vec) { std::streampos offset = bin.tellg(); tab(); xml << "<" << name << " ofs=\"" << offset << "\" size=\"" << vec.size() << "\"/>" << std::endl; - for (size_t i=0; i& vec) + { + if (binaryFormat) store_array_binary(name,vec); + else store_array_text (name,vec); } void XMLWriter::store_parm(const char* name, const float& v) { @@ -240,18 +336,33 @@ namespace embree void XMLWriter::store(Ref node, ssize_t id) { - switch (node->light->getType()) - { - case SceneGraph::LIGHT_AMBIENT : store(*node->light.dynamicCast(),id); break; - case SceneGraph::LIGHT_POINT : store(*node->light.dynamicCast(),id); break; - case SceneGraph::LIGHT_DIRECTIONAL : store(*node->light.dynamicCast(),id); break; - case SceneGraph::LIGHT_SPOT : store(*node->light.dynamicCast(),id); break; - case SceneGraph::LIGHT_DISTANT : store(*node->light.dynamicCast(),id); break; - case SceneGraph::LIGHT_TRIANGLE : store(*node->light.dynamicCast(),id); break; - case SceneGraph::LIGHT_QUAD : store(*node->light.dynamicCast(),id); break; - - default: throw std::runtime_error("unsupported light"); - } + if (auto light = node.dynamicCast>()) + store(light->light,id); + else if (auto light = node.dynamicCast>()) + store(light->light,id); + else if (auto light = node.dynamicCast>()) + store(light->light,id); + else if (auto light = node.dynamicCast>()) + store(light->light,id); + else if (auto light = node.dynamicCast>()) + store(light->light,id); + else if (auto light = node.dynamicCast>()) + store(light->light,id); + else if (auto light = node.dynamicCast>()) + store(light->light,id); + else + throw std::runtime_error("unsupported light"); + } + + void XMLWriter::store(Ref node, ssize_t id) + { + open(std::string("AnimatedLight ")+ + "time_range=\""+std::to_string(node->time_range.lower)+" "+std::to_string(node->time_range.upper)+"\""); + + for (size_t i=0; ilights.size(); i++) + store(node->lights[i].dynamicCast()); + + close("AnimatedLight"); } void XMLWriter::store(Ref material, ssize_t id) @@ -511,7 +622,7 @@ namespace embree open("Curves type=\""+str_subtype+"\" basis=\""+str_type+"\"",id); store(mesh->material); if (mesh->numTimeSteps() != 1) open("animated_positions"); - for (const auto& p : mesh->positions) store4f("positions",p); + for (const auto& p : mesh->positions) store("positions",p); if (mesh->numTimeSteps() != 1) close("animated_positions"); if (mesh->normals.size()) { if (mesh->numTimeSteps() != 1) open("animated_normals"); @@ -529,10 +640,22 @@ namespace embree xml << "name << "\" " << - "from=\"" << camera->from.x << " " << camera->from.y << " " << camera->from.z << "\" " << - "to=\"" << camera->to.x << " " << camera->to.y << " " << camera->to.z << "\" " << - "up=\"" << camera->up.x << " " << camera->up.y << " " << camera->up.z << "\" " << - "fov=\"" << camera->fov << "\" " << "/>" << std::endl; + "from=\"" << camera->data.from.x << " " << camera->data.from.y << " " << camera->data.from.z << "\" " << + "to=\"" << camera->data.to.x << " " << camera->data.to.y << " " << camera->data.to.z << "\" " << + "up=\"" << camera->data.up.x << " " << camera->data.up.y << " " << camera->data.up.z << "\" " << + "fov=\"" << camera->data.fov << "\" " << "/>" << std::endl; + } + + void XMLWriter::store(Ref camera, ssize_t id) + { + open(std::string("AnimatedPerspectiveCamera ")+ + "name=\"" + camera->name + "\" " + "time_range=\""+std::to_string(camera->time_range.lower)+" "+std::to_string(camera->time_range.upper)+"\""); + + for (size_t i=0; isize(); i++) + store(camera->cameras[i].dynamicCast()); + + close("AnimatedPerspectiveCamera"); } void XMLWriter::store(Ref node, ssize_t id) @@ -619,29 +742,34 @@ namespace embree const ssize_t id = nodeMap[node] = currentNodeID++; if (node->fileName != "") { tab(); xml << "fileName << "\"/>" << std::endl; return; - } + } - if (Ref cnode = node.dynamicCast()) store(cnode,id); + if (Ref cnode = node.dynamicCast()) store(cnode,id); + else if (Ref cnode = node.dynamicCast()) store(cnode,id); //else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); + else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); else if (Ref cnode = node.dynamicCast()) store(cnode,id); else throw std::runtime_error("unknown node type"); } - XMLWriter::XMLWriter(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials) - : ident(0), currentNodeID(0), embedTextures(embedTextures), referenceMaterials(referenceMaterials) + XMLWriter::XMLWriter(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials, bool binaryFormat) + : ident(0), currentNodeID(0), embedTextures(embedTextures), referenceMaterials(referenceMaterials), binaryFormat(binaryFormat) { - FileName binFileName = fileName.addExt(".bin"); - xml.exceptions (std::fstream::failbit | std::fstream::badbit); xml.open (fileName, std::fstream::out); - bin.exceptions (std::fstream::failbit | std::fstream::badbit); - bin.open (binFileName, std::fstream::out | std::fstream::binary); + + if (binaryFormat) + { + const FileName binFileName = fileName.addExt(".bin"); + bin.exceptions (std::fstream::failbit | std::fstream::badbit); + bin.open (binFileName, std::fstream::out | std::fstream::binary); + } xml << "" << std::endl; root->calculateInDegree(); @@ -651,7 +779,7 @@ namespace embree root->resetInDegree(); } - void SceneGraph::storeXML(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials) { - XMLWriter(root,fileName,embedTextures,referenceMaterials); + void SceneGraph::storeXML(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials, bool binaryFormat) { + XMLWriter(root,fileName,embedTextures,referenceMaterials,binaryFormat); } } diff --git a/tutorials/common/scenegraph/xml_writer.h b/tutorials/common/scenegraph/xml_writer.h index 0d89c5dae3..18619e7dfa 100644 --- a/tutorials/common/scenegraph/xml_writer.h +++ b/tutorials/common/scenegraph/xml_writer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -9,7 +9,7 @@ namespace embree { namespace SceneGraph { - void storeXML(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials); + void storeXML(Ref root, const FileName& fileName, bool embedTextures, bool referenceMaterials, bool binaryFormat); } } diff --git a/tutorials/common/texture/CMakeLists.txt b/tutorials/common/texture/CMakeLists.txt index 5fdc53f069..9539f89c6b 100644 --- a/tutorials/common/texture/CMakeLists.txt +++ b/tutorials/common/texture/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_LIBRARY(texture STATIC diff --git a/tutorials/common/texture/texture.h b/tutorials/common/texture/texture.h index 68f1cf1c9e..17af3624e7 100644 --- a/tutorials/common/texture/texture.h +++ b/tutorials/common/texture/texture.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /*! This header is shared with ISPC. */ diff --git a/tutorials/common/texture/texture2d.cpp b/tutorials/common/texture/texture2d.cpp index 71d52e65c3..a668d3cb3a 100644 --- a/tutorials/common/texture/texture2d.cpp +++ b/tutorials/common/texture/texture2d.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "texture2d.h" diff --git a/tutorials/common/texture/texture2d.h b/tutorials/common/texture/texture2d.h index 380307ce80..8e557cb021 100644 --- a/tutorials/common/texture/texture2d.h +++ b/tutorials/common/texture/texture2d.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/texture/texture2d.ispc b/tutorials/common/texture/texture2d.ispc index a517cc6811..998ff836d7 100644 --- a/tutorials/common/texture/texture2d.ispc +++ b/tutorials/common/texture/texture2d.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "texture2d.isph" diff --git a/tutorials/common/texture/texture2d.isph b/tutorials/common/texture/texture2d.isph index 6ee11a4bcc..e09354737e 100644 --- a/tutorials/common/texture/texture2d.isph +++ b/tutorials/common/texture/texture2d.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/texture/texture_param.h b/tutorials/common/texture/texture_param.h index 6a273a92dc..4efb4dff75 100644 --- a/tutorials/common/texture/texture_param.h +++ b/tutorials/common/texture/texture_param.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/texture/texture_param.isph b/tutorials/common/texture/texture_param.isph index 7c209d9b86..8e0ef58727 100644 --- a/tutorials/common/texture/texture_param.isph +++ b/tutorials/common/texture/texture_param.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/tutorial/CMakeLists.txt b/tutorials/common/tutorial/CMakeLists.txt index 93fd735b6a..c8ed32bb45 100644 --- a/tutorials/common/tutorial/CMakeLists.txt +++ b/tutorials/common/tutorial/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF (EMBREE_TUTORIALS_GLFW) @@ -10,6 +10,27 @@ TARGET_LINK_LIBRARIES(tutorial sys math lexers scenegraph lights embree ${IMGUI_ SET_PROPERTY(TARGET tutorial PROPERTY FOLDER tutorials/common) SET_PROPERTY(TARGET tutorial APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") +option(EMBREE_USE_GOOGLE_BENCHMARK "Use google benchmark (note: set benchmark_DIR to benchmark_install_dir/lib/cmake/benchmark)" OFF) + +IF(EMBREE_USE_GOOGLE_BENCHMARK) + IF (NOT DEFINED benchmark_DIR) + message(FATAL_ERROR "set benchmark_DIR to benchmark_install_dir/lib/cmake/benchmark") + ENDIF() + FIND_PACKAGE(benchmark REQUIRED) + IF (NOT TARGET benchmark::benchmark) + message(FATAL_ERROR "benchmark not found") + ENDIF() +ENDIF() + +ADD_LIBRARY(benchmark STATIC benchmark.cpp) +SET_PROPERTY(TARGET benchmark PROPERTY FOLDER tutorials/common) +SET_PROPERTY(TARGET benchmark APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") +IF(EMBREE_USE_GOOGLE_BENCHMARK) + TARGET_COMPILE_DEFINITIONS(benchmark PUBLIC USE_GOOGLE_BENCHMARK) + TARGET_LINK_LIBRARIES(benchmark benchmark::benchmark benchmark::benchmark_main) +ENDIF() +TARGET_LINK_LIBRARIES(tutorial benchmark) + ADD_LIBRARY(noise STATIC noise.cpp) SET_PROPERTY(TARGET noise PROPERTY FOLDER tutorials/common) SET_PROPERTY(TARGET noise APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") @@ -24,27 +45,40 @@ IF (EMBREE_ISPC_SUPPORT) SET_TARGET_PROPERTIES(noise_ispc PROPERTIES LINKER_LANGUAGE CXX) SET_PROPERTY(TARGET noise_ispc PROPERTY FOLDER tutorials/common) SET_PROPERTY(TARGET noise_ispc APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + TARGET_LINK_LIBRARIES(tutorial_ispc benchmark) ENDIF() IF (WIN32 AND NOT EMBREE_EXTERNAL_GLFW) GET_FILENAME_COMPONENT(GLFW_DIR ${GLFW_LIBRARY} PATH) ADD_CUSTOM_COMMAND(TARGET tutorial POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GLFW_DIR}/glfw3.dll $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${GLFW_DIR}/glfw3.dll" "$" COMMENT "Copying GLFW DLL" VERBATIM ) IF (EMBREE_SIGN_FILE) ADD_CUSTOM_COMMAND(TARGET tutorial POST_BUILD - COMMAND ${EMBREE_SIGN_FILE} $/glfw3.dll + COMMAND ${EMBREE_SIGN_FILE} "$/glfw3.dll" COMMENT "Signing GLFW DLL" VERBATIM ) ENDIF() - INSTALL(PROGRAMS $/glfw3.dll DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) + INSTALL(PROGRAMS "$/glfw3.dll" DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) +ENDIF() +IF(WIN32) + GET_TARGET_PROPERTY(DLL_PATH_RELEASE tasking IMPORTED_LOCATION_RELEASE) + GET_TARGET_PROPERTY(DLL_PATH_DEBUG tasking IMPORTED_LOCATION_DEBUG) + IF (DLL_PATH_DEBUG OR DLL_PATH_RELEASE) + SET(DLL_PATH $<$:${DLL_PATH_DEBUG}>$<$>:${DLL_PATH_RELEASE}>) + ADD_CUSTOM_COMMAND(TARGET tutorial POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DLL_PATH} $ + COMMENT "Copying TBB DLL" VERBATIM + ) + ENDIF() ENDIF() ADD_CUSTOM_COMMAND(TARGET tutorial POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/tutorials/models $/models + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/../../models" "$/models" COMMENT "Copying example models") diff --git a/tutorials/common/tutorial/application.cpp b/tutorials/common/tutorial/application.cpp index 502a16a237..3b38796415 100644 --- a/tutorials/common/tutorial/application.cpp +++ b/tutorials/common/tutorial/application.cpp @@ -1,11 +1,38 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "application.h" +#if defined(_WIN32) +# include +# include +# include +#endif + namespace embree { Application* Application::instance = nullptr; + + void waitForKeyPressedUnderWindows() + { +#if defined(_WIN32) + HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (!GetConsoleScreenBufferInfo(hStdOutput, &csbi)) { + printf("GetConsoleScreenBufferInfo failed: %d\n", GetLastError()); + return; + } + + /* do not pause when running on a shell */ + if (csbi.dwCursorPosition.X != 0 || csbi.dwCursorPosition.Y != 0) + return; + + /* only pause if running in separate console window. */ + printf("\n\tPress any key to exit...\n"); + int ch = getch(); +#endif + } Application::Application(int features) : rtcore("start_threads=1,set_affinity=1"), verbosity(0), @@ -16,7 +43,7 @@ namespace embree last_resident_memory(0) { if (instance) - throw std::runtime_error("internal error: applicaton already created"); + throw std::runtime_error("internal error: application already created"); instance = this; @@ -70,8 +97,7 @@ namespace embree " avx: select AVX codepath\n" " avxi: select AVXI codepath\n" " avx2: select AVX2 codepath\n" - " avx512knl: select AVX512 codepath for KNL\n" - " avx512skx: select AVX512 codepath for SKX\n"); + " avx512: select AVX512 codepath\n"); } } @@ -80,12 +106,37 @@ namespace embree assert(instance == this); instance = nullptr; } - - void Application::registerOptionAlias(const std::string& name, const std::string& alternativeName) { + + void Application::log(int verbose, const std::string& str) + { + if (verbosity < verbose) + return; + + double time = getSeconds(); + ssize_t virtual_memory = getVirtualMemoryBytes(); + ssize_t resident_memory = getResidentMemoryBytes(); + + double log_time = log_delta ? time-last_time : time-start_time; + ssize_t log_virtual_memory = log_delta ? virtual_memory-last_virtual_memory : virtual_memory; + ssize_t log_resident_memory = log_delta ? resident_memory-last_resident_memory : resident_memory; + + std::cout << "[ " + << std::setw(8) << std::setprecision(3) << std::fixed << log_time << "s, " + << std::setw(8) << std::setprecision(2) << std::fixed << double(log_virtual_memory)/1E6 << " MB virtual, " + << std::setw(8) << std::setprecision(2) << std::fixed << double(log_resident_memory)/1E6 << " MB resident ] " + << str << std::fixed + << std::endl << std::flush; + + last_time = time; + last_virtual_memory = virtual_memory; + last_resident_memory = resident_memory; + } + + void CommandLineParser::registerOptionAlias(const std::string& name, const std::string& alternativeName) { commandLineOptionMap[alternativeName] = commandLineOptionMap[name]; } - - void Application::parseCommandLine(int argc, char** argv) + + void CommandLineParser::parseCommandLine(int argc, char** argv) { /* create stream for parsing */ Ref stream = new ParseStream(new CommandLineStream(argc, argv)); @@ -94,7 +145,7 @@ namespace embree parseCommandLine(stream, FileName()); } - void Application::parseCommandLine(Ref cin, const FileName& path) + void CommandLineParser::parseCommandLine(Ref cin, const FileName& path) { while (true) { @@ -116,42 +167,19 @@ namespace embree } } - /* handle unknown command line options */ - std::cerr << "unknown command line parameter: " << tag0 << " "; - while (cin->peek() != "" && cin->peek()[0] != '-') std::cerr << cin->getString() << " "; - std::cerr << std::endl; + if (verbosity != SILENT) { + /* handle unknown command line options */ + std::cerr << "unknown command line parameter: " << tag0 << " "; + while (cin->peek() != "" && cin->peek()[0] != '-') std::cerr << cin->getString() << " "; + std::cerr << std::endl; + } } } - void Application::printCommandLineHelp() + void CommandLineParser::printCommandLineHelp() { for (auto& c : commandLineOptionList) { std::cout << c->description << std::endl; } } - - void Application::log(int verbose, const std::string& str) - { - if (verbosity < verbose) - return; - - double time = getSeconds(); - ssize_t virtual_memory = getVirtualMemoryBytes(); - ssize_t resident_memory = getResidentMemoryBytes(); - - double log_time = log_delta ? time-last_time : time-start_time; - ssize_t log_virtual_memory = log_delta ? virtual_memory-last_virtual_memory : virtual_memory; - ssize_t log_resident_memory = log_delta ? resident_memory-last_resident_memory : resident_memory; - - std::cout << "[ " - << std::setw(8) << std::setprecision(3) << std::fixed << log_time << "s, " - << std::setw(8) << std::setprecision(2) << std::fixed << double(log_virtual_memory)/1E6 << " MB virtual, " - << std::setw(8) << std::setprecision(2) << std::fixed << double(log_resident_memory)/1E6 << " MB resident ] " - << str << std::fixed - << std::endl << std::flush; - - last_time = time; - last_virtual_memory = virtual_memory; - last_resident_memory = resident_memory; - } } diff --git a/tutorials/common/tutorial/application.h b/tutorials/common/tutorial/application.h index 02d8f05b18..ed43eccf11 100644 --- a/tutorials/common/tutorial/application.h +++ b/tutorials/common/tutorial/application.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -7,32 +7,31 @@ namespace embree { - class Application + void waitForKeyPressedUnderWindows(); + + struct CommandLineParser { - public: - enum Features { FEATURE_RTCORE = 1, FEATURE_STREAM = 2 }; - - Application (int features); - virtual ~Application(); - - static Application* instance; + enum Verbosity { + NORMAL = 0, + SILENT + }; + CommandLineParser(Verbosity verbosity = NORMAL) : verbosity(verbosity) {} + /* virtual interface for command line option processing */ struct CommandLineOption : public RefCount { - public: CommandLineOption (const std::string& description) : description(description) {} virtual void parse(Ref cin, const FileName& path) = 0; - public: std::string description; }; - + /* helper class to provide parsing function via lambda function */ template - struct CommandLineOptionClosure : public CommandLineOption + struct CommandLineOptionClosure : public CommandLineOption { CommandLineOptionClosure (std::string description, const F& f) : CommandLineOption(description), f(f) {} @@ -41,10 +40,9 @@ namespace embree f(cin,path); } - public: F f; }; - + /* registers a command line option */ template void registerOption(const std::string& name, const F& f, const std::string& description) @@ -64,13 +62,49 @@ namespace embree /* prints help for all supported command line options */ void printCommandLineHelp(); - /* print log message */ - void log(int verbose, const std::string& str); - /* command line options database */ - public: std::vector< Ref > commandLineOptionList; std::map > commandLineOptionMap; + + Verbosity verbosity; + }; + + class Application + { + public: + enum Features { FEATURE_RTCORE = 1, FEATURE_STREAM = 2 }; + + Application (int features); + virtual ~Application(); + + static Application* instance; + + /* print log message */ + void log(int verbose, const std::string& str); + + template + void registerOption(const std::string& name, const F& f, const std::string& description) { + commandLineParser.registerOption(name, f, description); + } + + /* registers an alias for a command line option */ + void registerOptionAlias(const std::string& name, const std::string& alternativeName) { + commandLineParser.registerOptionAlias(name, alternativeName); + } + + /* command line parsing */ + void parseCommandLine(int argc, char** argv) { + commandLineParser.parseCommandLine(argc, argv); + } + + void parseCommandLine(Ref cin, const FileName& path) { + commandLineParser.parseCommandLine(cin, path); + } + + /* prints help for all supported command line options */ + void printCommandLineHelp() { + commandLineParser.printCommandLineHelp(); + } public: @@ -80,6 +114,8 @@ namespace embree public: std::string rtcore; // embree configuration int verbosity; // verbosity of output + + CommandLineParser commandLineParser; public: bool log_delta; // whether to print delta stats diff --git a/tutorials/common/tutorial/benchmark.cpp b/tutorials/common/tutorial/benchmark.cpp new file mode 100644 index 0000000000..d64678e4d4 --- /dev/null +++ b/tutorials/common/tutorial/benchmark.cpp @@ -0,0 +1,253 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include + +#include "benchmark.h" + +#ifdef USE_GOOGLE_BENCHMARK +#include +#endif + +namespace embree { + +////////////////////////////////////////////// +// util functions for command line handling // +////////////////////////////////////////////// +struct CommandLine +{ + typedef std::unordered_set> StringPool; + typedef std::unordered_set>> CommandLinePool; + + static StringPool string_pool; + static CommandLinePool command_line_pool; + + CommandLine() : cl(nullptr) { } + + CommandLine(int argc, char** argv) : cl(nullptr) + { + auto cl_iter = command_line_pool.emplace(std::unique_ptr>(new std::vector())); + cl = cl_iter.first->get(); + for (size_t i = 0; i < argc; ++i) { + auto pair = string_pool.emplace(std::unique_ptr{new std::string(argv[i])}); + cl->emplace_back(&(*pair.first->get())[0]); + } + } + + void add(std::vector const& args) + { + for (std::string const& str : args) { + auto pair = string_pool.emplace(std::unique_ptr{new std::string(str)}); + cl->emplace_back(&(*pair.first->get())[0]); + } + } + + int argc() { return cl->size(); } + char** argv() { return cl->data(); } + +private: + std::vector* cl; +}; + +CommandLine::StringPool CommandLine::string_pool; +CommandLine::CommandLinePool CommandLine::command_line_pool; + +bool endsWith(std::string const &str, std::string const &suffix) +{ + if (str.length() <= suffix.length()) + return false; + return str.substr(str.length() - suffix.length(), str.length() - 1) == suffix; +} + +bool startsWith(std::string const &str, std::string const &prefix) +{ + if (str.length() <= prefix.length()) + return false; + return (str.rfind(prefix, 0) == 0); +} + +std::string removeQuotes(std::string const &str) +{ + std::string res = str; + if (startsWith(res, "\"")) + res = res.substr(1, res.length()); + if (endsWith(res, "\"")) + res = res.substr(0, res.length() - 1); + return res; +} + +std::string getFileName(std::string const &path) +{ + const size_t b = (path.rfind("/") == std::string::npos) ? 0 : path.rfind("/") + 1; + return path.substr(b, path.rfind(".") - b); +} + +void printCommandLine(int argc, char** argv) +{ + for (int i = 0; i < argc; ++i) + std::cout << argv[i] << (i < argc-1 ? " " : ""); + if (argc > 0) std::cout << std::endl; +} +////////////////////////////////////////////// +////////////////////////////////////////////// + +int TutorialBenchmark::main(int argc, char** argv, std::string name) +{ + commandLineParser.parseCommandLine(argc, argv); + updateCommandLine(argc, argv); + + CommandLine commandLine(argc, argv); + +#if USE_GOOGLE_BENCHMARK + if (!params.legacy && params.minTimeOrIterations > 0) + commandLine.add({"--benchmark_min_time=" + std::to_string(params.minTimeOrIterations)}); + if (!params.legacy && params.repetitions > 0) + commandLine.add({"--benchmark_repetitions=" + std::to_string(params.repetitions)}); +#endif + + argc = commandLine.argc(); + argv = commandLine.argv(); + +#ifdef USE_GOOGLE_BENCHMARK + if (!params.legacy) + ::benchmark::Initialize(&argc, argv); +#endif + + commandLine = CommandLine(argc, argv); + + postParseCommandLine(); + + std::string benchmark_name = name; + if (endsWith(inputFile, ".xml")) { + benchmark_name = getFileName(inputFile); + } + else if (endsWith(inputFile, ".ecs")) { + benchmark_name = getFileName(inputFile); + } + + if (params.name != "") + benchmark_name = params.name; + + registerBenchmark(benchmark_name, commandLine.argc(), commandLine.argv()); + +#ifdef USE_GOOGLE_BENCHMARK + if (!params.legacy) + ::benchmark::RunSpecifiedBenchmarks(); +#endif + + return 0; +} + +// remove the processed commdand line options +void TutorialBenchmark::updateCommandLine(int& argc, char** argv) +{ + for (std::string const& str : processedCommandLineOptions) + { + for (int i = 0; i < argc; ++i) { + if (std::string(argv[i]) == str) { + int remove = 1; + int j = i+1; + while(j < argc && !startsWith(std::string(argv[j]), "-")) { + remove++; + j++; + } + argc -= remove; + for (j = i; j < argc; ++j) { + argv[j] = argv[j+remove]; + } + } + } + } +} + +void TutorialBenchmark::postParseCommandLine() +{ + +} + +void callBenchFunc(benchmark::State& state, int argc, char** argv, BenchParams benchParams, BenchFunc benchFunc) +{ + BenchState benchState; + benchState.state = &state; + benchFunc(benchState, benchParams, argc, argv); +} + +void TutorialBenchmark::registerBenchmark(std::string const& name, int argc, char** argv) +{ +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + std::cout << "BENCHMARK SCENE: " << name << std::endl; + BenchState benchState; + func(benchState, params, argc, argv); + } + else { + ::benchmark::RegisterBenchmark(name.c_str(), callBenchFunc, argc, argv, params, func)->Unit(::benchmark::TimeUnit::kMillisecond); + } +#else + std::cout << "BENCHMARK SCENE: " << name << std::endl; + BenchState benchState; + func(benchState, params, argc, argv); +#endif +} + +void callBuildBenchFunc(benchmark::State& state, int argc, char** argv, BenchParams benchParams, BuildBenchParams buildBenchParams, BuildBenchFunc buildBenchFunc) +{ + BenchState benchState; + benchState.state = &state; + buildBenchFunc(benchState, benchParams, buildBenchParams, argc, argv); +} + +void TutorialBuildBenchmark::registerBuildBenchmark(std::string name, BuildBenchType buildBenchType, int argc, char** argv) +{ + if (buildParams.buildBenchType & buildBenchType) { + // attach benchmark name if more than one bit in buildBenchMask is set + bool attach = (buildParams.buildBenchType & (buildParams.buildBenchType - 1)) != 0; + if (attach) name += "_" + getBuildBenchTypeString(buildBenchType); + BuildBenchParams p = buildParams; + p.buildBenchType = buildBenchType; +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + std::cout << "BENCHMARK SCENE: " << name << std::endl; + BenchState benchState; + buildBenchFunc(benchState, params, p, argc, argv); + } + else { + ::benchmark::RegisterBenchmark(name.c_str(), callBuildBenchFunc, argc, argv, params, p, buildBenchFunc)->Unit(::benchmark::TimeUnit::kMillisecond); + } +#else + std::cout << "BENCHMARK SCENE: " << name << std::endl; + BenchState benchState; + buildBenchFunc(benchState, params, p, argc, argv); +#endif + } +} + +void TutorialBuildBenchmark::registerBenchmark(std::string const& name, int argc, char** argv) +{ + registerBuildBenchmark(name, BuildBenchType::UPDATE_DYNAMIC_DEFORMABLE, argc, argv); + registerBuildBenchmark(name, BuildBenchType::UPDATE_DYNAMIC_DYNAMIC, argc, argv); + registerBuildBenchmark(name, BuildBenchType::UPDATE_DYNAMIC_STATIC, argc, argv); + registerBuildBenchmark(name, BuildBenchType::CREATE_DYNAMIC_DEFORMABLE, argc, argv); + registerBuildBenchmark(name, BuildBenchType::CREATE_DYNAMIC_DYNAMIC, argc, argv); + registerBuildBenchmark(name, BuildBenchType::CREATE_DYNAMIC_STATIC, argc, argv); + registerBuildBenchmark(name, BuildBenchType::CREATE_STATIC_STATIC, argc, argv); + registerBuildBenchmark(name, BuildBenchType::CREATE_HIGH_QUALITY_STATIC_STATIC, argc, argv); + registerBuildBenchmark(name, BuildBenchType::CREATE_USER_THREADS_STATIC_STATIC, argc, argv); +} + +void TutorialBuildBenchmark::postParseCommandLine() +{ + if (buildParams.userThreads > 0) { + buildParams.buildBenchType = BuildBenchType::CREATE_USER_THREADS_STATIC_STATIC; + } else { + buildParams.buildBenchType = (BuildBenchType)(buildParams.buildBenchType & ~(BuildBenchType::CREATE_USER_THREADS_STATIC_STATIC)); + } +} + +} \ No newline at end of file diff --git a/tutorials/common/tutorial/benchmark.h b/tutorials/common/tutorial/benchmark.h new file mode 100644 index 0000000000..83af332fb2 --- /dev/null +++ b/tutorials/common/tutorial/benchmark.h @@ -0,0 +1,165 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "application.h" + +namespace benchmark +{ + struct State; +} + +namespace embree { + +enum BuildBenchType { + UPDATE_DYNAMIC_DEFORMABLE = 1, + UPDATE_DYNAMIC_DYNAMIC = 2, + UPDATE_DYNAMIC_STATIC = 4, + CREATE_DYNAMIC_DEFORMABLE = 8, + CREATE_DYNAMIC_DYNAMIC = 16, + CREATE_DYNAMIC_STATIC = 32, + CREATE_STATIC_STATIC = 64, + CREATE_HIGH_QUALITY_STATIC_STATIC = 128, + CREATE_USER_THREADS_STATIC_STATIC = 256, + ALL = 511 +}; + +static MAYBE_UNUSED BuildBenchType getBuildBenchType(std::string const& str) +{ + if (str == "update_dynamic_deformable") return BuildBenchType::UPDATE_DYNAMIC_DEFORMABLE; + else if (str == "update_dynamic_dynamic") return BuildBenchType::UPDATE_DYNAMIC_DYNAMIC; + else if (str == "update_dynamic_static") return BuildBenchType::UPDATE_DYNAMIC_STATIC; + else if (str == "create_dynamic_deformable") return BuildBenchType::CREATE_DYNAMIC_DEFORMABLE; + else if (str == "create_dynamic_dynamic") return BuildBenchType::CREATE_DYNAMIC_DYNAMIC; + else if (str == "create_dynamic_static") return BuildBenchType::CREATE_DYNAMIC_STATIC; + else if (str == "create_static_static") return BuildBenchType::CREATE_STATIC_STATIC; + else if (str == "create_high_quality_static_static") return BuildBenchType::CREATE_HIGH_QUALITY_STATIC_STATIC; + else if (str == "create_user_threads_static_static") return BuildBenchType::CREATE_USER_THREADS_STATIC_STATIC; + return BuildBenchType::ALL; +} + +static MAYBE_UNUSED std::string getBuildBenchTypeString(BuildBenchType type) +{ + if (type == BuildBenchType::UPDATE_DYNAMIC_DEFORMABLE) return "update_dynamic_deformable"; + else if (type == BuildBenchType::UPDATE_DYNAMIC_DYNAMIC) return "update_dynamic_dynamic"; + else if (type == BuildBenchType::UPDATE_DYNAMIC_STATIC) return "update_dynamic_static"; + else if (type == BuildBenchType::CREATE_DYNAMIC_DEFORMABLE) return "create_dynamic_deformable"; + else if (type == BuildBenchType::CREATE_DYNAMIC_DYNAMIC) return "create_dynamic_dynamic"; + else if (type == BuildBenchType::CREATE_DYNAMIC_STATIC) return "create_dynamic_static"; + else if (type == BuildBenchType::CREATE_STATIC_STATIC) return "create_static_static"; + else if (type == BuildBenchType::CREATE_HIGH_QUALITY_STATIC_STATIC) return "create_high_quality_static_static"; + else if (type == BuildBenchType::CREATE_USER_THREADS_STATIC_STATIC) return "create_user_threads_static_static"; + return "all"; +} + +struct BenchState { + benchmark::State* state; +}; + +struct BenchParams { + int skipIterations = 0; + int minTimeOrIterations = 0; + int repetitions = 0; + bool legacy = false; + std::string name = ""; +}; + +struct BuildBenchParams { + BuildBenchType buildBenchType = BuildBenchType::ALL; + int userThreads = 0; +}; + +using BenchFunc = void(*)(BenchState& state, BenchParams& params, int argc, char** argv); +using BuildBenchFunc = void(*)(BenchState& state, BenchParams& params, BuildBenchParams& buildParams, int argc, char** argv); + +struct TutorialBenchmark +{ + static bool benchmark(int argc, char** argv) { + for (int i = 0; i < argc; ++i) + if (std::string(argv[i]) == "--benchmark") + return true; + return false; + } + + TutorialBenchmark(BenchFunc func) : + commandLineParser(CommandLineParser(CommandLineParser::SILENT)), + func(func) + { + commandLineParser.registerOption("help", [this] (Ref cin, const FileName& path) { + commandLineParser.printCommandLineHelp(); + exit(1); + }, "--help: prints help for all supported command line options"); + commandLineParser.registerOption("i", [&] (Ref cin, const FileName& path) { + inputFile = cin->getString(); + }, "-i : .xml "); + commandLineParser.registerOption("c", [&] (Ref cin, const FileName& path) { + inputFile = cin->getString(); + }, "-c : .ecs "); + commandLineParser.registerOption("benchmark", [&] (Ref cin, const FileName& path) { + params.skipIterations = cin->getInt(); + params.minTimeOrIterations = cin->getInt(); + processedCommandLineOptions.push_back("--benchmark"); + }, "--benchmark : run benchmark for M seconds (M iterations in legacy mode) with N iterations warm-up"); + commandLineParser.registerOption("legacy", [&] (Ref cin, const FileName& path) { + params.legacy = true; + processedCommandLineOptions.push_back("--legacy"); + }, "--legacy: run old benchmark version (without google benchmark)"); + commandLineParser.registerOption("benchmark_repetitions", [&] (Ref cin, const FileName& path) { + params.repetitions = cin->getInt(); + processedCommandLineOptions.push_back("--benchmark_repetitions"); + }, "--benchmark_repetitions : run R repetitions when using google benchmark"); + commandLineParser.registerOption("benchmark_name", [&] (Ref cin, const FileName& path) { + params.name = cin->getString(); + processedCommandLineOptions.push_back("--benchmark_name"); + }, "--benchmark_name : override name of the benchmark"); + } + + TutorialBenchmark() : TutorialBenchmark(nullptr) + { + } + + int main(int argc, char** argv, std::string name = "default"); + +protected: + CommandLineParser commandLineParser; + + // remove the processed commdand line options + void updateCommandLine(int& argc, char** argv); + virtual void postParseCommandLine(); + + std::string inputFile = ""; + std::vector processedCommandLineOptions; + BenchParams params; + + virtual void registerBenchmark(std::string const& name, int argc, char** argv); + +private: + BenchFunc func; +}; + +struct TutorialBuildBenchmark : public TutorialBenchmark +{ + TutorialBuildBenchmark(BuildBenchFunc func) : TutorialBenchmark(), buildBenchFunc(func) + { + commandLineParser.registerOption("benchmark_type", [&] (Ref cin, const FileName& path) { + std::string str = cin->getString(); + buildParams.buildBenchType = getBuildBenchType(str); + processedCommandLineOptions.push_back("--benchmark_type"); + }, "--benchmark_type : select which build types to benchmark"); + commandLineParser.registerOption("user_threads", [this] (Ref cin, const FileName& path) { + buildParams.userThreads = cin->getInt(); + }, "--user_threads : invokes user thread benchmark with specified number of application provided build threads"); + } + +private: + void postParseCommandLine() override; + + void registerBenchmark(std::string const& name, int argc, char** argv) override; + void registerBuildBenchmark(std::string name, BuildBenchType buildBenchType, int argc, char** argv); + + BuildBenchParams buildParams; + BuildBenchFunc buildBenchFunc; +}; + +} \ No newline at end of file diff --git a/tutorials/common/tutorial/benchmark_render.h b/tutorials/common/tutorial/benchmark_render.h new file mode 100644 index 0000000000..4630b9f808 --- /dev/null +++ b/tutorials/common/tutorial/benchmark_render.h @@ -0,0 +1,145 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "tutorial.h" +#include "statistics.h" +#include "benchmark.h" + +#ifdef USE_GOOGLE_BENCHMARK +#include +#endif + +/* ray statistics */ +#if !defined(TASKING_PPL) // not supported with PPL because threadIndex is not unique and atomics are too expensive +#define RAY_STATS +#endif + +namespace embree +{ + +template +static void renderBenchmarkLegacy(BenchState& state, BenchParams& params ,int argc, char** argv); + +template +static void renderBenchFunc(BenchState& state, BenchParams& params ,int argc, char** argv) +{ +#ifdef USE_GOOGLE_BENCHMARK + if (params.legacy) { + renderBenchmarkLegacy(state, params, argc, argv); + return; + } + + Tutorial tutorial; + tutorial.interactive = false; + tutorial.main(argc,argv); + + tutorial.resize(tutorial.width, tutorial.height); + ISPCCamera ispccamera = tutorial.camera.getISPCCamera(tutorial.width, tutorial.height); + + for (size_t i = 0; i < params.skipIterations; i++) + { + tutorial.initRayStats(); + tutorial.render(tutorial.pixels,tutorial.width,tutorial.height,0.0f,ispccamera); + } + + size_t numRays = 0; + for (auto _ : *state.state) + { + tutorial.initRayStats(); + tutorial.render(tutorial.pixels,tutorial.width,tutorial.height,0.0f,ispccamera); + numRays += tutorial.getNumRays(); + } + + state.state->SetItemsProcessed(state.state->iterations()); + state.state->counters["Rays/s"] = benchmark::Counter(numRays, benchmark::Counter::kIsRate); +#else + renderBenchmarkLegacy(state, params, argc, argv); +#endif +} + +template +static void renderBenchmarkLegacy(BenchState& state, BenchParams& params ,int argc, char** argv) +{ + Tutorial tutorial; + tutorial.interactive = false; + tutorial.main(argc,argv); + + tutorial.resize(tutorial.width, tutorial.height); + ISPCCamera ispccamera = tutorial.camera.getISPCCamera(tutorial.width, tutorial.height); + + IOStreamStateRestorer cout_state(std::cout); + std::cout.setf(std::ios::fixed, std::ios::floatfield); + std::cout.precision(4); + + //Statistics stat; + FilteredStatistics fpsStat(0.5f,0.0f); + FilteredStatistics mraypsStat(0.5f,0.0f); + { + size_t numTotalFrames = params.skipIterations + params.minTimeOrIterations; + for (size_t i=0; i= 1024 && (i % 64 == 0)) + { + double rate = 0; + if (fpsStat.getAvg()) rate = 100.0f*fpsStat.getSigma()/fpsStat.getAvg(); + + std::cout << "frame [" << std::setw(3) << i << " / " << std::setw(3) << numTotalFrames << "]: " + << std::setw(8) << fps << " fps, " + << "min = " << std::setw(8) << fpsStat.getMin() << " fps, " + << "avg = " << std::setw(8) << fpsStat.getAvg() << " fps, " + << "max = " << std::setw(8) << fpsStat.getMax() << " fps, " + << "sigma = " << std::setw(6) << fpsStat.getSigma() << " (" << rate << "%)" << std::endl << std::flush; + } + } + + double rate = 0; + if (fpsStat.getAvg()) rate = 100.0f*fpsStat.getAvgSigma()/fpsStat.getAvg(); + + std::cout << "frame [" << std::setw(3) << params.skipIterations << " - " << std::setw(3) << numTotalFrames << "]: " + << " " + << "min = " << std::setw(8) << fpsStat.getMin() << " fps, " + << "avg = " << std::setw(8) << fpsStat.getAvg() << " fps, " + << "max = " << std::setw(8) << fpsStat.getMax() << " fps, " + << "sigma = " << std::setw(6) << fpsStat.getAvgSigma() << " (" << rate << "%)" << std::endl; + } + + std::cout << "BENCHMARK_RENDER_MIN " << fpsStat.getMin() << std::endl; + std::cout << "BENCHMARK_RENDER_AVG " << fpsStat.getAvg() << std::endl; + std::cout << "BENCHMARK_RENDER_MAX " << fpsStat.getMax() << std::endl; + std::cout << "BENCHMARK_RENDER_SIGMA " << fpsStat.getSigma() << std::endl; + std::cout << "BENCHMARK_RENDER_AVG_SIGMA " << fpsStat.getAvgSigma() << std::endl; + +#if defined(RAY_STATS) + std::cout << "BENCHMARK_RENDER_MRAYPS_MIN " << mraypsStat.getMin() << std::endl; + std::cout << "BENCHMARK_RENDER_MRAYPS_AVG " << mraypsStat.getAvg() << std::endl; + std::cout << "BENCHMARK_RENDER_MRAYPS_MAX " << mraypsStat.getMax() << std::endl; + std::cout << "BENCHMARK_RENDER_MRAYPS_SIGMA " << mraypsStat.getSigma() << std::endl; + std::cout << "BENCHMARK_RENDER_MRAYPS_AVG_SIGMA " << mraypsStat.getAvgSigma() << std::endl; +#endif + + std::cout << std::flush; +} + +} \ No newline at end of file diff --git a/tutorials/common/tutorial/camera.h b/tutorials/common/tutorial/camera.h index 5844ddf802..6ec686da1b 100644 --- a/tutorials/common/tutorial/camera.h +++ b/tutorials/common/tutorial/camera.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,6 +8,7 @@ #include "../../../common/math/math.h" #include "../../../common/math/vec3.h" #include "../../../common/math/affinespace.h" +#include "../scenegraph/scenegraph.h" #include namespace embree @@ -35,9 +36,12 @@ namespace embree Camera () : from(0.0001f,0.0001f,-3.0f), to(0,0,0), up(0,1,0), fov(90), handedness(RIGHT_HANDED) {} - Camera (Vec3fa& from, Vec3fa& to, Vec3fa& up, float fov, Handedness handedness) + Camera (const Vec3fa& from, const Vec3fa& to, const Vec3fa& up, float fov, Handedness handedness) : from(from), to(to), up(up), fov(fov), handedness(handedness) {} + Camera (const SceneGraph::PerspectiveCameraData& cam, Handedness handedness) + : from(cam.from), to(cam.to), up(cam.up), fov(cam.fov), handedness(handedness) {} + std::string str() const { std::stringstream stream; @@ -65,7 +69,7 @@ namespace embree Vec3fa world2camera(const Vec3fa& p) { return xfmPoint(world2camera(),p); } Vec3fa camera2world(const Vec3fa& p) { return xfmPoint(camera2world(),p); } - ISPCCamera getISPCCamera (size_t width, size_t height, bool flip_y = false) + ISPCCamera getISPCCamera (size_t width, size_t height) { const float fovScale = 1.0f/tanf(deg2rad(0.5f*fov)); const AffineSpace3fa local2world = camera2world(); @@ -73,10 +77,6 @@ namespace embree Vec3fa vy = -local2world.l.vy; Vec3fa vz = -0.5f*width*local2world.l.vx + 0.5f*height*local2world.l.vy + 0.5f*height*fovScale*local2world.l.vz; Vec3fa p = local2world.p; - if (flip_y) { - vz = vz+float(height)*vy; - vy = -vy; - } return ISPCCamera(AffineSpace3fa(vx,vy,vz,p)); } diff --git a/tutorials/common/tutorial/camera.isph b/tutorials/common/tutorial/camera.isph index 5edbe45301..008f44db7c 100644 --- a/tutorials/common/tutorial/camera.isph +++ b/tutorials/common/tutorial/camera.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/tutorial/noise.cpp b/tutorials/common/tutorial/noise.cpp index 25e252d66c..6b0f8a9dc9 100644 --- a/tutorials/common/tutorial/noise.cpp +++ b/tutorials/common/tutorial/noise.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "noise.h" diff --git a/tutorials/common/tutorial/noise.h b/tutorials/common/tutorial/noise.h index 76f7d6cf5f..347056022d 100644 --- a/tutorials/common/tutorial/noise.h +++ b/tutorials/common/tutorial/noise.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/tutorial/noise.ispc b/tutorials/common/tutorial/noise.ispc index e80fd2d74c..d853f70977 100644 --- a/tutorials/common/tutorial/noise.ispc +++ b/tutorials/common/tutorial/noise.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "noise.isph" diff --git a/tutorials/common/tutorial/noise.isph b/tutorials/common/tutorial/noise.isph index 1aef224e8a..56c116ebdb 100644 --- a/tutorials/common/tutorial/noise.isph +++ b/tutorials/common/tutorial/noise.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/tutorial/optics.h b/tutorials/common/tutorial/optics.h index 5bd861f945..2c1c50158d 100644 --- a/tutorials/common/tutorial/optics.h +++ b/tutorials/common/tutorial/optics.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/tutorial/optics.isph b/tutorials/common/tutorial/optics.isph index 99363347fa..79d1a17b05 100644 --- a/tutorials/common/tutorial/optics.isph +++ b/tutorials/common/tutorial/optics.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/common/tutorial/scene.cpp b/tutorials/common/tutorial/scene.cpp index 879f8783f3..231cb9dead 100644 --- a/tutorials/common/tutorial/scene.cpp +++ b/tutorials/common/tutorial/scene.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene.h" @@ -18,30 +18,17 @@ namespace embree for (auto& node : group->children) { if (Ref lightNode = node.dynamicCast()) { - lights.push_back(lightNode->light); + lights.push_back(lightNode); } - else if (Ref xfmNode = node.dynamicCast()) { - addGeometry(xfmNode->child); - addGeometry(node); - } else if (Ref cameraNode = node.dynamicCast()) { cameras.push_back(cameraNode); } else { - addGeometry(node); + geometries.push_back(node); } } } - - unsigned TutorialScene::addGeometry(Ref node) - { - if (node->id == -1) { - geometries.push_back(node); - node->id = unsigned(geometries.size()-1); - } - return node->id; - } - + unsigned TutorialScene::materialID(Ref material) { if (material->id == -1) { @@ -51,12 +38,6 @@ namespace embree return material->id; } - unsigned TutorialScene::geometryID(Ref geometry) - { - assert(geometry->id != -1); - return geometry->id; - } - void TutorialScene::print_camera_names () { if (cameras.size() == 0) { diff --git a/tutorials/common/tutorial/scene.h b/tutorials/common/tutorial/scene.h index 1fabe55607..13caf0f558 100644 --- a/tutorials/common/tutorial/scene.h +++ b/tutorials/common/tutorial/scene.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -29,9 +29,7 @@ namespace embree ~TutorialScene(); void add (Ref node); - unsigned addGeometry(Ref node); unsigned materialID(Ref material); - unsigned geometryID(Ref geometry); void print_camera_names (); Ref getDefaultCamera(); Ref getCamera(const std::string& name); @@ -40,6 +38,6 @@ namespace embree std::vector> cameras; //!< list of all cameras std::vector> materials; //!< list of materials std::vector > geometries; //!< list of geometries - std::vector> lights; //!< list of lights + std::vector> lights; //!< list of lights }; } diff --git a/tutorials/common/tutorial/scene_device.cpp b/tutorials/common/tutorial/scene_device.cpp index 9625e2046a..1a0eaf26a9 100644 --- a/tutorials/common/tutorial/scene_device.cpp +++ b/tutorials/common/tutorial/scene_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_device.h" @@ -11,10 +11,16 @@ namespace embree extern "C" { int g_instancing_mode = SceneGraph::INSTANCING_NONE; float g_min_width_max_radius_scale = 1.0f; + AssignShaderTy assignShadersFunc = nullptr; } + extern "C" int g_animation_mode; + void deleteGeometry(ISPCGeometry* geom) { + if (geom == nullptr) + return; + switch (geom->type) { case TRIANGLE_MESH: delete (ISPCTriangleMesh*) geom; break; case SUBDIV_MESH : delete (ISPCSubdivMesh*) geom; break; @@ -28,11 +34,14 @@ namespace embree } } - ISPCScene::ISPCScene(TutorialScene* in) + ISPCScene::ISPCScene(RTCDevice device, TutorialScene* in) + : scene(rtcNewScene(device)), tutorialScene(in) { + SceneGraph::opaque_geometry_destruction = (void(*)(void*)) deleteGeometry; + geometries = new ISPCGeometry*[in->geometries.size()]; for (size_t i=0; igeometries.size(); i++) - geometries[i] = convertGeometry(in,in->geometries[i]); + geometries[i] = convertGeometry(device,in,in->geometries[i]); numGeometries = unsigned(in->geometries.size()); materials = new ISPCMaterial*[in->materials.size()]; @@ -44,17 +53,13 @@ namespace embree numLights = 0; for (size_t i=0; ilights.size(); i++) { - Light* light = convertLight(in->lights[i]); + Light* light = convertLight(in->lights[i]->get(0.0f)); if (light) lights[numLights++] = light; } } ISPCScene::~ISPCScene() { - /* delete all geometries */ - for (size_t i=0; i in) + Light* ISPCScene::convertLight(Ref in) { - void* out = 0; - - switch (in->getType()) - { - case SceneGraph::LIGHT_AMBIENT: - { - Ref inAmbient = in.dynamicCast(); - out = AmbientLight_create(); - AmbientLight_set(out, inAmbient->L); - break; - } - case SceneGraph::LIGHT_DIRECTIONAL: - { - Ref inDirectional = in.dynamicCast(); - out = DirectionalLight_create(); - DirectionalLight_set(out, -normalize(inDirectional->D), inDirectional->E, 1.0f); - break; - } - case SceneGraph::LIGHT_DISTANT: - { - Ref inDistant = in.dynamicCast(); - out = DirectionalLight_create(); - DirectionalLight_set(out, - -normalize(inDistant->D), - inDistant->L * rcp(uniformSampleConePDF(inDistant->cosHalfAngle)), - inDistant->cosHalfAngle); - break; - } - case SceneGraph::LIGHT_POINT: - { - Ref inPoint = in.dynamicCast(); - out = PointLight_create(); - PointLight_set(out, inPoint->P, inPoint->I, 0.f); - break; - } - case SceneGraph::LIGHT_SPOT: - case SceneGraph::LIGHT_TRIANGLE: - case SceneGraph::LIGHT_QUAD: + Light* l = createLight(in); + updateLight(in->get(0.0f),l); + return l; + } + + template<> void ISPCScene::updateLight(const SceneGraph::AmbientLight& in, Light* out) { + AmbientLight_set(out, in.L); + } + + template<> void ISPCScene::updateLight(const SceneGraph::DirectionalLight& in, Light* out) { + DirectionalLight_set(out, -normalize(in.D), in.E, 1.0f); + } + + template<> void ISPCScene::updateLight(const SceneGraph::DistantLight& in, Light* out) + { + DirectionalLight_set(out, + -normalize(in.D), + in.L * rcp(uniformSampleConePDF(in.cosHalfAngle)), + in.cosHalfAngle); + } + + template<> void ISPCScene::updateLight(const SceneGraph::PointLight& in, Light* out) { + PointLight_set(out, in.P, in.I, 0.f); + } + + Light* ISPCScene::createLight(Ref in) + { + switch (in->getType()) { + case SceneGraph::LIGHT_AMBIENT : return (Light*) AmbientLight_create(); + case SceneGraph::LIGHT_DIRECTIONAL: return (Light*) DirectionalLight_create(); + case SceneGraph::LIGHT_DISTANT : return (Light*) DirectionalLight_create(); + case SceneGraph::LIGHT_POINT : return (Light*) PointLight_create(); + case SceneGraph::LIGHT_SPOT : return nullptr; + case SceneGraph::LIGHT_TRIANGLE : return nullptr; + case SceneGraph::LIGHT_QUAD : return nullptr; + default : THROW_RUNTIME_ERROR("unknown light type"); + } + return nullptr; + } + + void ISPCScene::updateLight(const Ref& in, Light* out) + { + if (auto light = in.dynamicCast>()) + updateLight(light->light, out); + else if (auto light = in.dynamicCast>()) + updateLight(light->light, out); + else if (auto light = in.dynamicCast>()) + updateLight(light->light, out); + else if (auto light = in.dynamicCast>()) + updateLight(light->light, out); + } + + void ISPCScene::commit() + { + for (unsigned int geomID=0; geomIDgeometry,geomID); } - - return (Light*)out; + + rtcCommitScene(scene); } - ISPCTriangleMesh::ISPCTriangleMesh (TutorialScene* scene_in, Ref in) + ISPCTriangleMesh::ISPCTriangleMesh (RTCDevice device, TutorialScene* scene_in, Ref in) : geom(TRIANGLE_MESH), positions(nullptr), normals(nullptr) { + geom.geometry = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_TRIANGLE); + positions = new Vec3fa*[in->numTimeSteps()]; for (size_t i=0; inumTimeSteps(); i++) positions[i] = in->positions[i].data(); @@ -141,10 +161,28 @@ namespace embree if (positions) delete[] positions; if (normals) delete[] normals; } + + void ISPCTriangleMesh::commit() + { + RTCGeometry g = geom.geometry; + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + + for (unsigned int t=0; t in) + ISPCQuadMesh::ISPCQuadMesh (RTCDevice device, TutorialScene* scene_in, Ref in) : geom(QUAD_MESH), positions(nullptr), normals(nullptr) { + geom.geometry = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_QUAD); + positions = new Vec3fa*[in->numTimeSteps()]; for (size_t i=0; inumTimeSteps(); i++) positions[i] = in->positions[i].data(); @@ -170,10 +208,27 @@ namespace embree if (normals) delete[] normals; } - - ISPCGridMesh::ISPCGridMesh (TutorialScene* scene_in, Ref in) + void ISPCQuadMesh::commit() + { + RTCGeometry g = geom.geometry; + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + + for (unsigned int t=0; t in) : geom(GRID_MESH), positions(nullptr) { + geom.geometry = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_GRID); + positions = new Vec3fa*[in->numTimeSteps()]; for (size_t i=0; inumTimeSteps(); i++) positions[i] = in->positions[i].data(); @@ -191,10 +246,27 @@ namespace embree if (positions) delete[] positions; } - - ISPCSubdivMesh::ISPCSubdivMesh (TutorialScene* scene_in, Ref in) + void ISPCGridMesh::commit() + { + RTCGeometry g = geom.geometry; + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + + for (unsigned int t=0; t in) : geom(SUBDIV_MESH), positions(nullptr), normals(nullptr) { + geom.geometry = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION); + positions = new Vec3fa*[in->numTimeSteps()]; for (size_t i=0; inumTimeSteps(); i++) positions[i] = in->positions[i].data(); @@ -250,10 +322,64 @@ namespace embree if (subdivlevel) delete[] subdivlevel; if (face_offsets) delete[] face_offsets; } + + void ISPCSubdivMesh::commit() + { + RTCGeometry g = geom.geometry; + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + + for (unsigned int i=0; i in) + ISPCHairSet::ISPCHairSet (RTCDevice device, TutorialScene* scene_in, RTCGeometryType type, Ref in) : geom(CURVES), normals(nullptr), tangents(nullptr), dnormals(nullptr), hairs(nullptr), flags(nullptr), type(type) { + geom.geometry = rtcNewGeometry(device, type); + positions = new Vec3fa*[in->numTimeSteps()]; for (size_t i=0; inumTimeSteps(); i++) positions[i] = (Vec3fa*) in->positions[i].data(); @@ -297,9 +423,58 @@ namespace embree delete[] dnormals; } - ISPCPointSet::ISPCPointSet (TutorialScene* scene_in, RTCGeometryType type, Ref in) + void ISPCHairSet::commit() + { + RTCGeometry g = geom.geometry; + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + + for (unsigned int t=0; t= 1.0f) + rtcSetGeometryMaxRadiusScale(g,g_min_width_max_radius_scale); +#endif + + if (flags) { + rtcSetSharedGeometryBuffer(g, RTC_BUFFER_TYPE_FLAGS, 0, RTC_FORMAT_UCHAR, flags, 0, sizeof(unsigned char), numHairs); + } + rtcSetGeometryUserData(g, this); + + if (assignShadersFunc) assignShadersFunc(&geom); + rtcCommitGeometry(g); + } + + ISPCPointSet::ISPCPointSet (RTCDevice device, TutorialScene* scene_in, RTCGeometryType type, Ref in) : geom(POINTS), positions(nullptr), normals(nullptr), type(type) { + geom.geometry = rtcNewGeometry(device, type); + positions = new Vec3fa*[in->numTimeSteps()]; for (size_t i=0; inumTimeSteps(); i++) positions[i] = (Vec3fa*) in->positions[i].data(); @@ -310,6 +485,8 @@ namespace embree normals[i] = in->normals[i].data(); } + startTime = in->time_range.lower; + endTime = in->time_range.upper; numTimeSteps = (unsigned) in->numTimeSteps(); numVertices = (unsigned) in->numVertices(); geom.materialID = scene_in->materialID(in->material); @@ -320,63 +497,146 @@ namespace embree if (normals) delete[] normals; } + void ISPCPointSet::commit() + { + RTCGeometry g = geom.geometry; + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + + for (unsigned int t=0; t= 1.0f) + rtcSetGeometryMaxRadiusScale(g,g_min_width_max_radius_scale); +#endif + + rtcSetGeometryUserData(g, this); + + if (assignShadersFunc) assignShadersFunc(&geom); + rtcCommitGeometry(g); + } - ISPCInstance::ISPCInstance (TutorialScene* scene, Ref in) - : geom(INSTANCE), numTimeSteps(unsigned(in->spaces.size())) + ISPCInstance::ISPCInstance (RTCDevice device, TutorialScene* scene, Ref in) + : geom(INSTANCE), child(nullptr), startTime(0.0f), endTime(1.0f), numTimeSteps(1), quaternion(false), spaces(nullptr) { - spaces = (AffineSpace3fa*) alignedMalloc(in->spaces.size()*sizeof(AffineSpace3fa),16); - geom.geomID = scene->geometryID(in->child); - child = ISPCScene::convertGeometry(scene,in->child); - startTime = in->spaces.time_range.lower; - endTime = in->spaces.time_range.upper; - quaternion = in->spaces.quaternion; - for (size_t i=0; ispaces[i]; + geom.geometry = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_INSTANCE); + + if (g_animation_mode) + { + spaces = (AffineSpace3fa*) alignedMalloc(sizeof(AffineSpace3fa),16); + child = ISPCScene::convertGeometry(device,scene,in->child); + spaces[0] = in->get(0.0f); + } + else + { + spaces = (AffineSpace3fa*) alignedMalloc(in->spaces.size()*sizeof(AffineSpace3fa),16); + child = ISPCScene::convertGeometry(device,scene,in->child); + startTime = in->spaces.time_range.lower; + endTime = in->spaces.time_range.upper; + numTimeSteps = unsigned(in->spaces.size()); + quaternion = in->spaces.quaternion; + for (size_t i=0; ispaces[i]; + } } ISPCInstance::~ISPCInstance() { alignedFree(spaces); } - ISPCGroup::ISPCGroup (TutorialScene* scene, Ref in) - : geom(GROUP) + void ISPCInstance::commit() + { + if (child->type != GROUP) + THROW_RUNTIME_ERROR("invalid scene structure"); + + ISPCGroup* group = (ISPCGroup*) child; + RTCScene scene_inst = group->scene; + + if (numTimeSteps == 1 || g_animation_mode) + { + RTCGeometry g = geom.geometry; + rtcSetGeometryInstancedScene(g,scene_inst); + rtcSetGeometryTimeStepCount(g,1); + if (quaternion) { + QuaternionDecomposition qd = quaternionDecomposition(spaces[0]); + rtcSetGeometryTransformQuaternion(g,0,(RTCQuaternionDecomposition*)&qd); + } else { + rtcSetGeometryTransform(g,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,&spaces[0].l.vx.x); + } + rtcSetGeometryUserData(g, this); + rtcCommitGeometry(g); + } + else + { + RTCGeometry g = geom.geometry; + rtcSetGeometryInstancedScene(g,scene_inst); + rtcSetGeometryTimeStepCount(g,numTimeSteps); + rtcSetGeometryTimeRange(g,startTime,endTime); + for (size_t t=0; t in) + : geom(GROUP), scene(rtcNewScene(device)), requiredInstancingDepth(0) { numGeometries = (unsigned int) in->size(); geometries = new ISPCGeometry*[numGeometries]; for (size_t i=0; ichild(i)); + geometries[i] = ISPCScene::convertGeometry(device,scene,in->child(i)); } ISPCGroup::~ISPCGroup() { - for (size_t i=0; igeometry,geomID); + } + rtcCommitScene(scene); } - ISPCGeometry* ISPCScene::convertGeometry (TutorialScene* scene, Ref in) + ISPCGeometry* ISPCScene::convertGeometry (RTCDevice device, TutorialScene* scene, Ref in) { ISPCGeometry* geom = nullptr; if (in->geometry) return (ISPCGeometry*) in->geometry; else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCTriangleMesh(scene,mesh); + geom = (ISPCGeometry*) new ISPCTriangleMesh(device,scene,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCQuadMesh(scene,mesh); + geom = (ISPCGeometry*) new ISPCQuadMesh(device,scene,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCSubdivMesh(scene,mesh); + geom = (ISPCGeometry*) new ISPCSubdivMesh(device,scene,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCHairSet(scene,mesh->type,mesh); + geom = (ISPCGeometry*) new ISPCHairSet(device,scene,mesh->type,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCGridMesh(scene,mesh); + geom = (ISPCGeometry*) new ISPCGridMesh(device,scene,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCInstance(scene,mesh); + geom = (ISPCGeometry*) new ISPCInstance(device,scene,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCGroup(scene,mesh); + geom = (ISPCGeometry*) new ISPCGroup(device,scene,mesh); else if (Ref mesh = in.dynamicCast()) - geom = (ISPCGeometry*) new ISPCPointSet(scene, mesh->type, mesh); + geom = (ISPCGeometry*) new ISPCPointSet(device,scene, mesh->type, mesh); else THROW_RUNTIME_ERROR("unknown geometry type"); @@ -384,320 +644,165 @@ namespace embree return geom; } - unsigned int ConvertTriangleMesh(RTCDevice device, ISPCTriangleMesh* mesh, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) + void ConvertTriangleMesh(RTCDevice device, ISPCTriangleMesh* mesh, RTCBuildQuality quality, RTCSceneFlags flags) { - RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_TRIANGLE); - rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps); - rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime); - rtcSetGeometryBuildQuality(geom, quality); - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, mesh->triangles, 0, sizeof(ISPCTriangle), mesh->numTriangles); - rtcSetGeometryUserData(geom, mesh); - rtcCommitGeometry(geom); - rtcAttachGeometryByID(scene_out,geom,geomID); - mesh->geom.geometry = geom; - mesh->geom.scene = scene_out; - mesh->geom.geomID = geomID; - return geomID; + if (mesh->geom.visited) return; + mesh->geom.visited = true; + rtcSetGeometryBuildQuality(mesh->geom.geometry, quality); + mesh->commit(); } - unsigned int ConvertQuadMesh(RTCDevice device, ISPCQuadMesh* mesh, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) - { - RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_QUAD); - rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps); - rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime); - rtcSetGeometryBuildQuality(geom, quality); - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT4, mesh->quads, 0, sizeof(ISPCQuad), mesh->numQuads); - rtcSetGeometryUserData(geom, mesh); - rtcCommitGeometry(geom); - rtcAttachGeometryByID(scene_out,geom,geomID); - mesh->geom.geometry = geom; - mesh->geom.scene = scene_out; - mesh->geom.geomID = geomID; - return geomID; - } - - unsigned int ConvertGridMesh(RTCDevice device, ISPCGridMesh* mesh, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) - { - RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_GRID); - rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps); - rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime); - rtcSetGeometryBuildQuality(geom, quality); - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_GRID, 0, RTC_FORMAT_GRID, mesh->grids, 0, sizeof(ISPCGrid), mesh->numGrids); - rtcSetGeometryUserData(geom, mesh); - rtcCommitGeometry(geom); - rtcAttachGeometryByID(scene_out,geom,geomID); - mesh->geom.geometry = geom; - mesh->geom.scene = scene_out; - mesh->geom.geomID = geomID; - return geomID; + void ConvertQuadMesh(RTCDevice device, ISPCQuadMesh* mesh, RTCBuildQuality quality, RTCSceneFlags flags) + { + if (mesh->geom.visited) return; + mesh->geom.visited = true; + rtcSetGeometryBuildQuality(mesh->geom.geometry, quality); + mesh->commit(); + } + + void ConvertGridMesh(RTCDevice device, ISPCGridMesh* mesh, RTCBuildQuality quality, RTCSceneFlags flags) + { + if (mesh->geom.visited) return; + mesh->geom.visited = true; + rtcSetGeometryBuildQuality(mesh->geom.geometry, quality); + mesh->commit(); } - unsigned int ConvertSubdivMesh(RTCDevice device, ISPCSubdivMesh* mesh, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) + void ConvertSubdivMesh(RTCDevice device, ISPCSubdivMesh* mesh, RTCBuildQuality quality, RTCSceneFlags flags) { - RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION); - rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps); - rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime); - rtcSetGeometryBuildQuality(geom, quality); - for (unsigned int i=0; inumEdges; i++) mesh->subdivlevel[i] = FIXED_EDGE_TESSELLATION_VALUE; - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_LEVEL, 0, RTC_FORMAT_FLOAT, mesh->subdivlevel, 0, sizeof(float), mesh->numEdges); - - /* create geometry topology */ - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, mesh->position_indices, 0, sizeof(unsigned int), mesh->numEdges); - rtcSetGeometrySubdivisionMode(geom, 0, mesh->position_subdiv_mode); - - /* set normal buffers and optionally normal topology */ - if (mesh->normals) { - rtcSetGeometryVertexAttributeCount(geom,2); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, 1, RTC_FORMAT_FLOAT3, mesh->normals[0], 0, sizeof(Vec3fa), mesh->numNormals); - if (mesh->normal_indices) { - rtcSetGeometryTopologyCount(geom,2); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 1, RTC_FORMAT_UINT, mesh->normal_indices, 0, sizeof(unsigned int), mesh->numEdges); - rtcSetGeometryVertexAttributeTopology(geom, 1, 1); - rtcSetGeometrySubdivisionMode(geom, 1, mesh->normal_subdiv_mode); - } - } - - /* set texcoord buffer and optionally texcoord topology */ - if (mesh->texcoords) { - rtcSetGeometryVertexAttributeCount(geom,3); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, 2, RTC_FORMAT_FLOAT2, mesh->texcoords, 0, sizeof(Vec2f), mesh->numTexCoords); - if (mesh->texcoord_indices) { - rtcSetGeometryTopologyCount(geom,3); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 2, RTC_FORMAT_UINT, mesh->texcoord_indices, 0, sizeof(unsigned int), mesh->numEdges); - rtcSetGeometryVertexAttributeTopology(geom, 2, 2); - rtcSetGeometrySubdivisionMode(geom, 2, mesh->texcoord_subdiv_mode); - } - } - - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_FACE, 0, RTC_FORMAT_UINT, mesh->verticesPerFace, 0, sizeof(unsigned int), mesh->numFaces); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_HOLE, 0, RTC_FORMAT_UINT, mesh->holes, 0, sizeof(unsigned int), mesh->numHoles); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_EDGE_CREASE_INDEX, 0, RTC_FORMAT_UINT2, mesh->edge_creases, 0, 2*sizeof(unsigned int), mesh->numEdgeCreases); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT, 0, RTC_FORMAT_FLOAT, mesh->edge_crease_weights, 0, sizeof(float), mesh->numEdgeCreases); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX, 0, RTC_FORMAT_UINT, mesh->vertex_creases, 0, sizeof(unsigned int), mesh->numVertexCreases); - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT, 0, RTC_FORMAT_FLOAT, mesh->vertex_crease_weights, 0, sizeof(float), mesh->numVertexCreases); - rtcSetGeometryUserData(geom, mesh); - rtcCommitGeometry(geom); - - rtcAttachGeometryByID(scene_out,geom,geomID); - mesh->geom.geometry = geom; - mesh->geom.scene = scene_out; - mesh->geom.geomID = geomID; - return geomID; + if (mesh->geom.visited) return; + mesh->geom.visited = true; + rtcSetGeometryBuildQuality(mesh->geom.geometry, quality); + mesh->commit(); } - unsigned int ConvertCurveGeometry(RTCDevice device, ISPCHairSet* mesh, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) + void ConvertCurveGeometry(RTCDevice device, ISPCHairSet* mesh, RTCBuildQuality quality, RTCSceneFlags flags) { - RTCGeometry geom = rtcNewGeometry(device, mesh->type); - rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps); - rtcSetGeometryTimeRange(geom,mesh->startTime,mesh->endTime); - rtcSetGeometryBuildQuality(geom, quality); + if (mesh->geom.visited) return; + mesh->geom.visited = true; + rtcSetGeometryBuildQuality(mesh->geom.geometry, quality); + mesh->commit(); + } - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - - if (mesh->normals) { - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_NORMAL, t, RTC_FORMAT_FLOAT3, mesh->normals[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - } + void ConvertPoints(RTCDevice device, ISPCPointSet* mesh, RTCBuildQuality quality, RTCSceneFlags flags) + { + if (mesh->geom.visited) return; + mesh->geom.visited = true; + rtcSetGeometryBuildQuality(mesh->geom.geometry, quality); + mesh->commit(); + } + + unsigned int ConvertInstance(RTCDevice device, ISPCInstance* instance, RTCBuildQuality quality, RTCSceneFlags flags, unsigned int depth); + + unsigned int ConvertGroup(RTCDevice device, ISPCGroup* group, RTCBuildQuality quality, RTCSceneFlags flags, unsigned int depth) + { + if (group->geom.visited) return group->requiredInstancingDepth; + group->geom.visited = true; - if (mesh->tangents) { - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_TANGENT, t, RTC_FORMAT_FLOAT4, mesh->tangents[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - } + RTCScene scene = group->scene; + rtcSetSceneFlags(scene, flags); - if (mesh->dnormals) { - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_NORMAL_DERIVATIVE, t, RTC_FORMAT_FLOAT3, mesh->dnormals[t], 0, sizeof(Vec3fa), mesh->numVertices); + unsigned int requiredInstancingDepth = 0; + for (unsigned int geomID=0; geomIDnumGeometries; geomID++) + { + ISPCGeometry* geometry = group->geometries[geomID]; + if (geometry->type == SUBDIV_MESH) + ConvertSubdivMesh(device,(ISPCSubdivMesh*) geometry, quality, flags); + else if (geometry->type == TRIANGLE_MESH) + ConvertTriangleMesh(device,(ISPCTriangleMesh*) geometry, quality, flags); + else if (geometry->type == QUAD_MESH) + ConvertQuadMesh(device,(ISPCQuadMesh*) geometry, quality, flags); + else if (geometry->type == CURVES) + ConvertCurveGeometry(device,(ISPCHairSet*) geometry, quality, flags); + else if (geometry->type == GRID_MESH) + ConvertGridMesh(device,(ISPCGridMesh*) geometry, quality, flags); + else if (geometry->type == POINTS) + ConvertPoints(device,(ISPCPointSet*) geometry, quality, flags); + else if (geometry->type == INSTANCE) { + unsigned int reqDepth = ConvertInstance(device,(ISPCInstance*) geometry, quality, flags, depth); + requiredInstancingDepth = max(requiredInstancingDepth, reqDepth); } + else + assert(false); } - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, mesh->hairs, 0, sizeof(ISPCHair), mesh->numHairs); - if (mesh->type != RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE && mesh->type != RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) { - rtcSetGeometryTessellationRate(geom,(float)mesh->tessellation_rate); - } + group->commit(); -#if RTC_MIN_WIDTH - if (g_min_width_max_radius_scale >= 1.0f) - rtcSetGeometryMaxRadiusScale(geom,g_min_width_max_radius_scale); -#endif - - if (mesh->flags) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_FLAGS, 0, RTC_FORMAT_UCHAR, mesh->flags, 0, sizeof(unsigned char), mesh->numHairs); - } - rtcSetGeometryUserData(geom, mesh); - rtcCommitGeometry(geom); - - rtcAttachGeometryByID(scene_out,geom,geomID); - mesh->geom.geometry = geom; - mesh->geom.scene = scene_out; - mesh->geom.geomID = geomID; - return geomID; + group->requiredInstancingDepth = requiredInstancingDepth; + return requiredInstancingDepth; } - unsigned int ConvertPoints(RTCDevice device, ISPCPointSet* mesh, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) + unsigned int ConvertInstance(RTCDevice device, ISPCInstance* instance, RTCBuildQuality quality, RTCSceneFlags flags, unsigned int depth) { - RTCGeometry geom = rtcNewGeometry(device, mesh->type); - rtcSetGeometryTimeStepCount(geom,mesh->numTimeSteps); - rtcSetGeometryBuildQuality(geom, quality); + if (instance->child->type != GROUP) + THROW_RUNTIME_ERROR("invalid scene structure"); - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, mesh->positions[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - if (mesh->normals) { - for (unsigned int t=0; tnumTimeSteps; t++) { - rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_NORMAL, t, RTC_FORMAT_FLOAT3, mesh->normals[t], 0, sizeof(Vec3fa), mesh->numVertices); - } - } -#if RTC_MIN_WIDTH - if (g_min_width_max_radius_scale >= 1.0f) - rtcSetGeometryMaxRadiusScale(geom,g_min_width_max_radius_scale); -#endif - - rtcSetGeometryUserData(geom, mesh); - rtcCommitGeometry(geom); + ISPCGroup* group = (ISPCGroup*) instance->child; + unsigned int requiredInstancingDepth = 1+ConvertGroup(device, group, quality, flags, depth+1); - rtcAttachGeometryByID(scene_out,geom,geomID); - mesh->geom.geometry = geom; - mesh->geom.scene = scene_out; - mesh->geom.geomID = geomID; - return geomID; + if (depth + requiredInstancingDepth > RTC_MAX_INSTANCE_LEVEL_COUNT) + THROW_RUNTIME_ERROR("scene instancing depth is too large"); + + if (instance->geom.visited) return requiredInstancingDepth; + instance->geom.visited = true; + instance->commit(); + + return requiredInstancingDepth; } - void ConvertGroup(RTCDevice device, ISPCGroup* group, RTCBuildQuality quality, RTCScene scene_out, unsigned int geomID) + extern "C" RTCScene ConvertScene(RTCDevice g_device, ISPCScene* scene_in, RTCBuildQuality quality, RTCSceneFlags flags) { - for (unsigned int i=0; inumGeometries; i++) + RTCScene scene = scene_in->scene; + rtcSetSceneFlags(scene, flags); + + for (unsigned int geomID=0; geomIDnumGeometries; geomID++) { - ISPCGeometry* geometry = group->geometries[i]; + ISPCGeometry* geometry = scene_in->geometries[geomID]; if (geometry->type == SUBDIV_MESH) - ConvertSubdivMesh(device,(ISPCSubdivMesh*) geometry, quality, scene_out, i); + ConvertSubdivMesh(g_device,(ISPCSubdivMesh*) geometry, quality, flags); else if (geometry->type == TRIANGLE_MESH) - ConvertTriangleMesh(device,(ISPCTriangleMesh*) geometry, quality, scene_out, i); + ConvertTriangleMesh(g_device,(ISPCTriangleMesh*) geometry, quality, flags); else if (geometry->type == QUAD_MESH) - ConvertQuadMesh(device,(ISPCQuadMesh*) geometry, quality, scene_out, i); + ConvertQuadMesh(g_device,(ISPCQuadMesh*) geometry, quality, flags); else if (geometry->type == CURVES) - ConvertCurveGeometry(device,(ISPCHairSet*) geometry, quality, scene_out, i); + ConvertCurveGeometry(g_device,(ISPCHairSet*) geometry, quality, flags); else if (geometry->type == GRID_MESH) - ConvertGridMesh(device,(ISPCGridMesh*) geometry, quality, scene_out, i); + ConvertGridMesh(g_device,(ISPCGridMesh*) geometry, quality, flags); else if (geometry->type == POINTS) - ConvertPoints(device,(ISPCPointSet*) geometry, quality, scene_out, i); + ConvertPoints(g_device,(ISPCPointSet*) geometry, quality, flags); + else if (geometry->type == INSTANCE) + ConvertInstance(g_device, (ISPCInstance*) geometry, quality, flags, 0); else assert(false); - } - group->geom.geometry = nullptr; - group->geom.scene = scene_out; - group->geom.geomID = geomID; - } - unsigned int ConvertInstance(RTCDevice device, ISPCScene* scene_in, ISPCInstance* instance, RTCScene scene_out, unsigned int geomID) - { - RTCScene scene_inst = instance->child->scene; - if (instance->numTimeSteps == 1) { - RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(geom,scene_inst); - rtcSetGeometryTimeStepCount(geom,1); - if (instance->quaternion) { - QuaternionDecomposition qd = quaternionDecomposition(instance->spaces[0]); - rtcSetGeometryTransformQuaternion(geom,0,(RTCQuaternionDecomposition*)&qd); - } else { - rtcSetGeometryTransform(geom,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,&instance->spaces[0].l.vx.x); - } - rtcSetGeometryUserData(geom, instance); - rtcCommitGeometry(geom); - rtcAttachGeometryByID(scene_out,geom,geomID); - instance->geom.geometry = geom; - instance->geom.scene = scene_out; - instance->geom.geomID = geomID; - return geomID; - } - else - { - RTCGeometry geom = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(geom,scene_inst); - rtcSetGeometryTimeStepCount(geom,instance->numTimeSteps); - rtcSetGeometryTimeRange(geom,instance->startTime,instance->endTime); - for (size_t t=0; tnumTimeSteps; t++) { - if (instance->quaternion) { - QuaternionDecomposition qd = quaternionDecomposition(instance->spaces[t]); - rtcSetGeometryTransformQuaternion(geom,t,(RTCQuaternionDecomposition*)&qd); - } else { - rtcSetGeometryTransform(geom,(unsigned int)t,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,&instance->spaces[t].l.vx.x); - } - } - rtcSetGeometryUserData(geom, instance); - rtcCommitGeometry(geom); - rtcAttachGeometryByID(scene_out,geom,geomID); - instance->geom.geometry = geom; - instance->geom.scene = scene_out; - instance->geom.geomID = geomID; - return geomID; + rtcAttachGeometryByID(scene,geometry->geometry,geomID); } + + Application::instance->log(1,"creating Embree objects done"); + return scene; } - - typedef ISPCInstance* ISPCInstance_ptr; - typedef ISPCGeometry* ISPCGeometry_ptr; - - extern "C" RTCScene ConvertScene(RTCDevice g_device, ISPCScene* scene_in, RTCBuildQuality quality) + + extern "C" void UpdateScene(ISPCScene* scene_in, float time) { - RTCScene scene_out = rtcNewScene(g_device); + TutorialScene* tutorial_scene = (TutorialScene*) scene_in->tutorialScene; + if (!tutorial_scene) return; + if (!g_animation_mode) return; - /* use scene instancing feature */ - if (g_instancing_mode != SceneGraph::INSTANCING_NONE) + for (unsigned int geomID=0; geomIDnumGeometries; geomID++) { - for (unsigned int i=0; inumGeometries; i++) - { - ISPCGeometry* geometry = scene_in->geometries[i]; - if (geometry->type == GROUP) { - RTCScene objscene = rtcNewScene(g_device); - ConvertGroup(g_device,(ISPCGroup*) geometry,quality,objscene,i); - //rtcCommitScene(objscene); - } - else if (geometry->type == INSTANCE) { - ConvertInstance(g_device,scene_in, (ISPCInstance*) geometry, scene_out, i); - } - else - assert(false); - } - } - - /* no instancing */ - else - { - for (unsigned int i=0; inumGeometries; i++) - { - ISPCGeometry* geometry = scene_in->geometries[i]; - if (geometry->type == SUBDIV_MESH) - ConvertSubdivMesh(g_device,(ISPCSubdivMesh*) geometry, quality, scene_out, i); - else if (geometry->type == TRIANGLE_MESH) - ConvertTriangleMesh(g_device,(ISPCTriangleMesh*) geometry, quality, scene_out, i); - else if (geometry->type == QUAD_MESH) - ConvertQuadMesh(g_device,(ISPCQuadMesh*) geometry, quality, scene_out, i); - else if (geometry->type == CURVES) - ConvertCurveGeometry(g_device,(ISPCHairSet*) geometry, quality, scene_out, i); - else if (geometry->type == GRID_MESH) - ConvertGridMesh(g_device,(ISPCGridMesh*) geometry, quality, scene_out, i); - else if (geometry->type == POINTS) - ConvertPoints(g_device,(ISPCPointSet*) geometry, quality, scene_out, i); - else - assert(false); - } + ISPCGeometry* geometry = scene_in->geometries[geomID]; + if (geometry->type != INSTANCE) continue; + ISPCInstance* inst = (ISPCInstance*) geometry; + + Ref node = tutorial_scene->geometries[geomID].dynamicCast(); + assert(node); + inst->spaces[0] = node->get(time); + inst->commit(); } - Application::instance->log(1,"creating Embree objects done"); - return scene_out; + rtcCommitScene(scene_in->scene); + + for (unsigned int i=0; inumLights; i++) + ISPCScene::updateLight(tutorial_scene->lights[i]->get(time), scene_in->lights[i]); } } diff --git a/tutorials/common/tutorial/scene_device.h b/tutorials/common/tutorial/scene_device.h index b56f364ab6..28975682ba 100644 --- a/tutorials/common/tutorial/scene_device.h +++ b/tutorials/common/tutorial/scene_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -66,14 +66,13 @@ namespace embree struct ISPCGeometry { #if !defined(ISPC) - ISPCGeometry (ISPCType type) : type(type), geometry(nullptr), scene(nullptr), geomID(-1), materialID(-1) {} + ISPCGeometry (ISPCType type) : type(type), geometry(nullptr), materialID(-1), visited(false) {} ~ISPCGeometry () { if (geometry) rtcReleaseGeometry(geometry); } #endif ISPCType type; RTCGeometry geometry; - RTCScene scene; - unsigned int geomID; unsigned int materialID; + bool visited; }; #if !defined(ISPC) @@ -87,9 +86,11 @@ namespace embree struct ISPCTriangleMesh { #if !defined(ISPC) - ISPCTriangleMesh (TutorialScene* scene_in, Ref in); + ISPCTriangleMesh (RTCDevice device, TutorialScene* scene_in, Ref in); ~ISPCTriangleMesh (); + void commit(); + private: ISPCTriangleMesh (const ISPCTriangleMesh& other) DELETED; // do not implement ISPCTriangleMesh& operator= (const ISPCTriangleMesh& other) DELETED; // do not implement @@ -113,9 +114,11 @@ namespace embree struct ISPCQuadMesh { #if !defined(ISPC) - ISPCQuadMesh (TutorialScene* scene_in, Ref in); + ISPCQuadMesh (RTCDevice device, TutorialScene* scene_in, Ref in); ~ISPCQuadMesh (); + void commit(); + private: ISPCQuadMesh (const ISPCQuadMesh& other) DELETED; // do not implement ISPCQuadMesh& operator= (const ISPCQuadMesh& other) DELETED; // do not implement @@ -139,8 +142,10 @@ namespace embree struct ISPCSubdivMesh { #if !defined(ISPC) - ISPCSubdivMesh (TutorialScene* scene_in, Ref in); + ISPCSubdivMesh (RTCDevice device, TutorialScene* scene_in, Ref in); ~ISPCSubdivMesh (); + + void commit(); private: ISPCSubdivMesh (const ISPCSubdivMesh& other) DELETED; // do not implement @@ -184,9 +189,11 @@ namespace embree struct ISPCHairSet { #if !defined(ISPC) - ISPCHairSet (TutorialScene* scene_in, RTCGeometryType type, Ref in); + ISPCHairSet (RTCDevice device, TutorialScene* scene_in, RTCGeometryType type, Ref in); ~ISPCHairSet(); + void commit(); + private: ISPCHairSet (const ISPCHairSet& other) DELETED; // do not implement ISPCHairSet& operator= (const ISPCHairSet& other) DELETED; // do not implement @@ -218,9 +225,11 @@ namespace embree struct ISPCPointSet { #if !defined(ISPC) - ISPCPointSet (TutorialScene* scene_in, RTCGeometryType type, Ref in); + ISPCPointSet (RTCDevice device, TutorialScene* scene_in, RTCGeometryType type, Ref in); ~ISPCPointSet(); + void commit(); + private: ISPCPointSet (const ISPCPointSet& other) DELETED; // do not implement ISPCPointSet& operator= (const ISPCPointSet& other) DELETED; // do not implement @@ -233,6 +242,8 @@ namespace embree Vec3fa** normals; //!< normal control points (x,y,z,r) RTCGeometryType type; + float startTime; + float endTime; unsigned int numTimeSteps; unsigned int numVertices; }; @@ -240,9 +251,11 @@ namespace embree struct ISPCGridMesh { #if !defined(ISPC) - ISPCGridMesh (TutorialScene* scene_in, Ref in); + ISPCGridMesh (RTCDevice device, TutorialScene* scene_in, Ref in); ~ISPCGridMesh (); + void commit(); + private: ISPCGridMesh (const ISPCGridMesh& other) DELETED; // do not implement ISPCGridMesh& operator= (const ISPCGridMesh& other) DELETED; // do not implement @@ -265,9 +278,11 @@ namespace embree struct ISPCInstance { #if !defined(ISPC) - ISPCInstance (TutorialScene* scene, Ref in); + ISPCInstance (RTCDevice device, TutorialScene* scene, Ref in); ~ISPCInstance(); + void commit(); + private: ISPCInstance (const ISPCInstance& other) DELETED; // do not implement ISPCInstance& operator= (const ISPCInstance& other) DELETED; // do not implement @@ -287,8 +302,10 @@ namespace embree struct ISPCGroup { #if !defined(ISPC) - ISPCGroup (TutorialScene* scene, Ref in); + ISPCGroup (RTCDevice device, TutorialScene* scene, Ref in); ~ISPCGroup(); + + void commit(); private: ISPCGroup (const ISPCGroup& other) DELETED; // do not implement @@ -297,18 +314,26 @@ namespace embree public: #endif ISPCGeometry geom; + RTCScene scene; ISPCGeometry** geometries; unsigned int numGeometries; + unsigned int requiredInstancingDepth; // instancing depth required for this group }; struct ISPCScene { #if !defined(ISPC) - ISPCScene(TutorialScene* in); + ISPCScene(RTCDevice device, TutorialScene* in); ~ISPCScene(); + + void commit(); - static ISPCGeometry* convertGeometry (TutorialScene* scene, Ref in); - static Light* convertLight(Ref in); + static ISPCGeometry* convertGeometry (RTCDevice device, TutorialScene* scene, Ref in); + static Light* convertLight(Ref in); + static Light* createLight(Ref in); + + template static void updateLight(const LightNode& in, Light* out); + static void updateLight(const Ref& in, Light* out); private: ISPCScene (const ISPCScene& other) DELETED; // do not implement @@ -316,6 +341,7 @@ namespace embree public: #endif + RTCScene scene; ISPCGeometry** geometries; //!< list of geometries ISPCMaterial** materials; //!< material list unsigned int numGeometries; //!< number of geometries @@ -323,12 +349,23 @@ namespace embree Light** lights; //!< list of lights unsigned int numLights; //!< number of lights + void* tutorialScene; }; -#if !defined(ISPC) - extern "C" RTCScene ConvertScene(RTCDevice g_device, ISPCScene* scene_in, RTCBuildQuality quality); +#if !defined(ISPC) + typedef void (*AssignShaderTy)(ISPCGeometry* geometry); + extern "C" { extern AssignShaderTy assignShadersFunc; }; +#else + typedef unmasked void (*AssignShaderTy)(uniform ISPCGeometry* uniform geometry); + extern uniform AssignShaderTy assignShadersFunc; +#endif + +#if !defined(ISPC) + extern "C" void UpdateScene(ISPCScene* scene_in, float time); + extern "C" RTCScene ConvertScene(RTCDevice g_device, ISPCScene* scene_in, RTCBuildQuality quality, RTCSceneFlags flags = RTC_SCENE_FLAG_NONE); #else - unmasked extern "C" RTCScene ConvertScene (RTCDevice g_device, ISPCScene* uniform scene_in, uniform RTCBuildQuality quality); + unmasked extern "C" void UpdateScene(ISPCScene* uniform scene_in, uniform float time); + unmasked extern "C" RTCScene ConvertScene (RTCDevice g_device, ISPCScene* uniform scene_in, uniform RTCBuildQuality quality, uniform RTCSceneFlags flags = RTC_SCENE_FLAG_NONE); #endif #if !defined(ISPC) diff --git a/tutorials/common/tutorial/statistics.h b/tutorials/common/tutorial/statistics.h index 279d521abe..6d35156aa3 100644 --- a/tutorials/common/tutorial/statistics.h +++ b/tutorials/common/tutorial/statistics.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -38,7 +38,12 @@ namespace embree float getMin() const { return vmin; } float getMax() const { return vmax; } - float getAvg() const { return float(v/N); } + + float getAvg() const + { + if (N == 0) return 0.0f; + else return float(v/N); + } private: double v; // sum of all values diff --git a/tutorials/common/tutorial/tasksys.cpp b/tutorials/common/tutorial/tasksys.cpp index dba0a0be8a..920d623ef3 100644 --- a/tutorials/common/tutorial/tasksys.cpp +++ b/tutorials/common/tutorial/tasksys.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../../../common/algorithms/parallel_for.h" diff --git a/tutorials/common/tutorial/tutorial.cpp b/tutorials/common/tutorial/tutorial.cpp index 59a2e2e241..2ba160290b 100644 --- a/tutorials/common/tutorial/tutorial.cpp +++ b/tutorials/common/tutorial/tutorial.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "tutorial.h" @@ -63,6 +63,8 @@ namespace embree RTCIntersectContextFlags g_iflags_coherent = RTC_INTERSECT_CONTEXT_FLAG_COHERENT; RTCIntersectContextFlags g_iflags_incoherent = RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT; + int g_animation_mode = false; + RayStats* g_stats = nullptr; unsigned int render_texcoords_mode = 0; @@ -113,9 +115,6 @@ namespace embree referenceImageFilename(""), referenceImageThreshold(32.0f), - skipBenchmarkFrames(0), - numBenchmarkFrames(0), - interactive(true), fullscreen(false), @@ -170,7 +169,7 @@ namespace embree registerOption("compare-threshold", [this] (Ref cin, const FileName& path) { referenceImageThreshold = cin->getFloat(); - }, "--compare--threshold : threshold in number of wrong pixels when image is considered wrong"); + }, "--compare-threshold : threshold in number of wrong pixels when image is considered wrong"); /* camera settings */ registerOption("vp", [this] (Ref cin, const FileName& path) { @@ -216,19 +215,6 @@ namespace embree fullscreen = true; }, "--fullscreen: starts in fullscreen mode"); - registerOption("benchmark", [this] (Ref cin, const FileName& path) { - skipBenchmarkFrames = cin->getInt(); - numBenchmarkFrames = cin->getInt(); - interactive = false; - rtcore += ",benchmark=1,start_threads=1"; - }, "--benchmark : enabled benchmark mode, builds scene, skips N frames, renders M frames"); - - registerOption("nodisplay", [this] (Ref cin, const FileName& path) { - skipBenchmarkFrames = 0; - numBenchmarkFrames = 2048; - interactive = false; - }, "--nodisplay: enabled benchmark mode, continously renders frames"); - registerOption("print-frame-rate", [this] (Ref cin, const FileName& path) { print_frame_rate = true; }, "--print-frame-rate: prints framerate for each frame on console"); @@ -451,174 +437,194 @@ namespace embree else if (mode == "geometry") instancing_mode = SceneGraph::INSTANCING_GEOMETRY; else if (mode == "group" ) instancing_mode = SceneGraph::INSTANCING_GROUP; else if (mode == "flattened") instancing_mode = SceneGraph::INSTANCING_FLATTENED; + else if (mode == "multi_level") instancing_mode = SceneGraph::INSTANCING_MULTI_LEVEL; else throw std::runtime_error("unknown instancing mode: "+mode); g_instancing_mode = instancing_mode; }, "--instancing: set instancing mode\n" - " none: no instancing\n" + " none: perform no instancing and flatten entire scene\n" " geometry: instance individual geometries as scenes\n" " group: instance geometry groups as scenes\n" + " multi_level: use multi-level instancing\n" " flattened: assume flattened scene graph"); + registerOption("animation", [] (Ref cin, const FileName& path) { + g_animation_mode = true; + }, "--animation: render animated geometries"); + registerOption("ambientlight", [this] (Ref cin, const FileName& path) { - const Vec3fa L = cin->getVec3fa(); - scene->add(new SceneGraph::LightNode(new SceneGraph::AmbientLight(L))); + const Vec3f L = cin->getVec3f(); + futures.push_back([=]() { scene->add(new SceneGraph::LightNodeImpl(SceneGraph::AmbientLight(L))); }); }, "--ambientlight r g b: adds an ambient light with intensity rgb"); registerOptionAlias("ambientlight","ambient"); registerOption("pointlight", [this] (Ref cin, const FileName& path) { - const Vec3fa P = cin->getVec3fa(); - const Vec3fa I = cin->getVec3fa(); - scene->add(new SceneGraph::LightNode(new SceneGraph::PointLight(P,I))); + const Vec3f P = cin->getVec3f(); + const Vec3f I = cin->getVec3f(); + futures.push_back([=]() { scene->add(new SceneGraph::LightNodeImpl(SceneGraph::PointLight(P,I))); }); }, "--pointlight x y z r g b: adds a point light at position xyz with intensity rgb"); registerOption("directionallight", [this] (Ref cin, const FileName& path) { - const Vec3fa D = cin->getVec3fa(); - const Vec3fa E = cin->getVec3fa(); - scene->add(new SceneGraph::LightNode(new SceneGraph::DirectionalLight(D,E))); + const Vec3f D = cin->getVec3f(); + const Vec3f E = cin->getVec3f(); + futures.push_back([=]() { scene->add(new SceneGraph::LightNodeImpl(SceneGraph::DirectionalLight(D,E))); }); }, "--directionallight x y z r g b: adds a directional light with direction xyz and intensity rgb"); registerOptionAlias("directionallight","dirlight"); registerOption("distantlight", [this] (Ref cin, const FileName& path) { - const Vec3fa D = cin->getVec3fa(); - const Vec3fa L = cin->getVec3fa(); + const Vec3f D = cin->getVec3f(); + const Vec3f L = cin->getVec3f(); const float halfAngle = cin->getFloat(); - scene->add(new SceneGraph::LightNode(new SceneGraph::DistantLight(D,L,halfAngle))); + futures.push_back([=]() { scene->add(new SceneGraph::LightNodeImpl(SceneGraph::DistantLight(D,L,halfAngle))); }); }, "--distantlight x y z r g b a: adds a distant light with direction xyz, intensity rgb, and opening angle a"); registerOption("triangle-plane", [this] (Ref cin, const FileName& path) { - const Vec3fa p0 = cin->getVec3fa(); - const Vec3fa dx = cin->getVec3fa(); - const Vec3fa dy = cin->getVec3fa(); + const Vec3f p0 = cin->getVec3f(); + const Vec3f dx = cin->getVec3f(); + const Vec3f dy = cin->getVec3f(); const size_t width = cin->getInt(); const size_t height = cin->getInt(); - scene->add(SceneGraph::createTrianglePlane(p0,dx,dy,width,height,new OBJMaterial)); - }, "--triangle-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height: adds a plane build of triangles originated at p0 and spanned by the vectors dx and dy with a tesselation width/height."); + futures.push_back([=]() { scene->add(SceneGraph::createTrianglePlane(p0,dx,dy,width,height,new OBJMaterial)); }); + }, "--triangle-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height: adds a plane build of triangles originated at p0 and spanned by the vectors dx and dy with a tessellation width/height."); registerOption("quad-plane", [this] (Ref cin, const FileName& path) { - const Vec3fa p0 = cin->getVec3fa(); - const Vec3fa dx = cin->getVec3fa(); - const Vec3fa dy = cin->getVec3fa(); + const Vec3f p0 = cin->getVec3f(); + const Vec3f dx = cin->getVec3f(); + const Vec3f dy = cin->getVec3f(); const size_t width = cin->getInt(); const size_t height = cin->getInt(); - scene->add(SceneGraph::createQuadPlane(p0,dx,dy,width,height,new OBJMaterial)); - }, "--quad-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height: adds a plane build of quadrilaterals originated at p0 and spanned by the vectors dx and dy with a tesselation width/height."); + futures.push_back([=]() { scene->add(SceneGraph::createQuadPlane(p0,dx,dy,width,height,new OBJMaterial)); }); + }, "--quad-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height: adds a plane build of quadrilaterals originated at p0 and spanned by the vectors dx and dy with a tessellation width/height."); registerOption("grid-plane", [this] (Ref cin, const FileName& path) { - const Vec3fa p0 = cin->getVec3fa(); - const Vec3fa dx = cin->getVec3fa(); - const Vec3fa dy = cin->getVec3fa(); + const Vec3f p0 = cin->getVec3f(); + const Vec3f dx = cin->getVec3f(); + const Vec3f dy = cin->getVec3f(); const size_t width = cin->getInt(); const size_t height = cin->getInt(); - scene->add(SceneGraph::createGridPlane(p0,dx,dy,width,height,new OBJMaterial)); - }, "--grid-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height: adds a plane using a grid mesh build. The plane is originated at p0 and spanned by the vectors dx and dy with a tesselation width/height."); + futures.push_back([=]() { scene->add(SceneGraph::createGridPlane(p0,dx,dy,width,height,new OBJMaterial)); }); + }, "--grid-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height: adds a plane using a grid mesh build. The plane is originated at p0 and spanned by the vectors dx and dy with a tessellation width/height."); registerOption("subdiv-plane", [this] (Ref cin, const FileName& path) { - const Vec3fa p0 = cin->getVec3fa(); - const Vec3fa dx = cin->getVec3fa(); - const Vec3fa dy = cin->getVec3fa(); + const Vec3f p0 = cin->getVec3f(); + const Vec3f dx = cin->getVec3f(); + const Vec3f dy = cin->getVec3f(); const size_t width = cin->getInt(); const size_t height = cin->getInt(); const float tessellationRate = cin->getFloat(); - scene->add(SceneGraph::createSubdivPlane(p0,dx,dy,width,height,tessellationRate,new OBJMaterial)); - }, "--subdiv-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height tessellationRate: adds a plane build as a Catmull Clark subdivision surface originated at p0 and spanned by the vectors dx and dy. The plane consists of widt x height many patches, and each patch has the specified tesselation rate."); + futures.push_back([=]() { scene->add(SceneGraph::createSubdivPlane(p0,dx,dy,width,height,tessellationRate,new OBJMaterial)); }); + }, "--subdiv-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z width height tessellationRate: adds a plane build as a Catmull Clark subdivision surface originated at p0 and spanned by the vectors dx and dy. The plane consists of widt x height many patches, and each patch has the specified tessellation rate."); registerOption("hair-plane", [this] (Ref cin, const FileName& path) { - const Vec3fa p0 = cin->getVec3fa(); - const Vec3fa dx = cin->getVec3fa(); - const Vec3fa dy = cin->getVec3fa(); + const Vec3f p0 = cin->getVec3f(); + const Vec3f dx = cin->getVec3f(); + const Vec3f dy = cin->getVec3f(); const float len = cin->getFloat(); const float r = cin->getFloat(); const size_t N = cin->getInt(); - scene->add(SceneGraph::createHairyPlane(0,p0,dx,dy,len,r,N,SceneGraph::FLAT_CURVE,new OBJMaterial)); - }, "--hair-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z length radius num: adds a hair plane originated at p0 and spanned by the vectors dx and dy. num hairs are generated with speficied length and radius."); + futures.push_back([=]() { scene->add(SceneGraph::createHairyPlane(0,p0,dx,dy,len,r,N,SceneGraph::FLAT_CURVE,new OBJMaterial)); }); + }, "--hair-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z length radius num: adds a hair plane originated at p0 and spanned by the vectors dx and dy. num hairs are generated with specified length and radius."); registerOption("curve-plane", [this] (Ref cin, const FileName& path) { - const Vec3fa p0 = cin->getVec3fa(); - const Vec3fa dx = cin->getVec3fa(); - const Vec3fa dy = cin->getVec3fa(); + const Vec3f p0 = cin->getVec3f(); + const Vec3f dx = cin->getVec3f(); + const Vec3f dy = cin->getVec3f(); const float len = cin->getFloat(); const float r = cin->getFloat(); const size_t N = cin->getInt(); - scene->add(SceneGraph::createHairyPlane(0,p0,dx,dy,len,r,N,SceneGraph::ROUND_CURVE,new OBJMaterial)); - }, "--curve-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z length radius: adds a plane build of bezier curves originated at p0 and spanned by the vectors dx and dy. num curves are generated with speficied length and radius."); + futures.push_back([=]() { scene->add(SceneGraph::createHairyPlane(0,p0,dx,dy,len,r,N,SceneGraph::ROUND_CURVE,new OBJMaterial)); }); + }, "--curve-plane p.x p.y p.z dx.x dx.y dx.z dy.x dy.y dy.z length radius: adds a plane build of bezier curves originated at p0 and spanned by the vectors dx and dy. num curves are generated with specified length and radius."); registerOption("sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); - scene->add(SceneGraph::createSphere(p, r, new OBJMaterial)); + futures.push_back([=]() { scene->add(SceneGraph::createSphere(p, r, new OBJMaterial)); }); }, "--sphere p.x p.y p.z r: adds a sphere at position p with radius r"); registerOption("triangle-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const size_t numPhi = cin->getInt(); - scene->add(SceneGraph::createTriangleSphere(p,r,numPhi,new OBJMaterial)); - }, "--triangle-sphere p.x p.y p.z r numPhi: adds a sphere at position p with radius r and tesselation numPhi build of triangles."); + futures.push_back([=]() { scene->add(SceneGraph::createTriangleSphere(p,r,numPhi,new OBJMaterial)); }); + }, "--triangle-sphere p.x p.y p.z r numPhi: adds a sphere at position p with radius r and tessellation numPhi build of triangles."); registerOption("quad-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const size_t numPhi = cin->getInt(); - scene->add(SceneGraph::createQuadSphere(p,r,numPhi,new OBJMaterial)); - }, "--quad-sphere p.x p.y p.z r numPhi: adds a sphere at position p with radius r and tesselation numPhi build of quadrilaterals."); + futures.push_back([=]() { scene->add(SceneGraph::createQuadSphere(p,r,numPhi,new OBJMaterial)); }); + }, "--quad-sphere p.x p.y p.z r numPhi: adds a sphere at position p with radius r and tessellation numPhi build of quadrilaterals."); registerOption("grid-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const size_t N = cin->getInt(); - scene->add(SceneGraph::createGridSphere(p,r,N,new OBJMaterial)); + futures.push_back([=]() { scene->add(SceneGraph::createGridSphere(p,r,N,new OBJMaterial)); }); }, "--grid-sphere p.x p.y p.z r N: adds a grid sphere at position p with radius r using a cube topology and N*N quads at each face."); + registerOption("triangle-sphere-mblur", [this] (Ref cin, const FileName& path) { + const Vec3f p = cin->getVec3f(); + const Vec3f dp = cin->getVec3f(); + const float r = cin->getFloat(); + const size_t numPhi = cin->getInt(); + futures.push_back([=]() { + Ref mesh = SceneGraph::createTriangleSphere(p,r,numPhi,new OBJMaterial); + mesh->set_motion_vector(dp); + scene->add(mesh); + }); + }, "--triangle-sphere-mblur p.x p.y p.z d.x d.y d.z r numPhi : adds a motion blurred sphere build of triangles at position p, with motion vector d, radius r, and tessellation numPhi."); + registerOption("quad-sphere-mblur", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); - const Vec3fa dp = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); + const Vec3f dp = cin->getVec3f(); const float r = cin->getFloat(); const size_t numPhi = cin->getInt(); - Ref mesh = SceneGraph::createQuadSphere(p,r,numPhi,new OBJMaterial); - mesh->set_motion_vector(dp); - scene->add(mesh); - }, "--quad-sphere-mb p.x p.y p.z d.x d.y d.z r numPhi : adds a motion blurred sphere build of quadrilaterals at position p, with motion vector d, radius r, and tesselation numPhi."); + futures.push_back([=]() { + Ref mesh = SceneGraph::createQuadSphere(p,r,numPhi,new OBJMaterial); + mesh->set_motion_vector(dp); + scene->add(mesh); + }); + }, "--quad-sphere-mblur p.x p.y p.z d.x d.y d.z r numPhi : adds a motion blurred sphere build of quadrilaterals at position p, with motion vector d, radius r, and tessellation numPhi."); registerOption("subdiv-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const size_t numPhi = cin->getInt(); const float tessellationRate = cin->getFloat(); - scene->add(SceneGraph::createSubdivSphere(p,r,numPhi,tessellationRate,new OBJMaterial)); + futures.push_back([=]() { scene->add(SceneGraph::createSubdivSphere(p,r,numPhi,tessellationRate,new OBJMaterial)); }); }, "--subdiv-sphere p.x p.y p.z r numPhi: adds a sphere at position p with radius r build of Catmull Clark subdivision surfaces. The sphere consists of numPhi x numPhi many patches and each path has the specified tessellation rate."); registerOption("point-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const float pointR = cin->getFloat(); const size_t numPhi = cin->getInt(); - scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::SPHERE, new OBJMaterial)); - }, "--point-sphere p.x p.y p.z r pointR numPhi: adds a sphere at position p with radius r and tesselation numPhi build of spheres."); + futures.push_back([=]() { scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::SPHERE, new OBJMaterial)); }); + }, "--point-sphere p.x p.y p.z r pointR numPhi: adds a sphere at position p with radius r and tessellation numPhi build of spheres."); registerOption("point-sphere-mblur", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); - const Vec3fa dp = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); + const Vec3f dp = cin->getVec3f(); const float r = cin->getFloat(); const float pointR = cin->getFloat(); const size_t numPhi = cin->getInt(); - scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::SPHERE, new OBJMaterial)->set_motion_vector(dp)); - }, "--point-sphere p.x p.y p.z d.x d.y d.z r pointR numPhi: adds a sphere at position p, motion vector d, with radius r and tesselation numPhi build of spheres."); + futures.push_back([=]() { scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::SPHERE, new OBJMaterial)->set_motion_vector(dp)); }); + }, "--point-sphere p.x p.y p.z d.x d.y d.z r pointR numPhi: adds a sphere at position p, motion vector d, with radius r and tessellation numPhi build of spheres."); registerOption("disc-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const float pointR = cin->getFloat(); const size_t numPhi = cin->getInt(); - scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::DISC, new OBJMaterial)); - }, "--disc-sphere p.x p.y p.z r pointR numPhi: adds a sphere at position p with radius r and tesselation numPhi build of discs."); + futures.push_back([=]() { scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::DISC, new OBJMaterial)); }); + }, "--disc-sphere p.x p.y p.z r pointR numPhi: adds a sphere at position p with radius r and tessellation numPhi build of discs."); registerOption("oriented-disc-sphere", [this] (Ref cin, const FileName& path) { - const Vec3fa p = cin->getVec3fa(); + const Vec3f p = cin->getVec3f(); const float r = cin->getFloat(); const float pointR = cin->getFloat(); const size_t numPhi = cin->getInt(); - scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::ORIENTED_DISC, new OBJMaterial)); - }, "--oriented-disc-sphere p.x p.y p.z r pointR numPhi: adds a sphere at position p with radius r and tesselation numPhi build of oriented discs."); + futures.push_back([=]() { scene->add(SceneGraph::createPointSphere(p, r, pointR, numPhi, SceneGraph::ORIENTED_DISC, new OBJMaterial)); }); + }, "--oriented-disc-sphere p.x p.y p.z r pointR numPhi: adds a sphere at position p with radius r and tessellation numPhi build of oriented discs."); registerOption("print-cameras", [this] (Ref cin, const FileName& path) { print_scene_cameras = true; @@ -646,78 +652,6 @@ namespace embree return numRays; } - void TutorialApplication::renderBenchmark() - { - IOStreamStateRestorer cout_state(std::cout); - std::cout.setf(std::ios::fixed, std::ios::floatfield); - std::cout.precision(4); - - resize(width,height); - ISPCCamera ispccamera = camera.getISPCCamera(width,height); - - //Statistics stat; - FilteredStatistics fpsStat(0.5f,0.0f); - FilteredStatistics mraypsStat(0.5f,0.0f); - { - size_t numTotalFrames = skipBenchmarkFrames + numBenchmarkFrames; - for (size_t i=0; i= 1024 && (i % 64 == 0)) - { - std::cout << "frame [" << std::setw(3) << i << " / " << std::setw(3) << numTotalFrames << "]: " - << std::setw(8) << fps << " fps, " - << "min = " << std::setw(8) << fpsStat.getMin() << " fps, " - << "avg = " << std::setw(8) << fpsStat.getAvg() << " fps, " - << "max = " << std::setw(8) << fpsStat.getMax() << " fps, " - << "sigma = " << std::setw(6) << fpsStat.getSigma() << " (" << 100.0f*fpsStat.getSigma()/fpsStat.getAvg() << "%)" << std::endl << std::flush; - } - } - - std::cout << "frame [" << std::setw(3) << skipBenchmarkFrames << " - " << std::setw(3) << numTotalFrames << "]: " - << " " - << "min = " << std::setw(8) << fpsStat.getMin() << " fps, " - << "avg = " << std::setw(8) << fpsStat.getAvg() << " fps, " - << "max = " << std::setw(8) << fpsStat.getMax() << " fps, " - << "sigma = " << std::setw(6) << fpsStat.getAvgSigma() << " (" << 100.0f*fpsStat.getAvgSigma()/fpsStat.getAvg() << "%)" << std::endl; - } - - std::cout << "BENCHMARK_RENDER_MIN " << fpsStat.getMin() << std::endl; - std::cout << "BENCHMARK_RENDER_AVG " << fpsStat.getAvg() << std::endl; - std::cout << "BENCHMARK_RENDER_MAX " << fpsStat.getMax() << std::endl; - std::cout << "BENCHMARK_RENDER_SIGMA " << fpsStat.getSigma() << std::endl; - std::cout << "BENCHMARK_RENDER_AVG_SIGMA " << fpsStat.getAvgSigma() << std::endl; - -#if defined(RAY_STATS) - std::cout << "BENCHMARK_RENDER_MRAYPS_MIN " << mraypsStat.getMin() << std::endl; - std::cout << "BENCHMARK_RENDER_MRAYPS_AVG " << mraypsStat.getAvg() << std::endl; - std::cout << "BENCHMARK_RENDER_MRAYPS_MAX " << mraypsStat.getMax() << std::endl; - std::cout << "BENCHMARK_RENDER_MRAYPS_SIGMA " << mraypsStat.getSigma() << std::endl; - std::cout << "BENCHMARK_RENDER_MRAYPS_AVG_SIGMA " << mraypsStat.getAvgSigma() << std::endl; -#endif - - std::cout << std::flush; - } - void TutorialApplication::renderToFile(const FileName& fileName) { resize(width,height); @@ -759,7 +693,7 @@ namespace embree void TutorialApplication::set_scene (TutorialScene* in) { - ispc_scene.reset(new ISPCScene(in)); + ispc_scene.reset(new ISPCScene(g_device,in)); g_ispc_scene = ispc_scene.get(); } @@ -1011,22 +945,31 @@ namespace embree void TutorialApplication::displayFunc() { + double t0 = getSeconds(); + const float time = float(t0-time0); + /* update camera */ camera.move(moveDelta.x*speed, moveDelta.y*speed, moveDelta.z*speed); - ISPCCamera ispccamera = camera.getISPCCamera(width,height,true); + + /* update animated camera */ + if (animated_camera) + camera = Camera(animated_camera->get(time),camera.handedness); + + ISPCCamera ispccamera = camera.getISPCCamera(width,height); if (print_camera) std::cout << camera.str() << std::endl; /* render image using ISPC */ initRayStats(); - double t0 = getSeconds(); - render(pixels,width,height,float(time0-t0),ispccamera); + render(pixels,width,height,time,ispccamera); double dt0 = getSeconds()-t0; avg_render_time.add(dt0); double mrayps = double(getNumRays())/(1000000.0*dt0); avg_mrayps.add(mrayps); /* draw pixels to screen */ + glRasterPos2i(-1,1); + glPixelZoom(1.0f,-1.0f); glDrawPixels(width,height,GL_RGBA,GL_UNSIGNED_BYTE,pixels); ImGui_ImplGlfwGL2_NewFrame(); @@ -1046,7 +989,10 @@ namespace embree ImGui::SetNextWindowBgAlpha(0.3f); ImGui::Begin("Embree", nullptr, window_flags); drawGUI(); - ImGui::Text("%3.2f fps",1.0f/avg_render_time.get()); + + double avg_time = avg_render_time.get(); + double fps = avg_time != 0.0 ? 1.0f/avg_time : 0.0; + ImGui::Text("%3.2f fps",fps); #if defined(RAY_STATS) ImGui::Text("%3.2f Mray/s",avg_mrayps.get()); #endif @@ -1196,11 +1142,6 @@ namespace embree case SHADER_AMBIENT_OCCLUSION: renderFrame = renderFrameAmbientOcclusion; break; }; - /* benchmark mode */ - if (numBenchmarkFrames) { - renderBenchmark(); - } - /* render to disk */ if (outputImageFilename.str() != "") renderToFile(outputImageFilename); @@ -1270,6 +1211,9 @@ namespace embree rtcSetDeviceErrorFunction(g_device,error_handler,nullptr); log(1,"application start"); + + /* execute postponed scene graph operations */ + for (auto& f : futures) f(); /* load scene */ if (sceneFilename.size()) @@ -1366,14 +1310,18 @@ namespace embree /* use specified camera */ if (camera_name != "") { - Ref c = obj_scene.getCamera(camera_name); - camera = Camera(c->from,c->to,c->up,c->fov,camera.handedness); + auto cam = obj_scene.getCamera(camera_name); + camera = Camera(cam->get(0),camera.handedness); + if (cam->isAnimated()) animated_camera = cam; } /* otherwise use default camera */ else if (!command_line_camera) { - Ref c = obj_scene.getDefaultCamera(); - if (c) camera = Camera(c->from,c->to,c->up,c->fov,camera.handedness); + auto cam = obj_scene.getDefaultCamera(); + if (cam) { + camera = Camera(cam->get(0),camera.handedness); + if (cam->isAnimated()) animated_camera = cam; + } } /* send model */ diff --git a/tutorials/common/tutorial/tutorial.h b/tutorials/common/tutorial/tutorial.h index bff7f06573..deafbbd321 100644 --- a/tutorials/common/tutorial/tutorial.h +++ b/tutorials/common/tutorial/tutorial.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -55,7 +55,8 @@ namespace embree num++; } } - return sum/Ty(num); + if (num == 0) return 0; + else return sum/Ty(num); } std::deque> values; @@ -83,9 +84,6 @@ namespace embree /* callback called after command line parsing finished */ virtual void postParseCommandLine() {} - /* benchmark mode */ - void renderBenchmark(); - /* render to file mode */ void renderToFile(const FileName& fileName); @@ -136,6 +134,7 @@ namespace embree std::string tutorialName; /* render settings */ + Ref animated_camera; Camera camera; Shader shader; @@ -149,10 +148,6 @@ namespace embree FileName referenceImageFilename; float referenceImageThreshold; // threshold when we consider images to differ - /* benchmark mode settings */ - size_t skipBenchmarkFrames; - size_t numBenchmarkFrames; - /* window settings */ bool interactive; bool fullscreen; @@ -186,8 +181,7 @@ namespace embree RTCIntersectContextFlags iflags_incoherent; std::unique_ptr ispc_scene; - - private: + /* ray statistics */ void initRayStats(); int64_t getNumRays(); @@ -203,6 +197,10 @@ namespace embree virtual int main(int argc, char** argv); + bool scene_empty_post_parse() const { + return scene->size() == 0 && sceneFilename.size() == 0 && futures.size() == 0; + } + public: TutorialScene obj_scene; Ref scene; @@ -222,6 +220,7 @@ namespace embree CONVERT_MBLUR_TO_NONMBLUR, }; std::vector sgop; + std::vector> futures; // future scene graph operations float convert_tris_to_quads_prop; unsigned grid_resX, grid_resY; diff --git a/tutorials/common/tutorial/tutorial_device.cpp b/tutorials/common/tutorial/tutorial_device.cpp index ee65ee32c4..bf7d65ebf5 100644 --- a/tutorials/common/tutorial/tutorial_device.cpp +++ b/tutorials/common/tutorial/tutorial_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "tutorial_device.h" @@ -275,7 +275,7 @@ Vec3fa renderPixelTexCoords(const DebugShaderData& data, float x, float y, const else if (data.ispc_scene) { Vec2f st = Vec2f(0,0); - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { RTCGeometry geometry = rtcGetGeometry(data.scene,geomID); rtcInterpolate0(geometry,ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE,2,&st.x,2); } @@ -508,7 +508,7 @@ Vec3fa renderPixelDifferentials(const DebugShaderData& data, float x, float y, c Vec3fa dP00du, dP01du, dP10du, dP11du; Vec3fa dP00dv, dP01dv, dP10dv, dP11dv; Vec3fa dPdu1, dPdv1, ddPdudu1, ddPdvdv1, ddPdudv1; - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { RTCGeometry geometry = rtcGetGeometry(data.scene,geomID); rtcInterpolate1(geometry,ray.primID,ray.u+0.f,ray.v+0.f,RTC_BUFFER_TYPE_VERTEX,0,&P00.x,&dP00du.x,&dP00dv.x,3); rtcInterpolate1(geometry,ray.primID,ray.u+0.f,ray.v+eps,RTC_BUFFER_TYPE_VERTEX,0,&P01.x,&dP01du.x,&dP01dv.x,3); diff --git a/tutorials/common/tutorial/tutorial_device.h b/tutorials/common/tutorial/tutorial_device.h index 802392bbd4..749324a692 100644 --- a/tutorials/common/tutorial/tutorial_device.h +++ b/tutorials/common/tutorial/tutorial_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -15,7 +15,7 @@ struct Triangle { int v0, v1, v2; }; /* include embree API */ #include "../../../include/embree3/rtcore.h" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE /* include optional vector library */ #include "../math/math.h" diff --git a/tutorials/common/tutorial/tutorial_device.ispc b/tutorials/common/tutorial/tutorial_device.ispc index 88480fdf7b..6a916b4d6b 100644 --- a/tutorials/common/tutorial/tutorial_device.ispc +++ b/tutorials/common/tutorial/tutorial_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "tutorial_device.isph" diff --git a/tutorials/common/tutorial/tutorial_device.isph b/tutorials/common/tutorial/tutorial_device.isph index 86d239b4ee..04430fa0d1 100644 --- a/tutorials/common/tutorial/tutorial_device.isph +++ b/tutorials/common/tutorial/tutorial_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -15,7 +15,7 @@ struct Triangle { int v0, v1, v2; }; /* include embree API */ #include "../../../include/embree3/rtcore.isph" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE /* include optional vector library */ #include "../math/math.isph" diff --git a/tutorials/convert/CMakeLists.txt b/tutorials/convert/CMakeLists.txt index 3213cb6e9e..0470bd46fb 100644 --- a/tutorials/convert/CMakeLists.txt +++ b/tutorials/convert/CMakeLists.txt @@ -1,9 +1,9 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_EXECUTABLE(convert ../../kernels/embree.rc convert.cpp distribution1d.cpp distribution2d.cpp) TARGET_LINK_LIBRARIES(convert scenegraph image tasking) SET_PROPERTY(TARGET convert PROPERTY FOLDER tutorials/single) SET_PROPERTY(TARGET convert APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -INSTALL(TARGETS convert DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) +INSTALL(TARGETS convert DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) SIGN_TARGET(convert) diff --git a/tutorials/convert/convert.cpp b/tutorials/convert/convert.cpp index 5b1162359c..4f18f6ad42 100644 --- a/tutorials/convert/convert.cpp +++ b/tutorials/convert/convert.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "default.h" @@ -16,6 +16,7 @@ namespace embree bool embedTextures = true; bool referenceMaterials = false; bool referenceObjects = true; + bool binaryFormat = true; float centerScale = 0.0f; Vec3fa centerTranslate(0.0f,0.0f,0.0f); @@ -266,6 +267,16 @@ namespace embree referenceObjects = true; } + /* enable binary format */ + else if (tag == "-binary") { + binaryFormat = true; + } + + /* enable text format */ + else if (tag == "-text") { + binaryFormat = false; + } + else if (tag == "-centerScaleTranslate") { centerScale = cin->getFloat(); centerTranslate.x = cin->getFloat(); @@ -275,7 +286,7 @@ namespace embree /* output filename */ else if (tag == "-o") { - SceneGraph::store(g_scene.dynamicCast(),path + cin->getFileName(),embedTextures,referenceMaterials); + SceneGraph::store(g_scene.dynamicCast(),path + cin->getFileName(),embedTextures,referenceMaterials,binaryFormat); } /* skip unknown command line parameter */ diff --git a/tutorials/convert/default.h b/tutorials/convert/default.h index d1b5c88268..51baf77e0b 100644 --- a/tutorials/convert/default.h +++ b/tutorials/convert/default.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/convert/distribution1d.cpp b/tutorials/convert/distribution1d.cpp index 48def84391..dce114cc4d 100644 --- a/tutorials/convert/distribution1d.cpp +++ b/tutorials/convert/distribution1d.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "distribution1d.h" diff --git a/tutorials/convert/distribution1d.h b/tutorials/convert/distribution1d.h index 8d55cdc317..e6bed03cbd 100644 --- a/tutorials/convert/distribution1d.h +++ b/tutorials/convert/distribution1d.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/convert/distribution2d.cpp b/tutorials/convert/distribution2d.cpp index 149252c728..3efde9e2fb 100644 --- a/tutorials/convert/distribution2d.cpp +++ b/tutorials/convert/distribution2d.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "distribution2d.h" diff --git a/tutorials/convert/distribution2d.h b/tutorials/convert/distribution2d.h index 8989c5987a..b7a51336b4 100644 --- a/tutorials/convert/distribution2d.h +++ b/tutorials/convert/distribution2d.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/curve_geometry/CMakeLists.txt b/tutorials/curve_geometry/CMakeLists.txt index 8f739bc720..85b278bdb1 100644 --- a/tutorials/curve_geometry/CMakeLists.txt +++ b/tutorials/curve_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/curve_geometry/curve_geometry.cpp b/tutorials/curve_geometry/curve_geometry.cpp index 50a854c188..d4194b9175 100644 --- a/tutorials/curve_geometry/curve_geometry.cpp +++ b/tutorials/curve_geometry/curve_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "curve_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/curve_geometry/curve_geometry_device.cpp b/tutorials/curve_geometry/curve_geometry_device.cpp index 4e648bd7cd..d52bdd1f80 100644 --- a/tutorials/curve_geometry/curve_geometry_device.cpp +++ b/tutorials/curve_geometry/curve_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" @@ -77,7 +77,7 @@ unsigned int addCurve (RTCScene scene, RTCGeometryType gtype, const Vec4f& pos) RTCGeometry geom = rtcNewGeometry (g_device, gtype); rtcSetGeometryVertexAttributeCount(geom,1); - if (gtype == RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) + if (gtype == RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE) rtcSetSharedGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, hair_indices_linear,0, sizeof(unsigned int), NUM_CURVES); else rtcSetSharedGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, hair_indices, 0, sizeof(unsigned int), NUM_CURVES); @@ -92,7 +92,7 @@ unsigned int addCurve (RTCScene scene, RTCGeometryType gtype, const Vec4f& pos) rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_NORMAL, 0, RTC_FORMAT_FLOAT3, hair_normals, 0, sizeof(Vec3fa), NUM_VERTICES); } - if (gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) { + if (gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE) { rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_FLAGS, 0, RTC_FORMAT_UCHAR, hair_flags_linear, 0, sizeof(char), NUM_CURVES); } @@ -137,10 +137,11 @@ extern "C" void device_init (char* cfg) addGroundPlane(g_scene); /* add curves */ - addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, Vec4f(-4.5f, 0.0f, 3.f, 0.0f)); - addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, Vec4f(-1.5f, 0.0f, 3.f, 0.0f)); - addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, Vec4f(1.5f, 0.0f, 3.f, 0.0f)); - addCurve(g_scene, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, Vec4f(+4.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, Vec4f(-5.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, Vec4f(-2.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, Vec4f(0.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, Vec4f(3.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, Vec4f(+6.0f, 0.0f, 3.f, 0.0f)); addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, Vec4f(-4.5f, 0.0f, -2.f, 0.0f)); addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, Vec4f(-1.5f, 0.0f, -2.f, 0.0f)); @@ -172,7 +173,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Vec3fa diffuse = Vec3fa(1.0f,0.0f,0.0f); if (ray.geomID > 0) { - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { rtcInterpolate0(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE,0,&diffuse.x,3); } diffuse = 0.5f*diffuse; diff --git a/tutorials/curve_geometry/curve_geometry_device.ispc b/tutorials/curve_geometry/curve_geometry_device.ispc index e6240fc672..1d87ee25c1 100644 --- a/tutorials/curve_geometry/curve_geometry_device.ispc +++ b/tutorials/curve_geometry/curve_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" @@ -75,7 +75,7 @@ uniform unsigned int addCurve (RTCScene scene, uniform RTCGeometryType gtype, co RTCGeometry geom = rtcNewGeometry (g_device, gtype); rtcSetGeometryVertexAttributeCount(geom,1); - if (gtype == RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) + if (gtype == RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE) rtcSetSharedGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, hair_indices_linear,0, sizeof(uniform unsigned int), NUM_CURVES); else rtcSetSharedGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, hair_indices, 0, sizeof(uniform unsigned int), NUM_CURVES); @@ -90,7 +90,7 @@ uniform unsigned int addCurve (RTCScene scene, uniform RTCGeometryType gtype, co rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_NORMAL, 0, RTC_FORMAT_FLOAT3, hair_normals, 0, sizeof(uniform Vec3fa), NUM_VERTICES); } - if (gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) { + if (gtype == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE || gtype == RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE) { rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_FLAGS, 0, RTC_FORMAT_UCHAR, hair_flags_linear, 0, sizeof(uniform int8), NUM_CURVES); } @@ -135,10 +135,11 @@ export void device_init (uniform int8* uniform cfg) addGroundPlane(g_scene); /* add curves */ - addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, make_Vec4f(-4.5f, 0.0f, 3.f, 0.0f)); - addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, make_Vec4f(-1.5f, 0.0f, 3.f, 0.0f)); - addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, make_Vec4f(1.5f, 0.0f, 3.f, 0.0f)); - addCurve(g_scene, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, make_Vec4f(+4.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, make_Vec4f(-5.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, make_Vec4f(-2.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, make_Vec4f(0.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, make_Vec4f(3.5f, 0.0f, 3.f, 0.0f)); + addCurve(g_scene, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, make_Vec4f(+6.0f, 0.0f, 3.f, 0.0f)); addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, make_Vec4f(-4.5f, 0.0f, -2.f, 0.0f)); addCurve(g_scene, RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, make_Vec4f(-1.5f, 0.0f, -2.f, 0.0f)); diff --git a/tutorials/displacement_geometry/CMakeLists.txt b/tutorials/displacement_geometry/CMakeLists.txt index 15f4aeb304..3f33892ff8 100644 --- a/tutorials/displacement_geometry/CMakeLists.txt +++ b/tutorials/displacement_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/displacement_geometry/displacement_geometry.cpp b/tutorials/displacement_geometry/displacement_geometry.cpp index 449aa774b7..62b22ee105 100644 --- a/tutorials/displacement_geometry/displacement_geometry.cpp +++ b/tutorials/displacement_geometry/displacement_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "displacement_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/displacement_geometry/displacement_geometry_device.cpp b/tutorials/displacement_geometry/displacement_geometry_device.cpp index 90d7be5c67..18e2a87ee6 100644 --- a/tutorials/displacement_geometry/displacement_geometry_device.cpp +++ b/tutorials/displacement_geometry/displacement_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" @@ -195,7 +195,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Vec3fa P = ray.org + ray.tfar*ray.dir; if (ray.geomID > 0) { Vec3fa dPdu,dPdv; - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { rtcInterpolate1(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,nullptr,&dPdu.x,&dPdv.x,3); } Ng = normalize(cross(dPdu,dPdv)); diff --git a/tutorials/displacement_geometry/displacement_geometry_device.ispc b/tutorials/displacement_geometry/displacement_geometry_device.ispc index c6671041db..a15ecd4e48 100644 --- a/tutorials/displacement_geometry/displacement_geometry_device.ispc +++ b/tutorials/displacement_geometry/displacement_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/dynamic_scene/CMakeLists.txt b/tutorials/dynamic_scene/CMakeLists.txt index 232c65d2f8..80c3a74180 100644 --- a/tutorials/dynamic_scene/CMakeLists.txt +++ b/tutorials/dynamic_scene/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/dynamic_scene/dynamic_scene.cpp b/tutorials/dynamic_scene/dynamic_scene.cpp index 141a1cb7c6..da8a8333bf 100644 --- a/tutorials/dynamic_scene/dynamic_scene.cpp +++ b/tutorials/dynamic_scene/dynamic_scene.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/dynamic_scene/dynamic_scene_device.cpp b/tutorials/dynamic_scene/dynamic_scene_device.cpp index 22758cc39e..12c861b4a9 100644 --- a/tutorials/dynamic_scene/dynamic_scene_device.cpp +++ b/tutorials/dynamic_scene/dynamic_scene_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/dynamic_scene/dynamic_scene_device.ispc b/tutorials/dynamic_scene/dynamic_scene_device.ispc index bf7fd93003..c71c51cfb2 100644 --- a/tutorials/dynamic_scene/dynamic_scene_device.ispc +++ b/tutorials/dynamic_scene/dynamic_scene_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/embree_tests/CMakeLists.txt b/tutorials/embree_tests/CMakeLists.txt index 38eea6a26a..a813b4bcaa 100644 --- a/tutorials/embree_tests/CMakeLists.txt +++ b/tutorials/embree_tests/CMakeLists.txt @@ -1,13 +1,46 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 -ADD_EXECUTABLE(embree_tests ../../kernels/embree.rc - embree_tests.cpp - kernels/kernels_tests.cpp) -TARGET_LINK_LIBRARIES(embree_tests tasking sys math scenegraph embree) +ADD_EXECUTABLE(embree_tests ../../kernels/embree.rc + embree_tests.cpp + kernels/kernels_tests.cpp + common/common_tests.cpp) +TARGET_LINK_LIBRARIES(embree_tests tasking sys math embree) + +if (EMSCRIPTEN) + # Use "-s ALLOW_MEMORY_GROWTH=1" to allow the WASM heap to grow. + + # Use "-s PROXY_TO_PTHREAD=1" to move program execution to a worker thread, leaving the main + # thread available to respond to requests for more worker threads. Without this flag, we'd need + # to prepopulate a thread pool with enough threads for every unit test (with something like + # "-s PTHREAD_POOL_SIZE=40"), otherwise the main thread would block as soon another thread is + # launched. See https://emscripten.org/docs/porting/pthreads.html#additional-flags and + # https://github.com/emscripten-core/emscripten/blob/main/src/settings.js#L1019. + + # Use "-s EXIT_RUNTIME=1" to exit the Node.js process when the main thread completes. Otherwise, + # any worker threads (even completed threads) will keep the process alive. See + # https://github.com/emscripten-core/emscripten/blob/main/src/settings.js#L91. + + # Use "-s NODERAWFS=1" to allow tests running on Node.js to access the system's files (through + # Emscripten's "raw filesystem" backend). This is used by several unit tests to read test data. + # See https://github.com/emscripten-core/emscripten/blob/main/src/settings.js#L898. + + # Use "-Wno-pthreads-mem-growth" to silence the warning "USE_PTHREADS + ALLOW_MEMORY_GROWTH may + # run non-wasm code slowly, see https://github.com/WebAssembly/design/issues/1271". Unit tests + # don't run much (if any) non-wasm code. + + TARGET_LINK_OPTIONS(embree_tests PUBLIC + "SHELL:-s ASSERTIONS=1" + "SHELL:-s ALLOW_MEMORY_GROWTH=1" + "SHELL:-s PROXY_TO_PTHREAD=1" + "SHELL:-s EXIT_RUNTIME=1" + -Wno-pthreads-mem-growth + ) +endif() + SET_PROPERTY(TARGET embree_tests PROPERTY FOLDER tutorials) SET_PROPERTY(TARGET embree_tests APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -INSTALL(TARGETS embree_tests DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) +INSTALL(TARGETS embree_tests DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) SIGN_TARGET(embree_tests) IF (BUILD_TESTING) diff --git a/tutorials/embree_tests/common/algorithms/algorithms_tests.cpp b/tutorials/embree_tests/common/algorithms/algorithms_tests.cpp new file mode 100644 index 0000000000..803058de79 --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/algorithms_tests.cpp @@ -0,0 +1,14 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "parallel_any_of.cpp" +#include "parallel_filter.cpp" +#include "parallel_for.cpp" +#include "parallel_for_for.cpp" +#include "parallel_for_for_prefix_sum.cpp" +#include "parallel_map.cpp" +#include "parallel_partition.cpp" +#include "parallel_prefix_sum.cpp" +#include "parallel_reduce.cpp" +#include "parallel_set.cpp" +#include "parallel_sort.cpp" diff --git a/tutorials/embree_tests/common/algorithms/parallel_any_of.cpp b/tutorials/embree_tests/common/algorithms/parallel_any_of.cpp new file mode 100644 index 0000000000..967ca3d66f --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/parallel_any_of.cpp @@ -0,0 +1,36 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../../../external/catch.hpp" +#include "../common/tasking/taskscheduler.h" +#include "../common/algorithms/parallel_any_of.h" + +#include +#include +#include + +using namespace embree; + +namespace parallel_any_of_unit_tests { + +TEST_CASE ("Test parallel_any_of", "[parallel_any_of]") +{ + const size_t num_threads = std::thread::hardware_concurrency(); + TaskScheduler::create(num_threads, true, false); + + std::vector data(1024); + std::iota(data.begin(), data.end(), 0); + + std::shuffle(data.begin(), data.end(), std::mt19937{7777}); + + auto unaryPredicateTrue = [&](size_t i) -> bool { return data[i] == 512; }; + auto unaryPredicateFalse = [&](size_t i) -> bool { return data[i] == 1048; }; + + bool resultUnaryPredicateTrue = parallel_any_of(size_t(0), data.size(), unaryPredicateTrue); + bool resultUnaryPredicateFalse = parallel_any_of(size_t(0), data.size(), unaryPredicateFalse); + + REQUIRE(resultUnaryPredicateTrue); + REQUIRE(!resultUnaryPredicateFalse); +} + +} diff --git a/tutorials/embree_tests/common/algorithms/parallel_filter.cpp b/tutorials/embree_tests/common/algorithms/parallel_filter.cpp new file mode 100644 index 0000000000..2a46361264 --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/parallel_filter.cpp @@ -0,0 +1,54 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../../../external/catch.hpp" +#include "../common/algorithms/parallel_filter.h" + +#include +#include + +using namespace embree; + +namespace parallel_filter_unit_test { + +TEST_CASE("Test parallel_filter", "[parallel_filter]") +{ + bool passed = true; + auto pred = [&](uint32_t v) { return (v & 0x3) == 0; }; + + for (size_t N = 10; N < 1000000; N = size_t(2.1 * N)) + { + size_t N0 = rand() % N; + + /* initialize array with random numbers */ + std::vector src(N); + std::map m; + for (size_t i = 0; i < N; i++) + src[i] = rand(); + + /* count elements up */ + for (size_t i = N0; i < N; i++) + if (pred(src[i])) + m[src[i]] = 0; + for (size_t i = N0; i < N; i++) + if (pred(src[i])) + m[src[i]]++; + + /* filter array */ + //size_t M = sequential_filter(src.data(),N0,N,pred); + size_t M = parallel_filter(src.data(), N0, N, size_t(1024), pred); + + /* check if filtered data is correct */ + for (size_t i = N0; i < M; i++) + { + passed &= pred(src[i]); + m[src[i]]--; + } + for (size_t i = N0; i < M; i++) + passed &= (m[src[i]] == 0); + } + + REQUIRE(passed); +} + +} diff --git a/tutorials/embree_tests/common/algorithms/parallel_for.cpp b/tutorials/embree_tests/common/algorithms/parallel_for.cpp new file mode 100644 index 0000000000..023df82b64 --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/parallel_for.cpp @@ -0,0 +1,44 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../../../external/catch.hpp" +#include "../common/algorithms/parallel_for.h" + +#include + +using namespace embree; + +namespace parallel_for_unit_test { + +TEST_CASE("Test parallel_for", "[parallel_for") +{ + bool passed = true; + + const size_t M = 10; + for (size_t N=10; N<10000000; N=size_t(2.1*N)) + { + /* sequentially calculate sum of squares */ + size_t sum0 = 0; + for (size_t i=0; i sum1(0); + parallel_for( size_t(0), size_t(N), size_t(1024), [&](const range& r) + { + size_t s = 0; + for (size_t i=r.begin(); i + +using namespace embree; + +namespace parallel_for_for_unit_test { + +TEST_CASE("Test parallel_for_for", "[parallel_for_for]") +{ + bool passed = true; + + /* create vector with random numbers */ + size_t sum0 = 0; + size_t K = 0; + const size_t M = 1000; + std::vector *> array2(M); + for (size_t i = 0; i < M; i++) + { + const size_t N = rand() % 1024; + K += N; + array2[i] = new std::vector(N); + for (size_t j = 0; j < N; j++) + sum0 += (*array2[i])[j] = rand(); + } + + /* array to test global index */ + std::vector> verify_k(K); + for (size_t i = 0; i < K; i++) + verify_k[i].store(0); + + /* add all numbers using parallel_for_for */ + std::atomic sum1(0); + parallel_for_for(array2, size_t(1), + [&](std::vector *v, const range &r, size_t k) -> size_t + { + size_t s = 0; + for (size_t i = r.begin(); i < r.end(); i++) + { + s += (*v)[i]; + verify_k[k++]++; + } + sum1 += s; + return sum1; + }); + passed &= (sum0 == sum1); + + /* check global index */ + for (size_t i = 0; i < K; i++) + passed &= (verify_k[i] == 1); + + /* delete vectors again */ + for (size_t i = 0; i < array2.size(); i++) + delete array2[i]; + + REQUIRE(passed); +} + +} diff --git a/tutorials/embree_tests/common/algorithms/parallel_for_for_prefix_sum.cpp b/tutorials/embree_tests/common/algorithms/parallel_for_for_prefix_sum.cpp new file mode 100644 index 0000000000..ffdac70612 --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/parallel_for_for_prefix_sum.cpp @@ -0,0 +1,85 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../../../external/catch.hpp" +#include "../common/algorithms/parallel_for_for_prefix_sum.h" + +#include + +using namespace embree; + +namespace parallel_for_for_prefix_sum_unit_test { + +TEST_CASE("Test parallel_for_for_prefix_sum", "[parallel_for_for_prefix_sum]") +{ + bool passed = true; + + /* create vector with random numbers */ + const size_t M = 10; + std::vector> flattened; + typedef std::vector *> ArrayArray; + ArrayArray array2(M); + size_t K = 0; + for (size_t i = 0; i < M; i++) + { + const size_t N = rand() % 10; + K += N; + array2[i] = new std::vector(N); + for (size_t j = 0; j < N; j++) + (*array2[i])[j] = rand() % 10; + } + + /* array to test global index */ + std::vector> verify_k(K); + for (size_t i = 0; i < K; i++) + verify_k[i].store(0); + + ParallelForForPrefixSumState state(array2, size_t(1)); + + /* dry run only counts */ + size_t S = parallel_for_for_prefix_sum0( state, array2, size_t(0), + [&](std::vector *v, const range &r, size_t k, size_t i) -> size_t + { + size_t s = 0; + for (size_t i=r.begin(); i *v, const range &r, size_t k, size_t i, const size_t base) -> size_t + { + size_t s = 0; + for (size_t i=r.begin(); i keys(N); + std::vector vals(N); + for (size_t i=0; i map; + map.init(keys,vals); + + /* check that all keys are properly mapped */ + for (size_t i=0; i array(N); + for (unsigned i=0; i= split; + } + + REQUIRE(passed); +} + +} diff --git a/tutorials/embree_tests/common/algorithms/parallel_prefix_sum.cpp b/tutorials/embree_tests/common/algorithms/parallel_prefix_sum.cpp new file mode 100644 index 0000000000..5821856cf6 --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/parallel_prefix_sum.cpp @@ -0,0 +1,45 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../../../external/catch.hpp" +#include "../common/algorithms/parallel_prefix_sum.h" + +using namespace embree; + +namespace parallel_prefix_sum_unit_test { + +TEST_CASE("Test parallel_prefix_sum", "[parallel_prefix_sum") +{ + bool passed = true; + const size_t M = 10; + + for (size_t N = 10; N < 10000000; N = size_t(2.1 * N)) + { + /* initialize array with random numbers */ + uint32_t sum0 = 0; + std::vector src(N); + for (size_t i = 0; i < N; i++) + { + sum0 += src[i] = rand(); + } + + /* calculate parallel prefix sum */ + std::vector dst(N); + for (auto &v : dst) + v = 0; + + for (size_t i = 0; i < M; i++) + { + uint32_t sum1 = parallel_prefix_sum(src, dst, N, 0, std::plus()); + passed &= (sum0 == sum1); + } + + /* check if prefix sum is correct */ + for (size_t i = 0, sum = 0; i < N; sum += src[i++]) + passed &= ((uint32_t)sum == dst[i]); + } + + REQUIRE(passed); +} + +} diff --git a/tutorials/embree_tests/common/algorithms/parallel_reduce.cpp b/tutorials/embree_tests/common/algorithms/parallel_reduce.cpp new file mode 100644 index 0000000000..1af3dcc219 --- /dev/null +++ b/tutorials/embree_tests/common/algorithms/parallel_reduce.cpp @@ -0,0 +1,45 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../../../external/catch.hpp" +#include "../common/algorithms/parallel_reduce.h" + + +using namespace embree; + +namespace parallel_reduce_unit_test { + +TEST_CASE ("Test parallel_reduce", "[parallel_reduce]") +{ + bool passed = false; + + const size_t M = 10; + for (size_t N=10; N<10000000; N=size_t(2.1*N)) + { + /* sequentially calculate sum of squares */ + size_t sum0 = 0; + for (size_t i=0; i& r) -> size_t + { + size_t s = 0; + for (size_t i=r.begin(); i unsorted(N); + for (size_t i=0; i sorted; + sorted.init(unsorted); + + /* check that all elements are in the set */ + for (size_t i=0; i +bool run_sort_test() +{ + bool passed = true; + const size_t M = 10; + + for (size_t N = 10; N < 1000000; N = size_t(2.1 * N)) + { + std::vector src(N); + memset(src.data(), 0, N * sizeof(Key)); + std::vector tmp(N); + memset(tmp.data(), 0, N * sizeof(Key)); + for (size_t i = 0; i < N; i++) + src[i] = uint64_t(rand()) * uint64_t(rand()); + + /* calculate checksum */ + Key sum0 = 0; + for (size_t i = 0; i < N; i++) + sum0 += src[i]; + + /* sort numbers */ + for (size_t i = 0; i < M; i++) + { + radix_sort(src.data(), tmp.data(), N); + } + + /* calculate checksum */ + Key sum1 = 0; + for (size_t i = 0; i < N; i++) + sum1 += src[i]; + if (sum0 != sum1) + passed = false; + + /* check if numbers are sorted */ + for (size_t i = 1; i < N; i++) + passed &= src[i - 1] <= src[i]; + } + + return passed; +} + +TEST_CASE("Test parallel_sort (uint32_t)", "[parallel_sort_uint32_t]") +{ + REQUIRE(run_sort_test()); +} + +TEST_CASE("Test parallel_sort (uint64_t)", "[parallel_sort_uint64_t]") +{ + REQUIRE(run_sort_test()); +} + +} diff --git a/tutorials/embree_tests/common/common_tests.cpp b/tutorials/embree_tests/common/common_tests.cpp new file mode 100644 index 0000000000..a960cf9d54 --- /dev/null +++ b/tutorials/embree_tests/common/common_tests.cpp @@ -0,0 +1,4 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "algorithms/algorithms_tests.cpp" diff --git a/tutorials/embree_tests/embree_tests.cpp b/tutorials/embree_tests/embree_tests.cpp index f955694586..b27b659e5a 100644 --- a/tutorials/embree_tests/embree_tests.cpp +++ b/tutorials/embree_tests/embree_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define CATCH_CONFIG_MAIN diff --git a/tutorials/embree_tests/kernels/common/common_tests.cpp b/tutorials/embree_tests/kernels/common/common_tests.cpp index c56addc8aa..abd0d6ecd7 100644 --- a/tutorials/embree_tests/kernels/common/common_tests.cpp +++ b/tutorials/embree_tests/kernels/common/common_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scene_line_segments_tests.cpp" diff --git a/tutorials/embree_tests/kernels/common/scene_line_segments_tests.cpp b/tutorials/embree_tests/kernels/common/scene_line_segments_tests.cpp index 4799db053f..5f6166e564 100644 --- a/tutorials/embree_tests/kernels/common/scene_line_segments_tests.cpp +++ b/tutorials/embree_tests/kernels/common/scene_line_segments_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // #include "../../../external/catch.hpp" diff --git a/tutorials/embree_tests/kernels/geometry/geometry_tests.cpp b/tutorials/embree_tests/kernels/geometry/geometry_tests.cpp index 8b81e39e2c..b8c41fe18d 100644 --- a/tutorials/embree_tests/kernels/geometry/geometry_tests.cpp +++ b/tutorials/embree_tests/kernels/geometry/geometry_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "sphere_intersector_tests.cpp" diff --git a/tutorials/embree_tests/kernels/geometry/sphere_intersector_tests.cpp b/tutorials/embree_tests/kernels/geometry/sphere_intersector_tests.cpp index 86a0eaae4c..e6047f6c66 100644 --- a/tutorials/embree_tests/kernels/geometry/sphere_intersector_tests.cpp +++ b/tutorials/embree_tests/kernels/geometry/sphere_intersector_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../../../external/catch.hpp" diff --git a/tutorials/embree_tests/kernels/kernels_tests.cpp b/tutorials/embree_tests/kernels/kernels_tests.cpp index fc5e122376..0ea59ff8b2 100644 --- a/tutorials/embree_tests/kernels/kernels_tests.cpp +++ b/tutorials/embree_tests/kernels/kernels_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/common_tests.cpp" diff --git a/tutorials/external/catch.hpp b/tutorials/external/catch.hpp index df14c357c8..8c4cfe478c 100644 --- a/tutorials/external/catch.hpp +++ b/tutorials/external/catch.hpp @@ -70,8 +70,6 @@ # include # if TARGET_OS_OSX == 1 # define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE # endif #elif defined(linux) || defined(__linux) || defined(__linux__) @@ -6028,7 +6026,11 @@ namespace Catch { #ifdef CATCH_PLATFORM_MAC - #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + #if defined(__X86_ASM__) + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + #else + #define CATCH_TRAP() raise(SIGTRAP) + #endif #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break @@ -8746,7 +8748,7 @@ namespace Catch { // 32kb for the alternate stack seems to be sufficient. However, this value // is experimentally determined, so that's not guaranteed. - constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; + constexpr static std::size_t sigStackSize = 32768; //32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; static SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, diff --git a/tutorials/find_embree/CMakeLists.txt b/tutorials/find_embree/CMakeLists.txt index 8c60e15108..9476fbd73c 100644 --- a/tutorials/find_embree/CMakeLists.txt +++ b/tutorials/find_embree/CMakeLists.txt @@ -1,10 +1,10 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 PROJECT(find_embree) CMAKE_MINIMUM_REQUIRED(VERSION 3.2.0) -FIND_PACKAGE(embree 3.0 REQUIRED) +FIND_PACKAGE(embree REQUIRED) ADD_EXECUTABLE(find_embree find_embree.cpp) TARGET_LINK_LIBRARIES(find_embree embree) @@ -16,7 +16,7 @@ IF (EMBREE_ISPC_SUPPORT) # this configures the ADD_EMBREE_ISPC_EXECUTABLE from Embree IF (ENABLE_ISPC_SUPPORT) SET(ISPC_TARGETS "sse2;sse4;avx;avx2") - SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../common/cmake ${CMAKE_MODULE_PATH}) + SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../common/cmake" ${CMAKE_MODULE_PATH}) INCLUDE(ispc) get_target_property(embree_include_dir embree INTERFACE_INCLUDE_DIRECTORIES) diff --git a/tutorials/find_embree/find_embree.cpp b/tutorials/find_embree/find_embree.cpp index 19249dc109..1478fa02db 100644 --- a/tutorials/find_embree/find_embree.cpp +++ b/tutorials/find_embree/find_embree.cpp @@ -1,8 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE #include //#include // use this to get _MM_SET_DENORMALS_ZERO_MODE when compiling for SSE3 or higher @@ -23,7 +23,7 @@ int main(int argc, char* argv[]) /* create new Embree device */ RTCDevice device = rtcNewDevice("verbose=1"); - /* ddelete device again */ + /* delete device again */ rtcReleaseDevice(device); return 0; diff --git a/tutorials/find_embree/find_embree_ispc.cpp b/tutorials/find_embree/find_embree_ispc.cpp index e4ce6ffbd3..4076ee645d 100644 --- a/tutorials/find_embree/find_embree_ispc.cpp +++ b/tutorials/find_embree/find_embree_ispc.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include diff --git a/tutorials/find_embree/find_embree_ispc.ispc b/tutorials/find_embree/find_embree_ispc.ispc index 4c2e7d8b7b..423a4f1c3f 100644 --- a/tutorials/find_embree/find_embree_ispc.ispc +++ b/tutorials/find_embree/find_embree_ispc.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include diff --git a/tutorials/grid_geometry/CMakeLists.txt b/tutorials/grid_geometry/CMakeLists.txt index cfa00bdd8b..44f4681372 100644 --- a/tutorials/grid_geometry/CMakeLists.txt +++ b/tutorials/grid_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/grid_geometry/grid_geometry.cpp b/tutorials/grid_geometry/grid_geometry.cpp index 3fd3c8b184..200b24cc20 100644 --- a/tutorials/grid_geometry/grid_geometry.cpp +++ b/tutorials/grid_geometry/grid_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "grid_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/grid_geometry/grid_geometry_device.cpp b/tutorials/grid_geometry/grid_geometry_device.cpp index b0e8e9713b..fa7a87ecea 100644 --- a/tutorials/grid_geometry/grid_geometry_device.cpp +++ b/tutorials/grid_geometry/grid_geometry_device.cpp @@ -1,7 +1,7 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.h" +#include "grid_geometry_device.h" namespace embree { @@ -10,8 +10,8 @@ namespace embree { #define GRID_RESOLUTION_X EDGE_LEVEL #define GRID_RESOLUTION_Y EDGE_LEVEL -/* scene data */ RTCScene g_scene = nullptr; +TutorialData data; #if 1 @@ -96,17 +96,6 @@ struct Grid unsigned int width, height; }; -struct GridMesh -{ - RTCGeometry geom; - RTCGeometry geomNormals; - RTCGrid* egrids; - Vec3fa* vertices; - Vec3fa* normals; -}; - -GridMesh gmesh; - float displacement(const Vec3fa& P) { float dN = 0.0f; @@ -539,17 +528,18 @@ unsigned int addGroundPlane (RTCScene scene_i) extern "C" void device_init (char* cfg) { /* create scene */ - g_scene = rtcNewScene(g_device); - rtcSetSceneFlags(g_scene,RTC_SCENE_FLAG_ROBUST); + TutorialData_Constructor(&data); + g_scene = data.g_scene = rtcNewScene(g_device); + rtcSetSceneFlags(data.g_scene,RTC_SCENE_FLAG_ROBUST); - addGroundPlane(g_scene); + addGroundPlane(data.g_scene); - createGridGeometry(gmesh); - rtcAttachGeometry(g_scene,gmesh.geom); + createGridGeometry(data.gmesh); + rtcAttachGeometry(data.g_scene,data.gmesh.geom); //rtcAttachGeometry(g_scene,gmesh.geomNormals); - + /* commit changes to scene */ - rtcCommitScene (g_scene); + rtcCommitScene (data.g_scene); } Vec3fa mylerp(float f, const Vec3fa& a, const Vec3fa& b) { // FIXME: use lerpr, need to make ISPC lerpr and C++ lerpr compatible first @@ -557,18 +547,21 @@ Vec3fa mylerp(float f, const Vec3fa& a, const Vec3fa& b) { // FIXME: use lerpr, } /* task that renders a single screen tile */ -Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& stats) +Vec3fa renderPixelStandard(const TutorialData& data, + float x, float y, + const ISPCCamera& camera, + RayStats& stats) { RTCIntersectContext context; rtcInitIntersectContext(&context); - + /* initialize ray */ Ray ray(Vec3fa(camera.xfm.p), Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf); /* intersect ray with scene */ - rtcIntersect1(g_scene,&context,RTCRayHit_(ray)); + rtcIntersect1(data.g_scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); - + /* shade pixels */ Vec3fa color = Vec3fa(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) @@ -580,20 +573,20 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& if (ray.geomID == 1) { - unsigned int startVertexID = gmesh.egrids[ray.primID].startVertexID; - int width = gmesh.egrids[ray.primID].width; - int height = gmesh.egrids[ray.primID].height; - unsigned int stride = gmesh.egrids[ray.primID].stride; + unsigned int startVertexID = data.gmesh.egrids[ray.primID].startVertexID; + int width = data.gmesh.egrids[ray.primID].width; + int height = data.gmesh.egrids[ray.primID].height; + unsigned int stride = data.gmesh.egrids[ray.primID].stride; float U = ray.u*(width-1); float V = ray.v*(height-1); int x = min((int)floor(U),width -2); int y = min((int)floor(V),height-2); float u = U-x; float v = V-y; - Vec3fa N00 = gmesh.normals[startVertexID+(y+0)*stride+(x+0)]; - Vec3fa N01 = gmesh.normals[startVertexID+(y+0)*stride+(x+1)]; - Vec3fa N10 = gmesh.normals[startVertexID+(y+1)*stride+(x+0)]; - Vec3fa N11 = gmesh.normals[startVertexID+(y+1)*stride+(x+1)]; + Vec3fa N00 = data.gmesh.normals[startVertexID+(y+0)*stride+(x+0)]; + Vec3fa N01 = data.gmesh.normals[startVertexID+(y+0)*stride+(x+1)]; + Vec3fa N10 = data.gmesh.normals[startVertexID+(y+1)*stride+(x+0)]; + Vec3fa N11 = data.gmesh.normals[startVertexID+(y+1)*stride+(x+1)]; Vec3fa N0 = mylerp(u,N00,N01); Vec3fa N1 = mylerp(u,N10,N11); Ng = normalize(mylerp(v,N0,N1)); @@ -604,7 +597,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Ray shadow(ray.org + ray.tfar*ray.dir, neg(lightDir), 0.001f, inf, 0.0f); /* trace shadow ray */ - rtcOccluded1(g_scene,&context,RTCRay_(shadow)); + rtcOccluded1(data.g_scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -635,7 +628,7 @@ void renderTileStandard(int taskIndex, for (unsigned int y=y0; yg_scene = nullptr; + This->gmesh.geom = nullptr; + This->gmesh.geomNormals = nullptr; + This->gmesh.egrids = nullptr; + This->gmesh.vertices = nullptr; + This->gmesh.normals = nullptr; +} + +void TutorialData_Destructor(TutorialData* This) +{ + alignedFree(This->gmesh.normals); + rtcReleaseGeometry(This->gmesh.geom); + rtcReleaseGeometry(This->gmesh.geomNormals); + rtcReleaseScene (This->g_scene); This->g_scene = nullptr; +} + +} // namespace embree diff --git a/tutorials/grid_geometry/grid_geometry_device.ispc b/tutorials/grid_geometry/grid_geometry_device.ispc index 4b2c279e9d..07a925b980 100644 --- a/tutorials/grid_geometry/grid_geometry_device.ispc +++ b/tutorials/grid_geometry/grid_geometry_device.ispc @@ -1,15 +1,15 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.isph" +#include "grid_geometry_device.isph" /* configuration */ #define EDGE_LEVEL 257 #define GRID_RESOLUTION_X EDGE_LEVEL #define GRID_RESOLUTION_Y EDGE_LEVEL -/* scene data */ RTCScene g_scene = NULL; +uniform TutorialData data; #if 1 @@ -94,17 +94,6 @@ struct Grid unsigned int width, height; }; -struct GridMesh -{ - RTCGeometry geom; - RTCGeometry geomNormals; - uniform RTCGrid* uniform egrids; - uniform Vec3fa* uniform vertices; - uniform Vec3f* uniform normals; -}; - -uniform GridMesh gmesh; - float displacement(const Vec3f& P) { float dN = 0.0f; @@ -537,17 +526,18 @@ uniform unsigned int addGroundPlane (RTCScene scene_i) export void device_init (uniform int8* uniform cfg) { /* create scene */ - g_scene = rtcNewScene(g_device); - rtcSetSceneFlags(g_scene,RTC_SCENE_FLAG_ROBUST); + TutorialData_Constructor(&data); + g_scene = data.g_scene = rtcNewScene(g_device); + rtcSetSceneFlags(data.g_scene,RTC_SCENE_FLAG_ROBUST); - addGroundPlane(g_scene); + addGroundPlane(data.g_scene); - createGridGeometry(gmesh); - rtcAttachGeometry(g_scene,gmesh.geom); + createGridGeometry(data.gmesh); + rtcAttachGeometry(data.g_scene,data.gmesh.geom); //rtcAttachGeometry(g_scene,gmesh.geomNormals); - + /* commit changes to scene */ - rtcCommitScene (g_scene); + rtcCommitScene (data.g_scene); } Vec3f mylerp(float f, const Vec3f& a, const Vec3f& b) { // FIXME: use lerp, need to make ISPC lerp and C++ lerp compatible first @@ -555,18 +545,21 @@ Vec3f mylerp(float f, const Vec3f& a, const Vec3f& b) { // FIXME: use lerp, need } /* task that renders a single screen tile */ -Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, uniform RayStats& stats) +Vec3f renderPixelStandard(const uniform TutorialData& data, + float x, float y, + const uniform ISPCCamera& camera, + uniform RayStats& stats) { uniform RTCIntersectContext context; rtcInitIntersectContext(&context); - + /* initialize ray */ Ray ray = make_Ray(make_Vec3f(camera.xfm.p), make_Vec3f(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf); /* intersect ray with scene */ - rtcIntersectV(g_scene,&context,RTCRayHit_(ray)); + rtcIntersectV(data.g_scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); - + /* shade pixels */ Vec3f color = make_Vec3f(0.0f); if (ray.geomID != RTC_INVALID_GEOMETRY_ID) @@ -578,20 +571,20 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un if (ray.geomID == 1) { - unsigned int startVertexID = gmesh.egrids[ray.primID].startVertexID; - int width = gmesh.egrids[ray.primID].width; - int height = gmesh.egrids[ray.primID].height; - unsigned int stride = gmesh.egrids[ray.primID].stride; + unsigned int startVertexID = data.gmesh.egrids[ray.primID].startVertexID; + int width = data.gmesh.egrids[ray.primID].width; + int height = data.gmesh.egrids[ray.primID].height; + unsigned int stride = data.gmesh.egrids[ray.primID].stride; float U = ray.u*(width-1); float V = ray.v*(height-1); int x = min((int)floor(U),width -2); int y = min((int)floor(V),height-2); float u = U-x; float v = V-y; - Vec3f N00 = gmesh.normals[startVertexID+(y+0)*stride+(x+0)]; - Vec3f N01 = gmesh.normals[startVertexID+(y+0)*stride+(x+1)]; - Vec3f N10 = gmesh.normals[startVertexID+(y+1)*stride+(x+0)]; - Vec3f N11 = gmesh.normals[startVertexID+(y+1)*stride+(x+1)]; + Vec3f N00 = data.gmesh.normals[startVertexID+(y+0)*stride+(x+0)]; + Vec3f N01 = data.gmesh.normals[startVertexID+(y+0)*stride+(x+1)]; + Vec3f N10 = data.gmesh.normals[startVertexID+(y+1)*stride+(x+0)]; + Vec3f N11 = data.gmesh.normals[startVertexID+(y+1)*stride+(x+1)]; Vec3f N0 = mylerp(u,N00,N01); Vec3f N1 = mylerp(u,N10,N11); Ng = normalize(mylerp(v,N0,N1)); @@ -602,7 +595,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Ray shadow = make_Ray(ray.org + ray.tfar*ray.dir, neg(lightDir), 0.001f, inf, 0.0f); /* trace shadow ray */ - rtcOccludedV(g_scene,&context,RTCRay_(shadow)); + rtcOccludedV(data.g_scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -633,7 +626,7 @@ void renderTileStandard(uniform int taskIndex, foreach_tiled (y = y0 ... y1, x = x0 ... x1) { /* calculate pixel color */ - Vec3f color = renderPixelStandard((float)x,(float)y,camera,g_stats[threadIndex]); + Vec3f color = renderPixelStandard(data,(float)x,(float)y,camera,g_stats[threadIndex]); /* write color to framebuffer */ unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); @@ -679,8 +672,5 @@ export void device_render (uniform int* uniform pixels, /* called by the C++ code for cleanup */ export void device_cleanup () { - delete[] gmesh.normals; - rtcReleaseGeometry(gmesh.geom); - rtcReleaseGeometry(gmesh.geomNormals); - rtcReleaseScene (g_scene); g_scene = NULL; + TutorialData_Destructor(&data); } diff --git a/tutorials/grid_geometry/grid_geometry_device.isph b/tutorials/grid_geometry/grid_geometry_device.isph new file mode 100644 index 0000000000..a7a00d2530 --- /dev/null +++ b/tutorials/grid_geometry/grid_geometry_device.isph @@ -0,0 +1,41 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../common/tutorial/tutorial_device.isph" +#include "../common/tutorial/scene_device.h" + +struct GridMesh +{ + RTCGeometry geom; + RTCGeometry geomNormals; + uniform RTCGrid* uniform egrids; + uniform Vec3fa* uniform vertices; + uniform Vec3f* uniform normals; +}; + + +struct TutorialData +{ + /* scene data */ + RTCScene g_scene; + + uniform GridMesh gmesh; +}; + +void TutorialData_Constructor(uniform TutorialData* uniform This) +{ + This->g_scene = NULL; + This->gmesh.geom = NULL; + This->gmesh.geomNormals = NULL; + This->gmesh.egrids = NULL; + This->gmesh.vertices = NULL; + This->gmesh.normals = NULL; +} + +void TutorialData_Destructor(uniform TutorialData* uniform This) +{ + delete[] This->gmesh.normals; + rtcReleaseGeometry(This->gmesh.geom); + rtcReleaseGeometry(This->gmesh.geomNormals); + rtcReleaseScene (This->g_scene); This->g_scene = NULL; +} diff --git a/tutorials/hair_geometry/CMakeLists.txt b/tutorials/hair_geometry/CMakeLists.txt index bc7acaf4da..3ded100e0b 100644 --- a/tutorials/hair_geometry/CMakeLists.txt +++ b/tutorials/hair_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/hair_geometry/hair_geometry.cpp b/tutorials/hair_geometry/hair_geometry.cpp index de6c4714d3..b8fea471ab 100644 --- a/tutorials/hair_geometry/hair_geometry.cpp +++ b/tutorials/hair_geometry/hair_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,7 +20,7 @@ namespace embree void postParseCommandLine() override { /* load default scene if none specified */ - if (scene->size() == 0 && sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/furBall_A.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } @@ -30,5 +31,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "hair_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/hair_geometry/hair_geometry_device.cpp b/tutorials/hair_geometry/hair_geometry_device.cpp index f0de6b6aca..52365919ec 100644 --- a/tutorials/hair_geometry/hair_geometry_device.cpp +++ b/tutorials/hair_geometry/hair_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.h" @@ -69,7 +69,7 @@ void convertHairSet(ISPCHairSet* hair, RTCScene scene_out) RTCScene convertScene(ISPCScene* scene_in) { /* create scene */ - RTCScene scene_out = rtcNewScene(g_device); + RTCScene scene_out = scene_in->scene; for (unsigned int i=0; inumGeometries; i++) { diff --git a/tutorials/hair_geometry/hair_geometry_device.ispc b/tutorials/hair_geometry/hair_geometry_device.ispc index a30f019f46..e7549c5333 100644 --- a/tutorials/hair_geometry/hair_geometry_device.ispc +++ b/tutorials/hair_geometry/hair_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.isph" @@ -67,7 +67,7 @@ void convertHairSet(uniform ISPCHairSet* uniform hair, RTCScene scene_out) RTCScene convertScene(uniform ISPCScene* uniform scene_in) { /* create scene */ - RTCScene scene_out = rtcNewScene(g_device); + RTCScene scene_out = scene_in->scene; for (uniform unsigned int i=0; inumGeometries; i++) { diff --git a/tutorials/instanced_geometry/CMakeLists.txt b/tutorials/instanced_geometry/CMakeLists.txt index 02b4ed0731..7a9ef28ae8 100644 --- a/tutorials/instanced_geometry/CMakeLists.txt +++ b/tutorials/instanced_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/instanced_geometry/instanced_geometry.cpp b/tutorials/instanced_geometry/instanced_geometry.cpp index 6c5cd31999..0c5f1caa4c 100644 --- a/tutorials/instanced_geometry/instanced_geometry.cpp +++ b/tutorials/instanced_geometry/instanced_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "multi_instanced_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/instanced_geometry/instanced_geometry_device.cpp b/tutorials/instanced_geometry/instanced_geometry_device.cpp index 1ab97072b5..5c61d04a85 100644 --- a/tutorials/instanced_geometry/instanced_geometry_device.cpp +++ b/tutorials/instanced_geometry/instanced_geometry_device.cpp @@ -1,13 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.h" +#include "instanced_geometry_device.h" namespace embree { const int numPhi = 5; const int numTheta = 2*numPhi; +RTCScene g_scene = nullptr; +TutorialData data; + unsigned int createTriangulatedSphere (RTCScene scene, const Vec3fa& p, float r) { /* create triangle mesh */ @@ -88,82 +91,71 @@ unsigned int createGroundPlane (RTCScene scene) return geomID; } -/* scene data */ -RTCScene g_scene = nullptr; -RTCScene g_scene1 = nullptr; - -RTCGeometry g_instance0 = nullptr; -RTCGeometry g_instance1 = nullptr; -RTCGeometry g_instance2 = nullptr; -RTCGeometry g_instance3 = nullptr; -AffineSpace3fa instance_xfm[4]; -LinearSpace3fa normal_xfm[4]; - -Vec3fa colors[4][4]; - /* called by the C++ code for initialization */ extern "C" void device_init (char* cfg) { + TutorialData_Constructor(&data); + /* create scene */ - g_scene = rtcNewScene(g_device); - rtcSetSceneBuildQuality(g_scene,RTC_BUILD_QUALITY_LOW); - rtcSetSceneFlags(g_scene,RTC_SCENE_FLAG_DYNAMIC); + data.g_scene = g_scene = rtcNewScene(g_device); + rtcSetSceneBuildQuality(data.g_scene,RTC_BUILD_QUALITY_LOW); + rtcSetSceneFlags(data.g_scene,RTC_SCENE_FLAG_DYNAMIC); /* create scene with 4 triangulated spheres */ - g_scene1 = rtcNewScene(g_device); - createTriangulatedSphere(g_scene1,Vec3fa( 0, 0,+1),0.5f); - createTriangulatedSphere(g_scene1,Vec3fa(+1, 0, 0),0.5f); - createTriangulatedSphere(g_scene1,Vec3fa( 0, 0,-1),0.5f); - createTriangulatedSphere(g_scene1,Vec3fa(-1, 0, 0),0.5f); - rtcCommitScene (g_scene1); + data.g_scene1 = rtcNewScene(g_device); + createTriangulatedSphere(data.g_scene1,Vec3fa( 0, 0,+1),0.5f); + createTriangulatedSphere(data.g_scene1,Vec3fa(+1, 0, 0),0.5f); + createTriangulatedSphere(data.g_scene1,Vec3fa( 0, 0,-1),0.5f); + createTriangulatedSphere(data.g_scene1,Vec3fa(-1, 0, 0),0.5f); + rtcCommitScene (data.g_scene1); /* instantiate geometry */ - g_instance0 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance0,g_scene1); - rtcSetGeometryTimeStepCount(g_instance0,1); - g_instance1 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance1,g_scene1); - rtcSetGeometryTimeStepCount(g_instance1,1); - g_instance2 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance2,g_scene1); - rtcSetGeometryTimeStepCount(g_instance2,1); - g_instance3 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance3,g_scene1); - rtcSetGeometryTimeStepCount(g_instance3,1); - rtcAttachGeometry(g_scene,g_instance0); - rtcAttachGeometry(g_scene,g_instance1); - rtcAttachGeometry(g_scene,g_instance2); - rtcAttachGeometry(g_scene,g_instance3); - rtcReleaseGeometry(g_instance0); - rtcReleaseGeometry(g_instance1); - rtcReleaseGeometry(g_instance2); - rtcReleaseGeometry(g_instance3); - createGroundPlane(g_scene); + data.g_instance0 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance0,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance0,1); + data.g_instance1 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance1,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance1,1); + data.g_instance2 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance2,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance2,1); + data.g_instance3 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance3,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance3,1); + rtcAttachGeometry(data.g_scene,data.g_instance0); + rtcAttachGeometry(data.g_scene,data.g_instance1); + rtcAttachGeometry(data.g_scene,data.g_instance2); + rtcAttachGeometry(data.g_scene,data.g_instance3); + rtcReleaseGeometry(data.g_instance0); + rtcReleaseGeometry(data.g_instance1); + rtcReleaseGeometry(data.g_instance2); + rtcReleaseGeometry(data.g_instance3); + createGroundPlane(data.g_scene); /* set all colors */ - colors[0][0] = Vec3fa(0.25f, 0.f, 0.f); - colors[0][1] = Vec3fa(0.50f, 0.f, 0.f); - colors[0][2] = Vec3fa(0.75f, 0.f, 0.f); - colors[0][3] = Vec3fa(1.00f, 0.f, 0.f); - - colors[1][0] = Vec3fa(0.f, 0.25f, 0.f); - colors[1][1] = Vec3fa(0.f, 0.50f, 0.f); - colors[1][2] = Vec3fa(0.f, 0.75f, 0.f); - colors[1][3] = Vec3fa(0.f, 1.00f, 0.f); - - colors[2][0] = Vec3fa(0.f, 0.f, 0.25f); - colors[2][1] = Vec3fa(0.f, 0.f, 0.50f); - colors[2][2] = Vec3fa(0.f, 0.f, 0.75f); - colors[2][3] = Vec3fa(0.f, 0.f, 1.00f); - - colors[3][0] = Vec3fa(0.25f, 0.25f, 0.f); - colors[3][1] = Vec3fa(0.50f, 0.50f, 0.f); - colors[3][2] = Vec3fa(0.75f, 0.75f, 0.f); - colors[3][3] = Vec3fa(1.00f, 1.00f, 0.f); + data.colors[0][0] = Vec3fa(0.25f, 0.f, 0.f); + data.colors[0][1] = Vec3fa(0.50f, 0.f, 0.f); + data.colors[0][2] = Vec3fa(0.75f, 0.f, 0.f); + data.colors[0][3] = Vec3fa(1.00f, 0.f, 0.f); + + data.colors[1][0] = Vec3fa(0.f, 0.25f, 0.f); + data.colors[1][1] = Vec3fa(0.f, 0.50f, 0.f); + data.colors[1][2] = Vec3fa(0.f, 0.75f, 0.f); + data.colors[1][3] = Vec3fa(0.f, 1.00f, 0.f); + + data.colors[2][0] = Vec3fa(0.f, 0.f, 0.25f); + data.colors[2][1] = Vec3fa(0.f, 0.f, 0.50f); + data.colors[2][2] = Vec3fa(0.f, 0.f, 0.75f); + data.colors[2][3] = Vec3fa(0.f, 0.f, 1.00f); + + data.colors[3][0] = Vec3fa(0.25f, 0.25f, 0.f); + data.colors[3][1] = Vec3fa(0.50f, 0.50f, 0.f); + data.colors[3][2] = Vec3fa(0.75f, 0.75f, 0.f); + data.colors[3][3] = Vec3fa(1.00f, 1.00f, 0.f); } /* task that renders a single screen tile */ -Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& stats) +Vec3fa renderPixelStandard(const TutorialData& data, float x, float y, const ISPCCamera& camera, RayStats& stats) { RTCIntersectContext context; rtcInitIntersectContext(&context); @@ -172,7 +164,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Ray ray(Vec3fa(camera.xfm.p), Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf); /* intersect ray with scene */ - rtcIntersect1(g_scene,&context,RTCRayHit_(ray)); + rtcIntersect1(data.g_scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); /* shade pixels */ @@ -182,13 +174,13 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& /* calculate shading normal in world space */ Vec3fa Ns = ray.Ng; if (ray.instID[0] != RTC_INVALID_GEOMETRY_ID) - Ns = xfmVector(normal_xfm[ray.instID[0]],Ns); + Ns = xfmVector(data.normal_xfm[ray.instID[0]],Ns); Ns = normalize(Ns); /* calculate diffuse color of geometries */ Vec3fa diffuse = Vec3fa(1,1,1); if (ray.instID[0] != RTC_INVALID_GEOMETRY_ID) - diffuse = colors[ray.instID[0]][ray.geomID]; + diffuse = data.colors[ray.instID[0]][ray.geomID]; color = color + diffuse*0.5; /* initialize shadow ray */ @@ -196,7 +188,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Ray shadow(ray.org + ray.tfar*ray.dir, neg(lightDir), 0.001f, inf); /* trace shadow ray */ - rtcOccluded1(g_scene,&context,RTCRay_(shadow)); + rtcOccluded1(data.g_scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -227,7 +219,7 @@ void renderTileStandard(int taskIndex, for (unsigned int y=y0; y= 0.0f) { color_stream[N] = color_stream[N] + diffuse*clamp(-dot(lightDir,Ns),0.0f,1.0f); @@ -441,35 +433,34 @@ extern "C" void device_render (int* pixels, xfm.vy = Vec3fa(0,1,0); xfm.vz = Vec3fa(-sin(t1),0,cos(t1)); - /* calculate transformations to move instances in cirle */ + /* calculate transformations to move instances in circle */ for (int i=0; i<4; i++) { float t = t0+i*2.0f*float(M_PI)/4.0f; - instance_xfm[i] = AffineSpace3fa(xfm,2.2f*Vec3fa(+cos(t),0.0f,+sin(t))); + data.instance_xfm[i] = AffineSpace3fa(xfm,2.2f*Vec3fa(+cos(t),0.0f,+sin(t))); } /* calculate transformations to properly transform normals */ for (int i=0; i<4; i++) - normal_xfm[i] = transposed(rcp(instance_xfm[i].l)); + data.normal_xfm[i] = transposed(rcp(data.instance_xfm[i].l)); /* set instance transformations */ - rtcSetGeometryTransform(g_instance0,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&instance_xfm[0]); - rtcSetGeometryTransform(g_instance1,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&instance_xfm[1]); - rtcSetGeometryTransform(g_instance2,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&instance_xfm[2]); - rtcSetGeometryTransform(g_instance3,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&instance_xfm[3]); + rtcSetGeometryTransform(data.g_instance0,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&data.instance_xfm[0]); + rtcSetGeometryTransform(data.g_instance1,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&data.instance_xfm[1]); + rtcSetGeometryTransform(data.g_instance2,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&data.instance_xfm[2]); + rtcSetGeometryTransform(data.g_instance3,0,RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,(float*)&data.instance_xfm[3]); /* update scene */ - rtcCommitGeometry(g_instance0); - rtcCommitGeometry(g_instance1); - rtcCommitGeometry(g_instance2); - rtcCommitGeometry(g_instance3); - rtcCommitScene (g_scene); + rtcCommitGeometry(data.g_instance0); + rtcCommitGeometry(data.g_instance1); + rtcCommitGeometry(data.g_instance2); + rtcCommitGeometry(data.g_instance3); + rtcCommitScene (data.g_scene); } /* called by the C++ code for cleanup */ extern "C" void device_cleanup () { - rtcReleaseScene (g_scene); g_scene = nullptr; - rtcReleaseScene (g_scene1); g_scene1 = nullptr; + TutorialData_Destructor(&data); } } // namespace embree diff --git a/tutorials/instanced_geometry/instanced_geometry_device.h b/tutorials/instanced_geometry/instanced_geometry_device.h new file mode 100644 index 0000000000..04cb652d86 --- /dev/null +++ b/tutorials/instanced_geometry/instanced_geometry_device.h @@ -0,0 +1,43 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../common/tutorial/tutorial_device.h" +#include "../common/math/random_sampler.h" +#include "../common/core/differential_geometry.h" +#include "../common/tutorial/scene_device.h" + +namespace embree { + +struct TutorialData +{ + /* scene data */ + RTCScene g_scene; + RTCScene g_scene1; + + RTCGeometry g_instance0; + RTCGeometry g_instance1; + RTCGeometry g_instance2; + RTCGeometry g_instance3; + AffineSpace3fa instance_xfm[4]; + LinearSpace3fa normal_xfm[4]; + + Vec3fa colors[4][4]; +}; + +void TutorialData_Constructor(TutorialData* This) +{ + This->g_scene = nullptr; + This->g_scene1 = nullptr; + This->g_instance0 = nullptr; + This->g_instance1 = nullptr; + This->g_instance2 = nullptr; + This->g_instance3 = nullptr; +} + +void TutorialData_Destructor(TutorialData* This) +{ + rtcReleaseScene (This->g_scene); This->g_scene = nullptr; + rtcReleaseScene (This->g_scene1); This->g_scene1 = nullptr; +} + +} // namespace embree diff --git a/tutorials/instanced_geometry/instanced_geometry_device.ispc b/tutorials/instanced_geometry/instanced_geometry_device.ispc index 17c8df02bf..619f6de7f2 100644 --- a/tutorials/instanced_geometry/instanced_geometry_device.ispc +++ b/tutorials/instanced_geometry/instanced_geometry_device.ispc @@ -1,11 +1,14 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.isph" +#include "instanced_geometry_device.isph" const uniform int numPhi = 5; const uniform int numTheta = 2*numPhi; +RTCScene g_scene = NULL; +uniform TutorialData data; + uniform unsigned int createTriangulatedSphere (RTCScene scene, const uniform Vec3f& p, uniform float r) { /* create triangle mesh */ @@ -86,82 +89,71 @@ uniform unsigned int createGroundPlane (RTCScene scene) return geomID; } -/* scene data */ -RTCScene g_scene = NULL; -RTCScene g_scene1 = NULL; - -RTCGeometry g_instance0 = NULL; -RTCGeometry g_instance1 = NULL; -RTCGeometry g_instance2 = NULL; -RTCGeometry g_instance3 = NULL; -uniform AffineSpace3f instance_xfm[4]; -uniform LinearSpace3f normal_xfm[4]; - -uniform Vec3f colors[4][4]; - /* called by the C++ code for initialization */ export void device_init (uniform int8* uniform cfg) { + TutorialData_Constructor(&data); + /* create scene */ - g_scene = rtcNewScene(g_device); - rtcSetSceneBuildQuality(g_scene,RTC_BUILD_QUALITY_LOW); - rtcSetSceneFlags(g_scene,RTC_SCENE_FLAG_DYNAMIC); + data.g_scene = g_scene = rtcNewScene(g_device); + rtcSetSceneBuildQuality(data.g_scene,RTC_BUILD_QUALITY_LOW); + rtcSetSceneFlags(data.g_scene,RTC_SCENE_FLAG_DYNAMIC); /* create scene with 4 triangulated spheres */ - g_scene1 = rtcNewScene(g_device); - createTriangulatedSphere(g_scene1,make_Vec3f( 0, 0,+1),0.5f); - createTriangulatedSphere(g_scene1,make_Vec3f(+1, 0, 0),0.5f); - createTriangulatedSphere(g_scene1,make_Vec3f( 0, 0,-1),0.5f); - createTriangulatedSphere(g_scene1,make_Vec3f(-1, 0, 0),0.5f); - rtcCommitScene (g_scene1); + data.g_scene1 = rtcNewScene(g_device); + createTriangulatedSphere(data.g_scene1,make_Vec3f( 0, 0,+1),0.5f); + createTriangulatedSphere(data.g_scene1,make_Vec3f(+1, 0, 0),0.5f); + createTriangulatedSphere(data.g_scene1,make_Vec3f( 0, 0,-1),0.5f); + createTriangulatedSphere(data.g_scene1,make_Vec3f(-1, 0, 0),0.5f); + rtcCommitScene (data.g_scene1); /* instantiate geometry */ - g_instance0 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance0,g_scene1); - rtcSetGeometryTimeStepCount(g_instance0,1); - g_instance1 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance1,g_scene1); - rtcSetGeometryTimeStepCount(g_instance1,1); - g_instance2 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance2,g_scene1); - rtcSetGeometryTimeStepCount(g_instance2,1); - g_instance3 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(g_instance3,g_scene1); - rtcSetGeometryTimeStepCount(g_instance3,1); - rtcAttachGeometry(g_scene,g_instance0); - rtcAttachGeometry(g_scene,g_instance1); - rtcAttachGeometry(g_scene,g_instance2); - rtcAttachGeometry(g_scene,g_instance3); - rtcReleaseGeometry(g_instance0); - rtcReleaseGeometry(g_instance1); - rtcReleaseGeometry(g_instance2); - rtcReleaseGeometry(g_instance3); - createGroundPlane(g_scene); + data.g_instance0 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance0,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance0,1); + data.g_instance1 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance1,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance1,1); + data.g_instance2 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance2,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance2,1); + data.g_instance3 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(data.g_instance3,data.g_scene1); + rtcSetGeometryTimeStepCount(data.g_instance3,1); + rtcAttachGeometry(data.g_scene,data.g_instance0); + rtcAttachGeometry(data.g_scene,data.g_instance1); + rtcAttachGeometry(data.g_scene,data.g_instance2); + rtcAttachGeometry(data.g_scene,data.g_instance3); + rtcReleaseGeometry(data.g_instance0); + rtcReleaseGeometry(data.g_instance1); + rtcReleaseGeometry(data.g_instance2); + rtcReleaseGeometry(data.g_instance3); + createGroundPlane(data.g_scene); /* set all colors */ - colors[0][0] = make_Vec3f(0.25f, 0.f, 0.f); - colors[0][1] = make_Vec3f(0.50f, 0.f, 0.f); - colors[0][2] = make_Vec3f(0.75f, 0.f, 0.f); - colors[0][3] = make_Vec3f(1.00f, 0.f, 0.f); - - colors[1][0] = make_Vec3f(0.f, 0.25f, 0.f); - colors[1][1] = make_Vec3f(0.f, 0.50f, 0.f); - colors[1][2] = make_Vec3f(0.f, 0.75f, 0.f); - colors[1][3] = make_Vec3f(0.f, 1.00f, 0.f); - - colors[2][0] = make_Vec3f(0.f, 0.f, 0.25f); - colors[2][1] = make_Vec3f(0.f, 0.f, 0.50f); - colors[2][2] = make_Vec3f(0.f, 0.f, 0.75f); - colors[2][3] = make_Vec3f(0.f, 0.f, 1.00f); - - colors[3][0] = make_Vec3f(0.25f, 0.25f, 0.f); - colors[3][1] = make_Vec3f(0.50f, 0.50f, 0.f); - colors[3][2] = make_Vec3f(0.75f, 0.75f, 0.f); - colors[3][3] = make_Vec3f(1.00f, 1.00f, 0.f); + data.colors[0][0] = make_Vec3f(0.25f, 0.f, 0.f); + data.colors[0][1] = make_Vec3f(0.50f, 0.f, 0.f); + data.colors[0][2] = make_Vec3f(0.75f, 0.f, 0.f); + data.colors[0][3] = make_Vec3f(1.00f, 0.f, 0.f); + + data.colors[1][0] = make_Vec3f(0.f, 0.25f, 0.f); + data.colors[1][1] = make_Vec3f(0.f, 0.50f, 0.f); + data.colors[1][2] = make_Vec3f(0.f, 0.75f, 0.f); + data.colors[1][3] = make_Vec3f(0.f, 1.00f, 0.f); + + data.colors[2][0] = make_Vec3f(0.f, 0.f, 0.25f); + data.colors[2][1] = make_Vec3f(0.f, 0.f, 0.50f); + data.colors[2][2] = make_Vec3f(0.f, 0.f, 0.75f); + data.colors[2][3] = make_Vec3f(0.f, 0.f, 1.00f); + + data.colors[3][0] = make_Vec3f(0.25f, 0.25f, 0.f); + data.colors[3][1] = make_Vec3f(0.50f, 0.50f, 0.f); + data.colors[3][2] = make_Vec3f(0.75f, 0.75f, 0.f); + data.colors[3][3] = make_Vec3f(1.00f, 1.00f, 0.f); } /* task that renders a single screen tile */ -Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, uniform RayStats& stats) +Vec3f renderPixelStandard(const uniform TutorialData& data, float x, float y, const uniform ISPCCamera& camera, uniform RayStats& stats) { uniform RTCIntersectContext context; rtcInitIntersectContext(&context); @@ -170,7 +162,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Ray ray = make_Ray(make_Vec3f(camera.xfm.p), make_Vec3f(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf); /* intersect ray with scene */ - rtcIntersectV(g_scene,&context,RTCRayHit_(ray)); + rtcIntersectV(data.g_scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); /* shade pixels */ @@ -180,13 +172,13 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un /* calculate shading normal in world space */ Vec3f Ns = ray.Ng; if (ray.instID[0] != RTC_INVALID_GEOMETRY_ID) - Ns = xfmVector(normal_xfm[ray.instID[0]],Ns); + Ns = xfmVector(data.normal_xfm[ray.instID[0]],Ns); Ns = normalize(Ns); /* calculate diffuse color of geometries */ Vec3f diffuse = make_Vec3f(1,1,1); if (ray.instID[0] != RTC_INVALID_GEOMETRY_ID) - diffuse = colors[ray.instID[0]][ray.geomID]; + diffuse = data.colors[ray.instID[0]][ray.geomID]; color = color + diffuse*0.5; /* initialize shadow ray */ @@ -194,7 +186,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Ray shadow = make_Ray(ray.org + ray.tfar*ray.dir, neg(lightDir), 0.001f, inf); /* trace shadow ray */ - rtcOccludedV(g_scene,&context,RTCRay_(shadow)); + rtcOccludedV(data.g_scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -225,7 +217,7 @@ void renderTileStandard(uniform int taskIndex, foreach_tiled (y = y0 ... y1, x = x0 ... x1) { /* calculate pixel color */ - Vec3f color = renderPixelStandard((float)x,(float)y,camera,g_stats[threadIndex]); + Vec3f color = renderPixelStandard(data, (float)x,(float)y,camera,g_stats[threadIndex]); /* write color to framebuffer */ unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); @@ -289,7 +281,7 @@ void renderTileStandardStream(uniform int taskIndex, uniform RTCIntersectContext primary_context; rtcInitIntersectContext(&primary_context); primary_context.flags = g_iflags_coherent; - rtcIntersectVM(g_scene,&primary_context,(varying RTCRayHit* uniform)&primary_stream,N,sizeof(Ray)); + rtcIntersectVM(data.g_scene,&primary_context,(varying RTCRayHit* uniform)&primary_stream,N,sizeof(Ray)); /* terminate rays and update color */ N = -1; @@ -319,13 +311,13 @@ void renderTileStandardStream(uniform int taskIndex, Ray& primary = primary_stream[N]; Vec3f Ns = primary.Ng; if (primary.instID[0] != RTC_INVALID_GEOMETRY_ID) - Ns = xfmVector(normal_xfm[primary.instID[0]],Ns); + Ns = xfmVector(data.normal_xfm[primary.instID[0]],Ns); Ns = normalize(Ns); /* calculate diffuse color of geometries */ Vec3f diffuse = make_Vec3f(1,1,1); if (primary.instID[0] != RTC_INVALID_GEOMETRY_ID) - diffuse = colors[primary.instID[0]][primary.geomID]; + diffuse = data.colors[primary.instID[0]][primary.geomID]; color_stream[N] = color_stream[N] + diffuse*0.5; /* initialize shadow ray tnear/tfar */ @@ -343,7 +335,7 @@ void renderTileStandardStream(uniform int taskIndex, uniform RTCIntersectContext shadow_context; rtcInitIntersectContext(&shadow_context); shadow_context.flags = g_iflags_coherent; - rtcOccludedVM(g_scene,&shadow_context,(varying RTCRay* uniform)&shadow_stream,N,sizeof(Ray)); + rtcOccludedVM(data.g_scene,&shadow_context,(varying RTCRay* uniform)&shadow_stream,N,sizeof(Ray)); /* add light contribution */ N = -1; @@ -360,15 +352,15 @@ void renderTileStandardStream(uniform int taskIndex, Ray& primary = primary_stream[N]; Vec3f Ns = primary.Ng; if (primary.instID[0] != RTC_INVALID_GEOMETRY_ID) - Ns = xfmVector(normal_xfm[primary.instID[0]],Ns); + Ns = xfmVector(data.normal_xfm[primary.instID[0]],Ns); Ns = normalize(Ns); /* calculate diffuse color of geometries */ Vec3f diffuse = make_Vec3f(1,1,1); if (primary.instID[0] != RTC_INVALID_GEOMETRY_ID) - diffuse = colors[primary.instID[0]][primary.geomID]; + diffuse = data.colors[primary.instID[0]][primary.geomID]; - /* add light contrinution */ + /* add light contribution */ Ray& shadow = shadow_stream[N]; if (shadow.tfar >= 0.0f) { color_stream[N] = color_stream[N] + diffuse*clamp(-dot(lightDir,Ns),0.0f,1.0f); @@ -435,33 +427,32 @@ export void device_render (uniform int* uniform pixels, xfm.vy = make_Vec3f(0,1,0); xfm.vz = make_Vec3f(-sin(t1),0,cos(t1)); - /* calculate transformations to move instances in cirle */ + /* calculate transformations to move instances in circle */ for (uniform int i=0; i<4; i++) { uniform float t = t0+i*2.0f*M_PI/4.0f; - instance_xfm[i] = make_AffineSpace3f(xfm,2.2f*make_Vec3f(+cos(t),0.0f,+sin(t))); + data.instance_xfm[i] = make_AffineSpace3f(xfm,2.2f*make_Vec3f(+cos(t),0.0f,+sin(t))); } /* calculate transformations to properly transform normals */ for (uniform int i=0; i<4; i++) - normal_xfm[i] = transposed(rcp(instance_xfm[i].l)); + data.normal_xfm[i] = transposed(rcp(data.instance_xfm[i].l)); /* set instance transformations */ - rtcSetGeometryTransform(g_instance0,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&instance_xfm[0]); - rtcSetGeometryTransform(g_instance1,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&instance_xfm[1]); - rtcSetGeometryTransform(g_instance2,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&instance_xfm[2]); - rtcSetGeometryTransform(g_instance3,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&instance_xfm[3]); + rtcSetGeometryTransform(data.g_instance0,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&data.instance_xfm[0]); + rtcSetGeometryTransform(data.g_instance1,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&data.instance_xfm[1]); + rtcSetGeometryTransform(data.g_instance2,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&data.instance_xfm[2]); + rtcSetGeometryTransform(data.g_instance3,0,RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,(uniform float* uniform)&data.instance_xfm[3]); /* update scene */ - rtcCommitGeometry(g_instance0); - rtcCommitGeometry(g_instance1); - rtcCommitGeometry(g_instance2); - rtcCommitGeometry(g_instance3); - rtcCommitScene (g_scene); + rtcCommitGeometry(data.g_instance0); + rtcCommitGeometry(data.g_instance1); + rtcCommitGeometry(data.g_instance2); + rtcCommitGeometry(data.g_instance3); + rtcCommitScene (data.g_scene); } /* called by the C++ code for cleanup */ export void device_cleanup () { - rtcReleaseScene (g_scene); g_scene = NULL; - rtcReleaseScene (g_scene1); g_scene1 = NULL; + TutorialData_Destructor(&data); } diff --git a/tutorials/instanced_geometry/instanced_geometry_device.isph b/tutorials/instanced_geometry/instanced_geometry_device.isph new file mode 100644 index 0000000000..a3290fa39e --- /dev/null +++ b/tutorials/instanced_geometry/instanced_geometry_device.isph @@ -0,0 +1,39 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../common/tutorial/tutorial_device.isph" +#include "../common/math/random_sampler.isph" +#include "../common/core/differential_geometry.isph" +#include "../common/tutorial/scene_device.h" + +struct TutorialData +{ + /* scene data */ + RTCScene g_scene; + RTCScene g_scene1; + + RTCGeometry g_instance0; + RTCGeometry g_instance1; + RTCGeometry g_instance2; + RTCGeometry g_instance3; + uniform AffineSpace3f instance_xfm[4]; + uniform LinearSpace3f normal_xfm[4]; + + uniform Vec3f colors[4][4]; +}; + +void TutorialData_Constructor(uniform TutorialData* uniform This) +{ + This->g_scene = NULL; + This->g_scene1 = NULL; + This->g_instance0 = NULL; + This->g_instance1 = NULL; + This->g_instance2 = NULL; + This->g_instance3 = NULL; +} + +void TutorialData_Destructor(uniform TutorialData* uniform This) +{ + rtcReleaseScene (This->g_scene); This->g_scene = NULL; + rtcReleaseScene (This->g_scene1); This->g_scene1 = NULL; +} diff --git a/tutorials/interpolation/CMakeLists.txt b/tutorials/interpolation/CMakeLists.txt index b84eed4de0..af32f77d7c 100644 --- a/tutorials/interpolation/CMakeLists.txt +++ b/tutorials/interpolation/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/interpolation/interpolation.cpp b/tutorials/interpolation/interpolation.cpp index 20fa76ed94..28dcdb3a07 100644 --- a/tutorials/interpolation/interpolation.cpp +++ b/tutorials/interpolation/interpolation.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/interpolation/interpolation_device.cpp b/tutorials/interpolation/interpolation_device.cpp index b5d40a4fe2..68eebf11d7 100644 --- a/tutorials/interpolation/interpolation_device.cpp +++ b/tutorials/interpolation/interpolation_device.cpp @@ -1,7 +1,7 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.h" +#include "interpolation_device.h" #include "../common/tutorial/optics.h" namespace embree { @@ -15,7 +15,7 @@ namespace embree { /* scene data */ RTCScene g_scene = nullptr; -Vec3fa* vertex_colors = nullptr; +TutorialData data; unsigned int triCubeID, quadCubeID; #define NUM_VERTICES 8 @@ -314,8 +314,9 @@ unsigned int addGroundPlane (RTCScene scene_i) /* called by the C++ code for initialization */ extern "C" void device_init (char* cfg) { - /* create scene */ - g_scene = rtcNewScene(g_device); + /* create scene */ + TutorialData_Constructor(&data); + g_scene = data.scene = rtcNewScene(g_device); /* add ground plane */ addGroundPlane(g_scene); @@ -332,7 +333,7 @@ extern "C" void device_init (char* cfg) } /* task that renders a single screen tile */ -Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& stats) +Vec3fa renderPixel(const TutorialData& data, float x, float y, const ISPCCamera& camera, RayStats& stats) { RTCIntersectContext context; rtcInitIntersectContext(&context); @@ -341,7 +342,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Ray ray(Vec3fa(camera.xfm.p), Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf); /* intersect ray with scene */ - rtcIntersect1(g_scene,&context,RTCRayHit_(ray)); + rtcIntersect1(data.scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); /* shade pixels */ @@ -352,8 +353,8 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Vec3fa diffuse = Vec3fa(1.0f,0.0f,0.0f); if (ray.geomID > 0) { - unsigned int geomID = ray.geomID; { - rtcInterpolate0(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE,0,&diffuse.x,3); + auto geomID = ray.geomID; { + rtcInterpolate0(rtcGetGeometry(data.scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE,0,&diffuse.x,3); } //return diffuse; diffuse = 0.5f*diffuse; @@ -363,8 +364,8 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Vec3fa Ng = ray.Ng; if (ray.geomID == 2 || ray.geomID == 3) { Vec3fa dPdu,dPdv; - unsigned int geomID = ray.geomID; { - rtcInterpolate1(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,nullptr,&dPdu.x,&dPdv.x,3); + auto geomID = ray.geomID; { + rtcInterpolate1(rtcGetGeometry(data.scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,nullptr,&dPdu.x,&dPdv.x,3); } //return dPdu; Ng = cross(dPdu,dPdv); @@ -377,7 +378,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Ray shadow(ray.org + ray.tfar*ray.dir, neg(lightDir), 0.001f, inf); /* trace shadow ray */ - rtcOccluded1(g_scene,&context,RTCRay_(shadow)); + rtcOccluded1(data.scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -391,35 +392,23 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& return color; } -/* renders a single screen tile */ -void renderTileStandard(int taskIndex, - int threadIndex, - int* pixels, - const unsigned int width, - const unsigned int height, - const float time, - const ISPCCamera& camera, - const int numTilesX, - const int numTilesY) +void renderPixelWrite(const TutorialData& data, + int x, int y, + int* pixels, + const unsigned int width, + const unsigned int height, + const float time, + const ISPCCamera& camera, + RayStats& stats) { - const unsigned int tileY = taskIndex / numTilesX; - const unsigned int tileX = taskIndex - tileY * numTilesX; - const unsigned int x0 = tileX * TILE_SIZE_X; - const unsigned int x1 = min(x0+TILE_SIZE_X,width); - const unsigned int y0 = tileY * TILE_SIZE_Y; - const unsigned int y1 = min(y0+TILE_SIZE_Y,height); - - for (unsigned int y=y0; yscene = nullptr; +} + +inline void TutorialData_Destructor(TutorialData* This) +{ + rtcReleaseScene (This->scene); This->scene = nullptr; +} + +} // namespace embree diff --git a/tutorials/interpolation/interpolation_device.ispc b/tutorials/interpolation/interpolation_device.ispc index 8ba49e25d7..5bbea990cc 100644 --- a/tutorials/interpolation/interpolation_device.ispc +++ b/tutorials/interpolation/interpolation_device.ispc @@ -1,7 +1,7 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.isph" +#include "interpolation_device.isph" #include "../common/tutorial/optics.isph" //#define FORCE_FIXED_EDGE_TESSELLATION @@ -13,7 +13,7 @@ /* scene data */ RTCScene g_scene = NULL; -uniform Vec3fa* uniform vertex_colors = NULL; +uniform TutorialData data; uniform unsigned int triCubeID, quadCubeID; #define NUM_VERTICES 8 @@ -312,8 +312,9 @@ uniform unsigned int addGroundPlane (RTCScene scene_i) /* called by the C++ code for initialization */ export void device_init (uniform int8* uniform cfg) { - /* create scene */ - g_scene = rtcNewScene(g_device); + /* create scene */ + TutorialData_Constructor(&data); + g_scene = data.scene = rtcNewScene(g_device); /* add ground plane */ addGroundPlane(g_scene); @@ -330,7 +331,7 @@ export void device_init (uniform int8* uniform cfg) } /* task that renders a single screen tile */ -Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, uniform RayStats& stats) +Vec3f renderPixel(const uniform TutorialData& data, float x, float y, const uniform ISPCCamera& camera, uniform RayStats& stats) { uniform RTCIntersectContext context; rtcInitIntersectContext(&context); @@ -339,7 +340,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Ray ray = make_Ray(make_Vec3f(camera.xfm.p), make_Vec3f(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf); /* intersect ray with scene */ - rtcIntersectV(g_scene,&context,RTCRayHit_(ray)); + rtcIntersectV(data.scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); /* shade pixels */ @@ -351,7 +352,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un if (ray.geomID > 0) { foreach_unique (geomID in ray.geomID) { - rtcInterpolateV0(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE,0,&diffuse.x,3); + rtcInterpolateV0(rtcGetGeometry(data.scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE,0,&diffuse.x,3); } //return diffuse; diffuse = 0.5f*diffuse; @@ -362,7 +363,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un if (ray.geomID == 2 || ray.geomID == 3) { Vec3f dPdu,dPdv; foreach_unique (geomID in ray.geomID) { - rtcInterpolateV1(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,NULL,&dPdu.x,&dPdv.x,3); + rtcInterpolateV1(rtcGetGeometry(data.scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,NULL,&dPdu.x,&dPdv.x,3); } //return dPdu; Ng = cross(dPdu,dPdv); @@ -375,7 +376,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Ray shadow = make_Ray(ray.org + ray.tfar*ray.dir, neg(lightDir), 0.001f, inf); /* trace shadow ray */ - rtcOccludedV(g_scene,&context,RTCRay_(shadow)); + rtcOccludedV(data.scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -389,35 +390,23 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un return color; } -/* renders a single screen tile */ -void renderTileStandard(uniform int taskIndex, - uniform int threadIndex, - uniform int* uniform pixels, - const uniform unsigned int width, - const uniform unsigned int height, - const uniform float time, - const uniform ISPCCamera& camera, - const uniform int numTilesX, - const uniform int numTilesY) +void renderPixelWrite(const uniform TutorialData& data, + int x, int y, + uniform int* uniform pixels, + const uniform unsigned int width, + const uniform unsigned int height, + const uniform float time, + const uniform ISPCCamera& camera, + uniform RayStats& stats) { - const uniform unsigned int tileY = taskIndex / numTilesX; - const uniform unsigned int tileX = taskIndex - tileY * numTilesX; - const uniform unsigned int x0 = tileX * TILE_SIZE_X; - const uniform unsigned int x1 = min(x0+TILE_SIZE_X,width); - const uniform unsigned int y0 = tileY * TILE_SIZE_Y; - const uniform unsigned int y1 = min(y0+TILE_SIZE_Y,height); - - foreach_tiled (y = y0 ... y1, x = x0 ... x1) - { - /* calculate pixel color */ - Vec3f color = renderPixelStandard((float)x,(float)y,camera,g_stats[threadIndex]); - - /* write color to framebuffer */ - unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); - unsigned int g = (unsigned int) (255.0f * clamp(color.y,0.0f,1.0f)); - unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f)); - pixels[y*width+x] = (b << 16) + (g << 8) + r; - } + /* calculate pixel color */ + Vec3f color = renderPixel(data,(float)x,(float)y,camera,stats); + + /* write color to framebuffer */ + unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); + unsigned int g = (unsigned int) (255.0f * clamp(color.y,0.0f,1.0f)); + unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f)); + pixels[y*width+x] = (b << 16) + (g << 8) + r; } /* task that renders a single screen tile */ @@ -429,7 +418,17 @@ task void renderTileTask(uniform int* uniform pixels, const uniform int numTilesX, const uniform int numTilesY) { - renderTileStandard(taskIndex,threadIndex,pixels,width,height,time,camera,numTilesX,numTilesY); + const uniform unsigned int tileY = taskIndex / numTilesX; + const uniform unsigned int tileX = taskIndex - tileY * numTilesX; + const uniform unsigned int x0 = tileX * TILE_SIZE_X; + const uniform unsigned int x1 = min(x0+TILE_SIZE_X,width); + const uniform unsigned int y0 = tileY * TILE_SIZE_Y; + const uniform unsigned int y1 = min(y0+TILE_SIZE_Y,height); + + foreach_tiled (y = y0 ... y1, x = x0 ... x1) + { + renderPixelWrite(data,x,y,pixels,width,height,time,camera,g_stats[threadIndex]); + } } export void renderFrameStandard (uniform int* uniform pixels, @@ -461,5 +460,5 @@ export void device_render (uniform int* uniform pixels, /* called by the C++ code for cleanup */ export void device_cleanup () { - rtcReleaseScene (g_scene); g_scene = NULL; + TutorialData_Destructor(&data); } diff --git a/tutorials/interpolation/interpolation_device.isph b/tutorials/interpolation/interpolation_device.isph new file mode 100644 index 0000000000..4fa91b2428 --- /dev/null +++ b/tutorials/interpolation/interpolation_device.isph @@ -0,0 +1,19 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../common/tutorial/tutorial_device.isph" + +struct TutorialData +{ + RTCScene scene; +}; + +inline void TutorialData_Constructor(uniform TutorialData* uniform This) +{ + This->scene = NULL; +} + +inline void TutorialData_Destructor(uniform TutorialData* uniform This) +{ + rtcReleaseScene (This->scene); This->scene = NULL; +} diff --git a/tutorials/intersection_filter/CMakeLists.txt b/tutorials/intersection_filter/CMakeLists.txt index abaf3e1063..7a8e01159c 100644 --- a/tutorials/intersection_filter/CMakeLists.txt +++ b/tutorials/intersection_filter/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/intersection_filter/intersection_filter.cpp b/tutorials/intersection_filter/intersection_filter.cpp index 50736e16cc..da1045244b 100644 --- a/tutorials/intersection_filter/intersection_filter.cpp +++ b/tutorials/intersection_filter/intersection_filter.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -18,5 +19,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "intersection_filter"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/intersection_filter/intersection_filter_device.cpp b/tutorials/intersection_filter/intersection_filter_device.cpp index 8247ed640c..3bafb78f20 100644 --- a/tutorials/intersection_filter/intersection_filter_device.cpp +++ b/tutorials/intersection_filter/intersection_filter_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "intersection_filter_device.h" @@ -517,7 +517,7 @@ void renderTileStandardStream(int taskIndex, if (valid_stream[N] == false) continue; numActive++; - /* add light contrinution */ + /* add light contribution */ float opacity = 1.0f-primary.transparency; Vec3fa diffuse = data.colors[primary.ray.primID]; Ray2& shadow = shadow_stream[N]; diff --git a/tutorials/intersection_filter/intersection_filter_device.h b/tutorials/intersection_filter/intersection_filter_device.h index c08689ab66..2fcfc3d14d 100644 --- a/tutorials/intersection_filter/intersection_filter_device.h +++ b/tutorials/intersection_filter/intersection_filter_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/intersection_filter/intersection_filter_device.ispc b/tutorials/intersection_filter/intersection_filter_device.ispc index bb1f586582..4d90421a46 100644 --- a/tutorials/intersection_filter/intersection_filter_device.ispc +++ b/tutorials/intersection_filter/intersection_filter_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "intersection_filter_device.isph" @@ -515,7 +515,7 @@ void renderTileStandardStream(uniform int taskIndex, if (valid_stream[N] == false) continue; numActive++; - /* add light contrinution */ + /* add light contribution */ float opacity = 1.0f-primary.transparency; Vec3f diffuse = data.colors[primary.ray.primID]; Ray2& shadow = shadow_stream[N]; diff --git a/tutorials/intersection_filter/intersection_filter_device.isph b/tutorials/intersection_filter/intersection_filter_device.isph index aa634a8e84..52f80504ba 100644 --- a/tutorials/intersection_filter/intersection_filter_device.isph +++ b/tutorials/intersection_filter/intersection_filter_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/ispc2cpp.sh b/tutorials/ispc2cpp.sh index f053f86841..98d2930e6c 100755 --- a/tutorials/ispc2cpp.sh +++ b/tutorials/ispc2cpp.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 echo Converting ISPC tutorial $1 to CPP tutorial $2 @@ -55,7 +55,7 @@ sed -i.backup 's/foreach_tiled[ ]*([ ]*\([a-zA-Z0-9_]*\)[ ]*=[ ]*\([^ \.]*\)[ ] sed -i.backup 's/foreach[ ]*([ ]*\([a-zA-Z0-9_]*\)[ ]*=[ ]*\([^ \.]*\)[ ]*\.\.\.[ ]*\([^ ),]*\)[ ]*\,[ ]*\([a-zA-Z0-9_]*\)[ ]*=[ ]*\([^ \.]*\)[ ]*\.\.\.[ ]*\([^ ),]*\)[ ]*)/for (unsigned int \1=\2; \1<\3; \1++) for (int \4=\5; \4<\6; \4++)/g' $2 sed -i.backup 's/foreach_tiled[ ]*([ ]*\([a-zA-Z0-9_]*\)[ ]*=[ ]*\([^ \.]*\)[ ]*\.\.\.[ ]*\([^ ),]*\)[ ]*\,[ ]*\([a-zA-Z0-9_]*\)[ ]*=[ ]*\([^ \.]*\)[ ]*\.\.\.[ ]*\([^ ),]*\)[ ]*)/for (unsigned int \1=\2; \1<\3; \1++) for (unsigned int \4=\5; \4<\6; \4++)/g' $2 -sed -i.backup 's/foreach_unique[ ]*([ ]*\([[:alnum:]_]*\)[ ]*in[ ]*\([][[:alnum:]._]*\))/unsigned int \1 = \2;/g' $2 +sed -i.backup 's/foreach_unique[ ]*([ ]*\([[:alnum:]_]*\)[ ]*in[ ]*\([][[:alnum:]._]*\))/auto \1 = \2;/g' $2 sed -i.backup 's/new[ ]*\([a-zA-Z0-9_]*\)[ ]*\[\([^]]*\)\]/(\1\*) alignedMalloc(\2\*sizeof(\1),16)/g' $2 sed -i.backup 's/delete[ ]*\[[ ]*\][ ]*\([a-zA-Z0-9_.\>\-]*\)/alignedFree(\1)/g' $2 diff --git a/tutorials/lazy_geometry/CMakeLists.txt b/tutorials/lazy_geometry/CMakeLists.txt index 0370bd82bf..b58b6ecd54 100644 --- a/tutorials/lazy_geometry/CMakeLists.txt +++ b/tutorials/lazy_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/lazy_geometry/lazy_geometry.cpp b/tutorials/lazy_geometry/lazy_geometry.cpp index 45ce2b9849..8b357ac488 100644 --- a/tutorials/lazy_geometry/lazy_geometry.cpp +++ b/tutorials/lazy_geometry/lazy_geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/lazy_geometry/lazy_geometry_device.cpp b/tutorials/lazy_geometry/lazy_geometry_device.cpp index 0ed7a64bb9..79c458ee84 100644 --- a/tutorials/lazy_geometry/lazy_geometry_device.cpp +++ b/tutorials/lazy_geometry/lazy_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/lazy_geometry/lazy_geometry_device.ispc b/tutorials/lazy_geometry/lazy_geometry_device.ispc index fea6069cf2..860288b796 100644 --- a/tutorials/lazy_geometry/lazy_geometry_device.ispc +++ b/tutorials/lazy_geometry/lazy_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/minimal/CMakeLists.txt b/tutorials/minimal/CMakeLists.txt index ab5bec38b9..88b42c33c3 100644 --- a/tutorials/minimal/CMakeLists.txt +++ b/tutorials/minimal/CMakeLists.txt @@ -1,10 +1,10 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ADD_EXECUTABLE(minimal ../../kernels/embree.rc minimal.cpp) TARGET_LINK_LIBRARIES(minimal embree) -TARGET_INCLUDE_DIRECTORIES(minimal PRIVATE ${PROJECT_SOURCE_DIR}/include) +TARGET_INCLUDE_DIRECTORIES(minimal PRIVATE "${PROJECT_SOURCE_DIR}/include") SET_PROPERTY(TARGET minimal PROPERTY FOLDER tutorials/single) SET_PROPERTY(TARGET minimal APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -INSTALL(TARGETS minimal DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) +INSTALL(TARGETS minimal DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) SIGN_TARGET(minimal) diff --git a/tutorials/minimal/minimal.cpp b/tutorials/minimal/minimal.cpp index d2e843af8d..1a7d7b221f 100644 --- a/tutorials/minimal/minimal.cpp +++ b/tutorials/minimal/minimal.cpp @@ -1,10 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include #include +#include + +#if defined(_WIN32) +# include +# include +#endif /* * A minimal tutorial. @@ -31,8 +37,8 @@ * This is only required to make the tutorial compile even when * a custom namespace is set. */ -#if defined(RTC_NAMESPACE_OPEN) -RTC_NAMESPACE_OPEN +#if defined(RTC_NAMESPACE_USE) +RTC_NAMESPACE_USE #endif /* @@ -200,6 +206,27 @@ void castRay(RTCScene scene, printf("Did not find any intersection.\n"); } +void waitForKeyPressedUnderWindows() +{ +#if defined(_WIN32) + HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (!GetConsoleScreenBufferInfo(hStdOutput, &csbi)) { + printf("GetConsoleScreenBufferInfo failed: %d\n", GetLastError()); + return; + } + + /* do not pause when running on a shell */ + if (csbi.dwCursorPosition.X != 0 || csbi.dwCursorPosition.Y != 0) + return; + + /* only pause if running in separate console window. */ + printf("\n\tPress any key to exit...\n"); + int ch = getch(); +#endif +} + /* -------------------------------------------------------------------------- */ @@ -220,7 +247,10 @@ int main() * always make sure to release resources allocated through Embree. */ rtcReleaseScene(scene); rtcReleaseDevice(device); - + + /* wait for user input under Windows when opened in separate window */ + waitForKeyPressedUnderWindows(); + return 0; } diff --git a/tutorials/models/build.bench b/tutorials/models/build.bench new file mode 100644 index 0000000000..34118475b6 --- /dev/null +++ b/tutorials/models/build.bench @@ -0,0 +1,8 @@ +barbarian barbarian/barbarian.xml +barbarian_mblur_instancing barbarian/barbarian_mblur_instancing.xml +barbarian_subdiv barbarian/barbarian_subdiv.xml +sophie sophie/sophie.xml +sophie_mblur sophie_mblur/sophie_mblur.xml +crown crown/crown.xml +conference conference/conference.xml +powerplant powerplant/powerplant.xml diff --git a/tutorials/models/cornell_box_instanced.ecs b/tutorials/models/cornell_box_instanced.ecs new file mode 100644 index 0000000000..d4b0237a3b --- /dev/null +++ b/tutorials/models/cornell_box_instanced.ecs @@ -0,0 +1,3 @@ +-i cornell_box_instanced.xml +--vp 2.01 2.01 -2 --vi 2 2 0 --vu 0 1 0 --fov 90 --righthanded + diff --git a/tutorials/models/cornell_box_instanced.xml b/tutorials/models/cornell_box_instanced.xml new file mode 100644 index 0000000000..03370b0ba8 --- /dev/null +++ b/tutorials/models/cornell_box_instanced.xml @@ -0,0 +1,125 @@ + + + + + + + 0.00178826 0 0 0 + 0 0.00178826 0 0 + 0 0 0.00178826 0 + + + + + + + + + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 + + + + + + + + + 1 0 0 0 + 0 1 0 +1 + 0 0 1 0 + + + + + + + + + 1 0 0 +1 + 0 1 0 0 + 0 0 1 0 + + + + + + + + + 1 0 0 +1 + 0 1 0 +1 + 0 0 1 0 + + + + + + + + + + + + + + + + + + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 + + + + + + + + + 1 0 0 0 + 0 1 0 +2 + 0 0 1 0 + + + + + + + + + 1 0 0 +2 + 0 1 0 0 + 0 0 1 0 + + + + + + + + + 1 0 0 +2 + 0 1 0 +2 + 0 0 1 0 + + + + + + + + + + + + + + + + + + + diff --git a/tutorials/models/oriented_curve_large_curvature.ecs b/tutorials/models/oriented_curve_large_curvature.ecs new file mode 100644 index 0000000000..28b7354054 --- /dev/null +++ b/tutorials/models/oriented_curve_large_curvature.ecs @@ -0,0 +1,2 @@ +-i oriented_curve_large_curvature.xml +--vp 93.472229 53.9328537 -24.73282051 --vi 97.46273804 46.86347961 -5.722045898e-06 --vu 0 1 0 --fov 90 --righthanded diff --git a/tutorials/models/oriented_curve_large_curvature.xml b/tutorials/models/oriented_curve_large_curvature.xml new file mode 100644 index 0000000000..debd630a5b --- /dev/null +++ b/tutorials/models/oriented_curve_large_curvature.xml @@ -0,0 +1,36 @@ + + + + + + + + + 0.0 0.0 0.0 1.0 + 100.0 0.0 0.0 1.0 + 100.0 100.0 0.0 1.0 + 101.0 0.0 0.0 1.0 + + + + 0 0 1 + 0 0 1 + 0 0 1 + 0 0 1 + + + + 0 + + + + "OBJ" + + 1 0 0 + + + + + + + diff --git a/tutorials/models/trace.bench b/tutorials/models/trace.bench new file mode 100644 index 0000000000..8c858c9f97 --- /dev/null +++ b/tutorials/models/trace.bench @@ -0,0 +1,11 @@ +barbarian barbarian/barbarian.ecs +barbarian_msmblur barbarian/barbarian_msmblur.ecs +barbarian_mblur_instancing barbarian/barbarian_mblur_instancing.ecs +barbarian_msmblur_instancing barbarian/barbarian_msmblur_instancing.ecs +barbarian_subdiv barbarian/barbarian_subdiv.ecs +barbarian_subdiv_mblur barbarian/barbarian_subdiv_mblur.ecs +barbarian_subdiv_msmblur barbarian/barbarian_subdiv_msmblur.ecs +sophie sophie/sophie.ecs +crown crown/crown.ecs +sponza sponza/sponza.ecs +conference conference/conference.ecs \ No newline at end of file diff --git a/tutorials/motion_blur_geometry/CMakeLists.txt b/tutorials/motion_blur_geometry/CMakeLists.txt index 9459c4c779..3135720a97 100644 --- a/tutorials/motion_blur_geometry/CMakeLists.txt +++ b/tutorials/motion_blur_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/motion_blur_geometry/motion_blur_geometry.cpp b/tutorials/motion_blur_geometry/motion_blur_geometry.cpp index 8632b39d75..67d33f2f48 100644 --- a/tutorials/motion_blur_geometry/motion_blur_geometry.cpp +++ b/tutorials/motion_blur_geometry/motion_blur_geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp b/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp index 597d240904..47c4f8cd8d 100644 --- a/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp +++ b/tutorials/motion_blur_geometry/motion_blur_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "motion_blur_geometry_device.h" diff --git a/tutorials/motion_blur_geometry/motion_blur_geometry_device.h b/tutorials/motion_blur_geometry/motion_blur_geometry_device.h index 276329efee..2a03ff8089 100644 --- a/tutorials/motion_blur_geometry/motion_blur_geometry_device.h +++ b/tutorials/motion_blur_geometry/motion_blur_geometry_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/motion_blur_geometry/motion_blur_geometry_device.ispc b/tutorials/motion_blur_geometry/motion_blur_geometry_device.ispc index fda17e44d8..43186058c4 100644 --- a/tutorials/motion_blur_geometry/motion_blur_geometry_device.ispc +++ b/tutorials/motion_blur_geometry/motion_blur_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "motion_blur_geometry_device.isph" diff --git a/tutorials/motion_blur_geometry/motion_blur_geometry_device.isph b/tutorials/motion_blur_geometry/motion_blur_geometry_device.isph index 3684d33c33..9a8b1114c7 100644 --- a/tutorials/motion_blur_geometry/motion_blur_geometry_device.isph +++ b/tutorials/motion_blur_geometry/motion_blur_geometry_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/multi_instanced_geometry/CMakeLists.txt b/tutorials/multi_instanced_geometry/CMakeLists.txt index 5afb970e4a..363734fe78 100644 --- a/tutorials/multi_instanced_geometry/CMakeLists.txt +++ b/tutorials/multi_instanced_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/multi_instanced_geometry/geometry/ground.cpp b/tutorials/multi_instanced_geometry/geometry/ground.cpp index b85a31f406..97bf5e06e0 100644 --- a/tutorials/multi_instanced_geometry/geometry/ground.cpp +++ b/tutorials/multi_instanced_geometry/geometry/ground.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace Ground { diff --git a/tutorials/multi_instanced_geometry/geometry/tree.cpp b/tutorials/multi_instanced_geometry/geometry/tree.cpp index b914177dfa..79adc1fc6f 100644 --- a/tutorials/multi_instanced_geometry/geometry/tree.cpp +++ b/tutorials/multi_instanced_geometry/geometry/tree.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace Twigs01 { diff --git a/tutorials/multi_instanced_geometry/geometry/trees.cpp b/tutorials/multi_instanced_geometry/geometry/trees.cpp index c3ce6fa031..483b1391e0 100644 --- a/tutorials/multi_instanced_geometry/geometry/trees.cpp +++ b/tutorials/multi_instanced_geometry/geometry/trees.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace Trees { diff --git a/tutorials/multi_instanced_geometry/geometry/twig.cpp b/tutorials/multi_instanced_geometry/geometry/twig.cpp index a2de58a0ab..e9df330fc5 100644 --- a/tutorials/multi_instanced_geometry/geometry/twig.cpp +++ b/tutorials/multi_instanced_geometry/geometry/twig.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace Twig { diff --git a/tutorials/multi_instanced_geometry/multi_instanced_geometry.cpp b/tutorials/multi_instanced_geometry/multi_instanced_geometry.cpp index 771cfa0b17..93cf3fb8b9 100644 --- a/tutorials/multi_instanced_geometry/multi_instanced_geometry.cpp +++ b/tutorials/multi_instanced_geometry/multi_instanced_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -18,5 +19,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "multi_instanced_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp b/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp index 826d5a680a..9abc8785e3 100644 --- a/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp +++ b/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.ispc b/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.ispc index d789f8bb1c..f2fa761846 100644 --- a/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.ispc +++ b/tutorials/multi_instanced_geometry/multi_instanced_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/multi_instanced_geometry/scene.cpp b/tutorials/multi_instanced_geometry/scene.cpp index 968bcd3918..233bb4e792 100644 --- a/tutorials/multi_instanced_geometry/scene.cpp +++ b/tutorials/multi_instanced_geometry/scene.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/affinespace.h" diff --git a/tutorials/multi_instanced_geometry/scene.h b/tutorials/multi_instanced_geometry/scene.h index 3aad5b5cc1..3b0095df5a 100644 --- a/tutorials/multi_instanced_geometry/scene.h +++ b/tutorials/multi_instanced_geometry/scene.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/multi_instanced_geometry/scene.isph b/tutorials/multi_instanced_geometry/scene.isph index a5ac5252da..4bac2b24ee 100644 --- a/tutorials/multi_instanced_geometry/scene.isph +++ b/tutorials/multi_instanced_geometry/scene.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/tutorials/multiscene_geometry/CMakeLists.txt b/tutorials/multiscene_geometry/CMakeLists.txt index 5fa33a296c..4bcfbf8be5 100644 --- a/tutorials/multiscene_geometry/CMakeLists.txt +++ b/tutorials/multiscene_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 SET(EMBREE_ISPC_SUPPORT OFF) diff --git a/tutorials/multiscene_geometry/multiscene_geometry.cpp b/tutorials/multiscene_geometry/multiscene_geometry.cpp index db44681568..d8f5bbf99b 100644 --- a/tutorials/multiscene_geometry/multiscene_geometry.cpp +++ b/tutorials/multiscene_geometry/multiscene_geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/multiscene_geometry/multiscene_geometry_device.cpp b/tutorials/multiscene_geometry/multiscene_geometry_device.cpp index 6362963406..2f88646383 100644 --- a/tutorials/multiscene_geometry/multiscene_geometry_device.cpp +++ b/tutorials/multiscene_geometry/multiscene_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/next_hit/CMakeLists.txt b/tutorials/next_hit/CMakeLists.txt index d6463cdb9c..977bf28fed 100644 --- a/tutorials/next_hit/CMakeLists.txt +++ b/tutorials/next_hit/CMakeLists.txt @@ -1,11 +1,11 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) ADD_TUTORIAL(next_hit) MACRO (ALL_HITS_TEST name model max_next_hits) - ADD_TEST(NAME next_hit_${name}_${max_next_hits} COMMAND next_hit -c ${EMBREE_MODEL_DIR}/${model} -c ${EMBREE_MODEL_DIR}/${model} --verify --max_next_hits ${max_next_hits} --max_total_hits 1024 ${ARGN} --shader default -o test.tga) + ADD_TEST(NAME next_hit_${name}_${max_next_hits} COMMAND next_hit -c "${EMBREE_MODEL_DIR}/${model}" -c "${EMBREE_MODEL_DIR}/${model}" --verify --max_next_hits ${max_next_hits} --max_total_hits 1024 ${ARGN} --shader default -o test.tga) ENDMACRO () IF (BUILD_TESTING AND EMBREE_TESTING_INTENSITY GREATER 1) diff --git a/tutorials/next_hit/next_hit.cpp b/tutorials/next_hit/next_hit.cpp index 46d2b25c7a..e4af79ea74 100644 --- a/tutorials/next_hit/next_hit.cpp +++ b/tutorials/next_hit/next_hit.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" @@ -75,7 +75,7 @@ namespace embree void postParseCommandLine() override { /* load default scene if none specified */ - if (scene->size() == 0 && sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/cornell_box.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } diff --git a/tutorials/next_hit/next_hit_device.cpp b/tutorials/next_hit/next_hit_device.cpp index c3fcfcbe17..03320edcbb 100644 --- a/tutorials/next_hit/next_hit_device.cpp +++ b/tutorials/next_hit/next_hit_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.h" @@ -124,20 +124,7 @@ RTCScene g_scene = nullptr; RTCScene convertScene(ISPCScene* scene_in) { - RTCScene scene_out = ConvertScene(g_device, g_ispc_scene, RTC_BUILD_QUALITY_MEDIUM); - rtcSetSceneFlags(scene_out, rtcGetSceneFlags(scene_out) | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION | RTC_SCENE_FLAG_ROBUST); - - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) { - rtcSetSceneFlags(geometry->scene, rtcGetSceneFlags(geometry->scene) | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION | RTC_SCENE_FLAG_ROBUST); - rtcCommitScene(geometry->scene); - } - } - } + RTCScene scene_out = ConvertScene(g_device, g_ispc_scene, RTC_BUILD_QUALITY_MEDIUM, RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION | RTC_SCENE_FLAG_ROBUST); /* commit changes to scene */ return scene_out; @@ -179,7 +166,7 @@ void single_pass(const Ray& ray_i, HitList& hits_o, RandomSampler& sampler, RayS /* sort hits by extended order */ std::sort(&context.hits.hits[context.hits.begin],&context.hits.hits[context.hits.end]); - /* ignore duplicated hits that can occur for tesselated primitives */ + /* ignore duplicated hits that can occur for tessellated primitives */ if (hits_o.size()) { unsigned int i=0, j=1; diff --git a/tutorials/osp2emb.sh b/tutorials/osp2emb.sh index a9bc2f385d..e6a0e39a78 100755 --- a/tutorials/osp2emb.sh +++ b/tutorials/osp2emb.sh @@ -1,6 +1,6 @@ #!/bin/bash -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 echo Converting OSPRay code $1 to Embree code $2 diff --git a/tutorials/pathtracer/CMakeLists.txt b/tutorials/pathtracer/CMakeLists.txt index 60754354e7..c1be330d92 100644 --- a/tutorials/pathtracer/CMakeLists.txt +++ b/tutorials/pathtracer/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/pathtracer/pathtracer.cpp b/tutorials/pathtracer/pathtracer.cpp index ea6d7211c2..a8003b91c0 100644 --- a/tutorials/pathtracer/pathtracer.cpp +++ b/tutorials/pathtracer/pathtracer.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -32,7 +33,7 @@ namespace embree void postParseCommandLine() override { /* load default scene if none specified */ - if (scene->size() == 0 && sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/cornell_box.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } @@ -53,5 +54,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/pathtracer/pathtracer_device.cpp b/tutorials/pathtracer/pathtracer_device.cpp index 3c09f6d83e..dde85348fd 100644 --- a/tutorials/pathtracer/pathtracer_device.cpp +++ b/tutorials/pathtracer/pathtracer_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.h" @@ -29,7 +29,8 @@ namespace embree { extern "C" int g_spp; extern "C" int g_max_path_length; extern "C" bool g_accumulate; - +extern "C" int g_animation_mode; + bool g_subdiv_mode = false; unsigned int keyframeID = 0; @@ -759,7 +760,7 @@ Vec3fa HairMaterial__sample(ISPCHairMaterial* This, const BRDF& brdf, const Vec3 inline void Material__preprocess(ISPCMaterial** materials, unsigned int materialID, unsigned int numMaterials, BRDF& brdf, const Vec3fa& wo, const DifferentialGeometry& dg, const Medium& medium) { - unsigned int id = materialID; + auto id = materialID; { if (id < numMaterials) // FIXME: workaround for ISPC bug, location reached with empty execution mask { @@ -785,7 +786,7 @@ inline void Material__preprocess(ISPCMaterial** materials, unsigned int material inline Vec3fa Material__eval(ISPCMaterial** materials, unsigned int materialID, unsigned int numMaterials, const BRDF& brdf, const Vec3fa& wo, const DifferentialGeometry& dg, const Vec3fa& wi) { Vec3fa c = Vec3fa(0.0f); - unsigned int id = materialID; + auto id = materialID; { if (id < numMaterials) // FIXME: workaround for ISPC bug, location reached with empty execution mask { @@ -811,7 +812,7 @@ inline Vec3fa Material__eval(ISPCMaterial** materials, unsigned int materialID, inline Vec3fa Material__sample(ISPCMaterial** materials, unsigned int materialID, unsigned int numMaterials, const BRDF& brdf, const Vec3fa& Lw, const Vec3fa& wo, const DifferentialGeometry& dg, Sample3f& wi_o, Medium& medium, const Vec2f& s) { Vec3fa c = Vec3fa(0.0f); - unsigned int id = materialID; + auto id = materialID; { if (id < numMaterials) // FIXME: workaround for ISPC bug, location reached with empty execution mask { @@ -950,11 +951,6 @@ void assignShaders(ISPCGeometry* geometry) rtcSetGeometryOccludedFilterFunction(geom,occlusionFilterHair); } #endif - else if (geometry->type == GROUP) { - ISPCGroup* group = (ISPCGroup*) geometry; - for (unsigned int i=0; inumGeometries; i++) - assignShaders(group->geometries[i]); - } } typedef ISPCInstance* ISPCInstance_ptr; @@ -970,22 +966,10 @@ RTCScene convertScene(ISPCScene* scene_in) } } + assignShadersFunc = assignShaders; + RTCScene scene_out = ConvertScene(g_device, g_ispc_scene, RTC_BUILD_QUALITY_MEDIUM); - /* assign shaders */ - for (unsigned int i=0; inumGeometries; i++) { - assignShaders(scene_in->geometries[i]); - } - - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) rtcCommitScene(geometry->scene); - } - } - /* commit changes to scene */ //progressStart(); //rtcSetSceneProgressMonitorFunction(scene_out,progressMonitor,nullptr); @@ -1336,11 +1320,6 @@ void postIntersectGeometry(const Ray& ray, DifferentialGeometry& dg, ISPCGeometr dg.Ng = dg.Ns = normalize(cross(dg.Ty,dg.Tx)); } } - else if (geometry->type == GROUP) { - unsigned int geomID = dg.geomID; { - postIntersectGeometry(ray,dg,((ISPCGroup*) geometry)->geometries[geomID],materialID); - } - } else assert(false); @@ -1366,36 +1345,30 @@ typedef ISPCInstance* ISPCInstancePtr; inline int postIntersect(const Ray& ray, DifferentialGeometry& dg) { dg.eps = 32.0f*1.19209e-07f*max(max(abs(dg.P.x),abs(dg.P.y)),max(abs(dg.P.z),ray.tfar)); + + AffineSpace3fa local2world = AffineSpace3fa::scale(Vec3fa(1)); + ISPCGeometry** geometries = g_ispc_scene->geometries; + + for (int i=0; igeometries[instID]; - geometry = instance->child; - } else { - geometry = g_ispc_scene->geometries[geomID]; - } - postIntersectGeometry(ray,dg,geometry,materialID); - } - } + ISPCInstance* instance = (ISPCInstancePtr) geometries[instID]; + local2world = local2world * calculate_interpolated_space(instance,ray.time()); - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - unsigned int instID = dg.instID; - { - /* get instance and geometry pointers */ - ISPCInstance* instance = (ISPCInstancePtr) g_ispc_scene->geometries[instID]; - - /* convert normals */ - //AffineSpace3fa space = (1.0f-ray.time())*AffineSpace3fa(instance->space0) + ray.time()*AffineSpace3fa(instance->space1); - AffineSpace3fa space = calculate_interpolated_space(instance,ray.time()); - dg.Ng = xfmVector(space,dg.Ng); - dg.Ns = xfmVector(space,dg.Ns); - } + assert(instance->child->type == GROUP); + geometries = ((ISPCGroup*)instance->child)->geometries; } + int materialID = 0; + ISPCGeometry* geom = geometries[dg.geomID]; + auto g = geom; { + postIntersectGeometry(ray,dg,g,materialID); + } + dg.Ng = xfmVector(local2world,dg.Ng); + dg.Ns = xfmVector(local2world,dg.Ns); + return materialID; } @@ -1424,7 +1397,9 @@ void intersectionFilterOBJ(const RTCFilterFunctionNArguments* args) //const float tfar = RTCHitN_t(hit,N,rayID); const float tfar = ray->tfar; DifferentialGeometry dg; - dg.instID = RTCHitN_instID(hit,N,rayID, 0); + for (int i=0; itfar = tfar; - // ray->instID = dg.instID; - // ray->geomID = dg.geomID; - // ray->primID = dg.primID; - // ray->u = dg.u; - // ray->v = dg.v; - // ray->Ng = Ng; - } else valid_i[0] = 0; } @@ -1499,7 +1466,9 @@ void occlusionFilterOBJ(const RTCFilterFunctionNArguments* args) const float tfar = ray->tfar; DifferentialGeometry dg; - dg.instID = RTCHitN_instID(hit,N,rayID, 0); + for (int i=0; igeometries[geomID]; if (geometry->type == CURVES) @@ -1615,7 +1584,9 @@ Vec3fa renderPixelFunction(float x, float y, RandomSampler& sampler, const ISPCC Vec3fa Ns = normalize(ray.Ng); /* compute differential geometry */ - dg.instID = ray.instID[0]; + for (int i=0; igeometry; if (geometry->type == SUBDIV_MESH) @@ -948,11 +949,6 @@ void assignShaders(ISPCGeometry* uniform geometry) rtcSetGeometryOccludedFilterFunction(geom,occlusionFilterHair); } #endif - else if (geometry->type == GROUP) { - ISPCGroup* uniform group = (ISPCGroup* uniform) geometry; - for (uniform unsigned int i=0; inumGeometries; i++) - assignShaders(group->geometries[i]); - } } typedef uniform ISPCInstance* uniform ISPCInstance_ptr; @@ -968,22 +964,10 @@ RTCScene convertScene(uniform ISPCScene* uniform scene_in) } } + assignShadersFunc = assignShaders; + RTCScene scene_out = ConvertScene(g_device, g_ispc_scene, RTC_BUILD_QUALITY_MEDIUM); - /* assign shaders */ - for (uniform unsigned int i=0; inumGeometries; i++) { - assignShaders(scene_in->geometries[i]); - } - - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (uniform unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* uniform geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) rtcCommitScene(geometry->scene); - } - } - /* commit changes to scene */ //progressStart(); //rtcSetSceneProgressMonitorFunction(scene_out,progressMonitor,NULL); @@ -1334,11 +1318,6 @@ void postIntersectGeometry(const Ray& ray, DifferentialGeometry& dg, uniform ISP dg.Ng = dg.Ns = normalize(cross(dg.Ty,dg.Tx)); } } - else if (geometry->type == GROUP) { - foreach_unique (geomID in dg.geomID) { - postIntersectGeometry(ray,dg,((uniform ISPCGroup*) geometry)->geometries[geomID],materialID); - } - } else assert(false); @@ -1346,7 +1325,7 @@ void postIntersectGeometry(const Ray& ray, DifferentialGeometry& dg, uniform ISP dg.Ns = make_Vec3f(1, 0, 0); } -AffineSpace3f calculate_interpolated_space (uniform ISPCInstance* uniform instance, float gtime) +AffineSpace3f calculate_interpolated_space (uniform ISPCInstance* instance, float gtime) { if (instance->numTimeSteps == 1) return make_AffineSpace3f(instance->spaces[0]); @@ -1359,41 +1338,35 @@ AffineSpace3f calculate_interpolated_space (uniform ISPCInstance* uniform instan return (1.0f-ftime)*make_AffineSpace3f(instance->spaces[itime+0]) + ftime*make_AffineSpace3f(instance->spaces[itime+1]); } -typedef ISPCInstance* uniform ISPCInstancePtr; +typedef ISPCInstance* ISPCInstancePtr; inline int postIntersect(const Ray& ray, DifferentialGeometry& dg) { dg.eps = 32.0f*1.19209e-07f*max(max(abs(dg.P.x),abs(dg.P.y)),max(abs(dg.P.z),ray.tfar)); + + AffineSpace3f local2world = make_AffineSpace3f_scale(make_Vec3f(1)); + ISPCGeometry* uniform* geometries = g_ispc_scene->geometries; + + for (uniform int i=0; igeometries[instID]; - geometry = instance->child; - } else { - geometry = g_ispc_scene->geometries[geomID]; - } - postIntersectGeometry(ray,dg,geometry,materialID); - } - } + ISPCInstance* instance = (ISPCInstancePtr) geometries[instID]; + local2world = local2world * calculate_interpolated_space(instance,ray.time); - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - foreach_unique (instID in dg.instID) - { - /* get instance and geometry pointers */ - ISPCInstance* uniform instance = (ISPCInstancePtr) g_ispc_scene->geometries[instID]; - - /* convert normals */ - //AffineSpace3f space = (1.0f-ray.time)*make_AffineSpace3f(instance->space0) + ray.time*make_AffineSpace3f(instance->space1); - AffineSpace3f space = calculate_interpolated_space(instance,ray.time); - dg.Ng = xfmVector(space,dg.Ng); - dg.Ns = xfmVector(space,dg.Ns); - } + assert(instance->child->type == GROUP); + geometries = ((ISPCGroup*)instance->child)->geometries; } + int materialID = 0; + ISPCGeometry* geom = geometries[dg.geomID]; + foreach_unique (g in geom) { + postIntersectGeometry(ray,dg,g,materialID); + } + dg.Ng = xfmVector(local2world,dg.Ng); + dg.Ns = xfmVector(local2world,dg.Ns); + return materialID; } @@ -1422,7 +1395,9 @@ unmasked void intersectionFilterOBJ(const RTCFilterFunctionNArguments* uniform a //const float tfar = RTCHitN_t(hit,N,rayID); const float tfar = ray->tfar; DifferentialGeometry dg; - dg.instID = RTCHitN_instID(hit,N,rayID, 0); + for (uniform int i=0; itfar = tfar; - // ray->instID = dg.instID; - // ray->geomID = dg.geomID; - // ray->primID = dg.primID; - // ray->u = dg.u; - // ray->v = dg.v; - // ray->Ng = Ng; - } else valid_i[programIndex] = 0; } @@ -1497,7 +1464,9 @@ unmasked void occlusionFilterOBJ(const RTCFilterFunctionNArguments* uniform args const float tfar = ray->tfar; DifferentialGeometry dg; - dg.instID = RTCHitN_instID(hit,N,rayID, 0); + for (uniform int i=0; i).main(argc, argv, "point_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/point_geometry/point_geometry_device.cpp b/tutorials/point_geometry/point_geometry_device.cpp index 07490d0082..850e816aeb 100644 --- a/tutorials/point_geometry/point_geometry_device.cpp +++ b/tutorials/point_geometry/point_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "point_geometry_device.h" diff --git a/tutorials/point_geometry/point_geometry_device.h b/tutorials/point_geometry/point_geometry_device.h index 1d22fa182f..4b9c932a2c 100644 --- a/tutorials/point_geometry/point_geometry_device.h +++ b/tutorials/point_geometry/point_geometry_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/point_geometry/point_geometry_device.ispc b/tutorials/point_geometry/point_geometry_device.ispc index ba8caf82fc..ff8b2ebe1f 100644 --- a/tutorials/point_geometry/point_geometry_device.ispc +++ b/tutorials/point_geometry/point_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "point_geometry_device.isph" diff --git a/tutorials/point_geometry/point_geometry_device.isph b/tutorials/point_geometry/point_geometry_device.isph index 78218d4a45..4368eb6917 100644 --- a/tutorials/point_geometry/point_geometry_device.isph +++ b/tutorials/point_geometry/point_geometry_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/quaternion_motion_blur/CMakeLists.txt b/tutorials/quaternion_motion_blur/CMakeLists.txt index 235692d1c8..3eaaf2cbab 100644 --- a/tutorials/quaternion_motion_blur/CMakeLists.txt +++ b/tutorials/quaternion_motion_blur/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/quaternion_motion_blur/quaternion_motion_blur.cpp b/tutorials/quaternion_motion_blur/quaternion_motion_blur.cpp index 3d585c00c3..d94e51330a 100644 --- a/tutorials/quaternion_motion_blur/quaternion_motion_blur.cpp +++ b/tutorials/quaternion_motion_blur/quaternion_motion_blur.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -55,5 +56,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "quaternion_motion_blur"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp b/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp index 5ed8033bb3..9698614c0c 100644 --- a/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp +++ b/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.ispc b/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.ispc index 4d86fc458d..0aef539437 100644 --- a/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.ispc +++ b/tutorials/quaternion_motion_blur/quaternion_motion_blur_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/subdivision_geometry/CMakeLists.txt b/tutorials/subdivision_geometry/CMakeLists.txt index 11a82d2c42..bd019b89ef 100644 --- a/tutorials/subdivision_geometry/CMakeLists.txt +++ b/tutorials/subdivision_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/subdivision_geometry/subdivision_geometry.cpp b/tutorials/subdivision_geometry/subdivision_geometry.cpp index 6148a7efb1..d650a1f7fd 100644 --- a/tutorials/subdivision_geometry/subdivision_geometry.cpp +++ b/tutorials/subdivision_geometry/subdivision_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "subdivision_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/subdivision_geometry/subdivision_geometry_device.cpp b/tutorials/subdivision_geometry/subdivision_geometry_device.cpp index 66a69e3818..d3ee6f30a4 100644 --- a/tutorials/subdivision_geometry/subdivision_geometry_device.cpp +++ b/tutorials/subdivision_geometry/subdivision_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" @@ -193,7 +193,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Vec3fa Ng = ray.Ng; if (ray.geomID > 0) { Vec3fa dPdu,dPdv; - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { rtcInterpolate1(rtcGetGeometry(g_scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,nullptr,&dPdu.x,&dPdv.x,3); } Ng = cross(dPdu,dPdv); diff --git a/tutorials/subdivision_geometry/subdivision_geometry_device.ispc b/tutorials/subdivision_geometry/subdivision_geometry_device.ispc index a2571870e7..3bc5c15c41 100644 --- a/tutorials/subdivision_geometry/subdivision_geometry_device.ispc +++ b/tutorials/subdivision_geometry/subdivision_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/triangle_geometry/CMakeLists.txt b/tutorials/triangle_geometry/CMakeLists.txt index df5fa36ebe..755466be99 100644 --- a/tutorials/triangle_geometry/CMakeLists.txt +++ b/tutorials/triangle_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/triangle_geometry/triangle_geometry.cpp b/tutorials/triangle_geometry/triangle_geometry.cpp index 5ff05df0a5..878026454a 100644 --- a/tutorials/triangle_geometry/triangle_geometry.cpp +++ b/tutorials/triangle_geometry/triangle_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "triangle_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/triangle_geometry/triangle_geometry_device.cpp b/tutorials/triangle_geometry/triangle_geometry_device.cpp index cf44bdab55..3211c00734 100644 --- a/tutorials/triangle_geometry/triangle_geometry_device.cpp +++ b/tutorials/triangle_geometry/triangle_geometry_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "triangle_geometry_device.h" diff --git a/tutorials/triangle_geometry/triangle_geometry_device.h b/tutorials/triangle_geometry/triangle_geometry_device.h index 27c16f81bb..7de878cd86 100644 --- a/tutorials/triangle_geometry/triangle_geometry_device.h +++ b/tutorials/triangle_geometry/triangle_geometry_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" diff --git a/tutorials/triangle_geometry/triangle_geometry_device.ispc b/tutorials/triangle_geometry/triangle_geometry_device.ispc index 8f0306d051..1ff69587ca 100644 --- a/tutorials/triangle_geometry/triangle_geometry_device.ispc +++ b/tutorials/triangle_geometry/triangle_geometry_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "triangle_geometry_device.isph" diff --git a/tutorials/triangle_geometry/triangle_geometry_device.isph b/tutorials/triangle_geometry/triangle_geometry_device.isph index ed461981ee..6e3b1ef3b1 100644 --- a/tutorials/triangle_geometry/triangle_geometry_device.isph +++ b/tutorials/triangle_geometry/triangle_geometry_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" diff --git a/tutorials/user_geometry/CMakeLists.txt b/tutorials/user_geometry/CMakeLists.txt index a536c33064..4e1bb65b72 100644 --- a/tutorials/user_geometry/CMakeLists.txt +++ b/tutorials/user_geometry/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/user_geometry/user_geometry.cpp b/tutorials/user_geometry/user_geometry.cpp index 8aad898c93..ae536889a0 100644 --- a/tutorials/user_geometry/user_geometry.cpp +++ b/tutorials/user_geometry/user_geometry.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -19,5 +20,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv, "user_geometry"); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/user_geometry/user_geometry_device.cpp b/tutorials/user_geometry/user_geometry_device.cpp index 4aec0652f0..94315f797c 100644 --- a/tutorials/user_geometry/user_geometry_device.cpp +++ b/tutorials/user_geometry/user_geometry_device.cpp @@ -1,10 +1,13 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.h" +#include "user_geometry_device.h" namespace embree { +RTCScene g_scene = nullptr; +TutorialData data; + const int numPhi = 5; const int numTheta = 2*numPhi; @@ -65,19 +68,6 @@ inline void copyInstanceIdStack(const RTCIntersectContext* ctx, unsigned* tgt) // User defined instancing // // ======================================================================== // -struct Instance -{ - ALIGNED_STRUCT_(16) - RTCGeometry geometry; - RTCScene object; - int userID; - AffineSpace3fa local2world; - AffineSpace3fa world2local; - LinearSpace3fa normal2world; - Vec3fa lower; - Vec3fa upper; -}; - void instanceBoundsFunc(const struct RTCBoundsFunctionArguments* args) { const Instance* instance = (const Instance*) args->geometryUserPtr; @@ -302,15 +292,6 @@ void updateInstance (RTCScene scene, Instance* instance) // User defined sphere geometry // // ======================================================================== // -struct Sphere -{ - ALIGNED_STRUCT_(16) - Vec3fa p; //!< position of the sphere - float r; //!< radius of the sphere - RTCGeometry geometry; - unsigned int geomID; -}; - void sphereBoundsFunc(const struct RTCBoundsFunctionArguments* args) { const Sphere* spheres = (const Sphere*) args->geometryUserPtr; @@ -932,84 +913,72 @@ unsigned int createGroundPlane (RTCScene scene) return geomID; } -/* scene data */ -RTCScene g_scene = nullptr; -RTCScene g_scene0 = nullptr; -RTCScene g_scene1 = nullptr; -RTCScene g_scene2 = nullptr; -Sphere* g_spheres = nullptr; -Sphere* g_sphere0 = nullptr; -Sphere* g_sphere1 = nullptr; - -Instance* g_instance[4] = { nullptr, nullptr, nullptr, nullptr }; - -Vec3fa colors[5][4]; - /* called by the C++ code for initialization */ extern "C" void device_init (char* cfg) { /* create scene */ - g_scene = rtcNewScene(g_device); + TutorialData_Constructor(&data); + g_scene = data.g_scene = rtcNewScene(g_device); /* create scene with 4 analytical spheres */ - g_scene0 = rtcNewScene(g_device); - rtcSetSceneBuildQuality(g_scene0,RTC_BUILD_QUALITY_LOW); - g_spheres = createAnalyticalSpheres(g_scene0,4); - g_spheres[0].p = Vec3fa( 0, 0,+1); g_spheres[0].r = 0.5f; - g_spheres[1].p = Vec3fa(+1, 0, 0); g_spheres[1].r = 0.5f; - g_spheres[2].p = Vec3fa( 0, 0,-1); g_spheres[2].r = 0.5f; - g_spheres[3].p = Vec3fa(-1, 0, 0); g_spheres[3].r = 0.5f; - rtcCommitScene(g_scene0); + data.g_scene0 = rtcNewScene(g_device); + rtcSetSceneBuildQuality(data.g_scene0,RTC_BUILD_QUALITY_LOW); + data.g_spheres = createAnalyticalSpheres(data.g_scene0,4); + data.g_spheres[0].p = Vec3fa( 0, 0,+1); data.g_spheres[0].r = 0.5f; + data.g_spheres[1].p = Vec3fa(+1, 0, 0); data.g_spheres[1].r = 0.5f; + data.g_spheres[2].p = Vec3fa( 0, 0,-1); data.g_spheres[2].r = 0.5f; + data.g_spheres[3].p = Vec3fa(-1, 0, 0); data.g_spheres[3].r = 0.5f; + rtcCommitScene(data.g_scene0); /* create scene with 4 triangulated spheres */ - g_scene1 = rtcNewScene(g_device); - createTriangulatedSphere(g_scene1,Vec3fa( 0, 0,+1),0.5f); - createTriangulatedSphere(g_scene1,Vec3fa(+1, 0, 0),0.5f); - createTriangulatedSphere(g_scene1,Vec3fa( 0, 0,-1),0.5f); - createTriangulatedSphere(g_scene1,Vec3fa(-1, 0, 0),0.5f); - rtcCommitScene(g_scene1); + data.g_scene1 = rtcNewScene(g_device); + createTriangulatedSphere(data.g_scene1,Vec3fa( 0, 0,+1),0.5f); + createTriangulatedSphere(data.g_scene1,Vec3fa(+1, 0, 0),0.5f); + createTriangulatedSphere(data.g_scene1,Vec3fa( 0, 0,-1),0.5f); + createTriangulatedSphere(data.g_scene1,Vec3fa(-1, 0, 0),0.5f); + rtcCommitScene(data.g_scene1); /* create scene with 2 triangulated and 2 analytical spheres */ - g_scene2 = rtcNewScene(g_device); - createTriangulatedSphere(g_scene2,Vec3fa( 0, 0,+1),0.5f); - g_sphere0 = createAnalyticalSphere (g_scene2,Vec3fa(+1, 0, 0),0.5f); - createTriangulatedSphere(g_scene2,Vec3fa( 0, 0,-1),0.5f); - g_sphere1 = createAnalyticalSphere (g_scene2,Vec3fa(-1, 0, 0),0.5f); - rtcCommitScene(g_scene2); + data.g_scene2 = rtcNewScene(g_device); + createTriangulatedSphere(data.g_scene2,Vec3fa( 0, 0,+1),0.5f); + data.g_sphere0 = createAnalyticalSphere (data.g_scene2,Vec3fa(+1, 0, 0),0.5f); + createTriangulatedSphere(data.g_scene2,Vec3fa( 0, 0,-1),0.5f); + data.g_sphere1 = createAnalyticalSphere (data.g_scene2,Vec3fa(-1, 0, 0),0.5f); + rtcCommitScene(data.g_scene2); /* instantiate geometry */ - g_instance[0] = createInstance(g_scene,g_scene0,0,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); - g_instance[1] = createInstance(g_scene,g_scene1,1,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); - g_instance[2] = createInstance(g_scene,g_scene2,2,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); - g_instance[3] = createInstance(g_scene,g_scene2,3,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); - createGroundPlane(g_scene); - rtcCommitScene(g_scene); + data.g_instance[0] = createInstance(data.g_scene,data.g_scene0,0,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); + data.g_instance[1] = createInstance(data.g_scene,data.g_scene1,1,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); + data.g_instance[2] = createInstance(data.g_scene,data.g_scene2,2,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); + data.g_instance[3] = createInstance(data.g_scene,data.g_scene2,3,Vec3fa(-2,-2,-2),Vec3fa(+2,+2,+2)); + createGroundPlane(data.g_scene); + rtcCommitScene(data.g_scene); /* set all colors */ - colors[0][0] = Vec3fa(0.25f, 0.00f, 0.00f); - colors[0][1] = Vec3fa(0.50f, 0.00f, 0.00f); - colors[0][2] = Vec3fa(0.75f, 0.00f, 0.00f); - colors[0][3] = Vec3fa(1.00f, 0.00f, 0.00f); - - colors[1][0] = Vec3fa(0.00f, 0.25f, 0.00f); - colors[1][1] = Vec3fa(0.00f, 0.50f, 0.00f); - colors[1][2] = Vec3fa(0.00f, 0.75f, 0.00f); - colors[1][3] = Vec3fa(0.00f, 1.00f, 0.00f); - - colors[2][0] = Vec3fa(0.00f, 0.00f, 0.25f); - colors[2][1] = Vec3fa(0.00f, 0.00f, 0.50f); - colors[2][2] = Vec3fa(0.00f, 0.00f, 0.75f); - colors[2][3] = Vec3fa(0.00f, 0.00f, 1.00f); - - colors[3][0] = Vec3fa(0.25f, 0.25f, 0.00f); - colors[3][1] = Vec3fa(0.50f, 0.50f, 0.00f); - colors[3][2] = Vec3fa(0.75f, 0.75f, 0.00f); - colors[3][3] = Vec3fa(1.00f, 1.00f, 0.00f); - - colors[4][0] = Vec3fa(1.0f, 1.0f, 1.0f); - colors[4][1] = Vec3fa(1.0f, 1.0f, 1.0f); - colors[4][2] = Vec3fa(1.0f, 1.0f, 1.0f); - colors[4][3] = Vec3fa(1.0f, 1.0f, 1.0f); + data.colors[0][0] = Vec3fa(0.25f, 0.00f, 0.00f); + data.colors[0][1] = Vec3fa(0.50f, 0.00f, 0.00f); + data.colors[0][2] = Vec3fa(0.75f, 0.00f, 0.00f); + data.colors[0][3] = Vec3fa(1.00f, 0.00f, 0.00f); + + data.colors[1][0] = Vec3fa(0.00f, 0.25f, 0.00f); + data.colors[1][1] = Vec3fa(0.00f, 0.50f, 0.00f); + data.colors[1][2] = Vec3fa(0.00f, 0.75f, 0.00f); + data.colors[1][3] = Vec3fa(0.00f, 1.00f, 0.00f); + + data.colors[2][0] = Vec3fa(0.00f, 0.00f, 0.25f); + data.colors[2][1] = Vec3fa(0.00f, 0.00f, 0.50f); + data.colors[2][2] = Vec3fa(0.00f, 0.00f, 0.75f); + data.colors[2][3] = Vec3fa(0.00f, 0.00f, 1.00f); + + data.colors[3][0] = Vec3fa(0.25f, 0.25f, 0.00f); + data.colors[3][1] = Vec3fa(0.50f, 0.50f, 0.00f); + data.colors[3][2] = Vec3fa(0.75f, 0.75f, 0.00f); + data.colors[3][3] = Vec3fa(1.00f, 1.00f, 0.00f); + + data.colors[4][0] = Vec3fa(1.0f, 1.0f, 1.0f); + data.colors[4][1] = Vec3fa(1.0f, 1.0f, 1.0f); + data.colors[4][2] = Vec3fa(1.0f, 1.0f, 1.0f); + data.colors[4][3] = Vec3fa(1.0f, 1.0f, 1.0f); } inline Vec3fa face_forward(const Vec3fa& dir, const Vec3fa& _Ng) { @@ -1018,7 +987,9 @@ inline Vec3fa face_forward(const Vec3fa& dir, const Vec3fa& _Ng) { } /* task that renders a single screen tile */ -Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& stats) +Vec3fa renderPixelStandard(const TutorialData& data, + float x, float y, const ISPCCamera& camera, + RayStats& stats) { RTCIntersectContext context; rtcInitIntersectContext(&context); @@ -1030,7 +1001,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& RTC_INVALID_GEOMETRY_ID, RTC_INVALID_GEOMETRY_ID); /* intersect ray with scene */ - rtcIntersect1(g_scene,&context,RTCRayHit_(ray)); + rtcIntersect1(data.g_scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); /* shade pixels */ @@ -1041,15 +1012,15 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Vec3fa Ns = ray.Ng; if (ray.instID[0] != RTC_INVALID_GEOMETRY_ID) { - Ns = xfmVector(g_instance[ray.instID[0]]->normal2world,Vec3fa(Ns)); + Ns = xfmVector(data.g_instance[ray.instID[0]]->normal2world,Vec3fa(Ns)); } Ns = face_forward(ray.dir,normalize(Ns)); /* calculate diffuse color of geometries */ Vec3fa diffuse = Vec3fa(0.0f); - if (ray.instID[0] == 0) diffuse = colors[ray.instID[0]][ray.primID]; - else if (ray.instID[0] == -1) diffuse = colors[4][ray.primID]; - else diffuse = colors[ray.instID[0]][ray.geomID]; + if (ray.instID[0] == 0) diffuse = data.colors[ray.instID[0]][ray.primID]; + else if (ray.instID[0] == -1) diffuse = data.colors[4][ray.primID]; + else diffuse = data.colors[ray.instID[0]][ray.geomID]; color = color + diffuse*0.5; /* initialize shadow ray */ @@ -1057,7 +1028,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& Ray shadow(ray.org + 0.999f*ray.tfar*ray.dir, neg(lightDir), 0.001f, inf); /* trace shadow ray */ - rtcOccluded1(g_scene,&context,RTCRay_(shadow)); + rtcOccluded1(data.g_scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -1067,6 +1038,23 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats& return color; } +void renderPixelStandard(const TutorialData& data, + int x, int y, + int* pixels, + const unsigned int width, + const unsigned int height, + const float time, + const ISPCCamera& camera, RayStats& stats) +{ + Vec3fa color = renderPixelStandard(data,x,y,camera,stats); + + /* write color to framebuffer */ + unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); + unsigned int g = (unsigned int) (255.0f * clamp(color.y,0.0f,1.0f)); + unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f)); + pixels[y*width+x] = (b << 16) + (g << 8) + r; +} + /* renders a single screen tile */ void renderTileStandard(int taskIndex, int threadIndex, @@ -1087,16 +1075,7 @@ void renderTileStandard(int taskIndex, for (unsigned int y=y0; ynormal2world,Vec3fa(Ns)); + Ns = xfmVector(data.g_instance[primary.instID[0]]->normal2world,Vec3fa(Ns)); } Ns = face_forward(primary.dir,normalize(Ns)); - /* add light contrinution */ + /* add light contribution */ Vec3fa diffuse = Vec3fa(0.0f); - if (primary.instID[0] == 0) diffuse = colors[primary.instID[0]][primary.primID]; - else if (primary.instID[0] == -1) diffuse = colors[4][primary.primID]; - else diffuse = colors[primary.instID[0]][primary.geomID]; + if (primary.instID[0] == 0) diffuse = data.colors[primary.instID[0]][primary.primID]; + else if (primary.instID[0] == -1) diffuse = data.colors[4][primary.primID]; + else diffuse = data.colors[primary.instID[0]][primary.geomID]; Ray& shadow = shadow_stream[N]; if (shadow.tfar >= 0.0f) { color_stream[N] = color_stream[N] + diffuse*clamp(-dot(lightDir,Ns),0.0f,1.0f); @@ -1300,30 +1279,23 @@ extern "C" void device_render (int* pixels, xfm.vz = Vec3fa(-sin(t1),0,cos(t1)); /* calculate transformations to move instances in circles */ - g_instance[0]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(+cos(t0),0.0f,+sin(t0))); - g_instance[1]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(-cos(t0),0.0f,-sin(t0))); - g_instance[2]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(-sin(t0),0.0f,+cos(t0))); - g_instance[3]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(+sin(t0),0.0f,-cos(t0))); + data.g_instance[0]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(+cos(t0),0.0f,+sin(t0))); + data.g_instance[1]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(-cos(t0),0.0f,-sin(t0))); + data.g_instance[2]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(-sin(t0),0.0f,+cos(t0))); + data.g_instance[3]->local2world = AffineSpace3fa(xfm,2.2f*Vec3fa(+sin(t0),0.0f,-cos(t0))); /* update scene */ - updateInstance(g_scene,g_instance[0]); - updateInstance(g_scene,g_instance[1]); - updateInstance(g_scene,g_instance[2]); - updateInstance(g_scene,g_instance[3]); - rtcCommitScene (g_scene); + updateInstance(data.g_scene,data.g_instance[0]); + updateInstance(data.g_scene,data.g_instance[1]); + updateInstance(data.g_scene,data.g_instance[2]); + updateInstance(data.g_scene,data.g_instance[3]); + rtcCommitScene (data.g_scene); } /* called by the C++ code for cleanup */ extern "C" void device_cleanup () { - rtcReleaseScene (g_scene); g_scene = nullptr; - rtcReleaseScene (g_scene0); g_scene0 = nullptr; - rtcReleaseScene (g_scene1); g_scene1 = nullptr; - rtcReleaseScene (g_scene2); g_scene2 = nullptr; - rtcReleaseDevice(g_device); g_device = nullptr; - alignedFree(g_spheres); g_spheres = nullptr; - alignedFree(g_sphere0); g_sphere0 = nullptr; - alignedFree(g_sphere1); g_sphere1 = nullptr; + TutorialData_Destructor(&data); } } // namespace embree diff --git a/tutorials/user_geometry/user_geometry_device.h b/tutorials/user_geometry/user_geometry_device.h new file mode 100644 index 0000000000..92467e91d1 --- /dev/null +++ b/tutorials/user_geometry/user_geometry_device.h @@ -0,0 +1,73 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../common/tutorial/tutorial_device.h" + +namespace embree { + +struct Sphere +{ + ALIGNED_STRUCT_(16) + Vec3fa p; //!< position of the sphere + float r; //!< radius of the sphere + RTCGeometry geometry; + unsigned int geomID; +}; + +struct Instance +{ + ALIGNED_STRUCT_(16) + RTCGeometry geometry; + RTCScene object; + int userID; + AffineSpace3fa local2world; + AffineSpace3fa world2local; + LinearSpace3fa normal2world; + Vec3fa lower; + Vec3fa upper; +}; + +struct TutorialData +{ + /* scene data */ + RTCScene g_scene; + RTCScene g_scene0; + RTCScene g_scene1; + RTCScene g_scene2; + Sphere* g_spheres; + Sphere* g_sphere0; + Sphere* g_sphere1; + + Instance* g_instance[4]; + + Vec3fa colors[5][4]; +}; + +inline void TutorialData_Constructor(TutorialData* This) +{ + This->g_scene = nullptr; + This->g_scene0 = nullptr; + This->g_scene1 = nullptr; + This->g_scene2 = nullptr; + This->g_spheres = nullptr; + This->g_sphere0 = nullptr; + This->g_sphere1 = nullptr; + This->g_instance[0] = nullptr; + This->g_instance[1] = nullptr; + This->g_instance[2] = nullptr; + This->g_instance[3] = nullptr; +} + +inline void TutorialData_Destructor(TutorialData* This) +{ + rtcReleaseScene (This->g_scene); This->g_scene = nullptr; + rtcReleaseScene (This->g_scene0); This->g_scene0 = nullptr; + rtcReleaseScene (This->g_scene1); This->g_scene1 = nullptr; + rtcReleaseScene (This->g_scene2); This->g_scene2 = nullptr; + rtcReleaseDevice(g_device); g_device = nullptr; + alignedFree(This->g_spheres); This->g_spheres = nullptr; + alignedFree(This->g_sphere0); This->g_sphere0 = nullptr; + alignedFree(This->g_sphere1); This->g_sphere1 = nullptr; +} + +} // namespace embree diff --git a/tutorials/user_geometry/user_geometry_device.ispc b/tutorials/user_geometry/user_geometry_device.ispc index d2cac557b2..9fc0c2d33b 100644 --- a/tutorials/user_geometry/user_geometry_device.ispc +++ b/tutorials/user_geometry/user_geometry_device.ispc @@ -1,7 +1,10 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../common/tutorial/tutorial_device.isph" +#include "user_geometry_device.isph" + +RTCScene g_scene = NULL; +uniform TutorialData data; const uniform int numPhi = 5; const uniform int numTheta = 2*numPhi; @@ -63,19 +66,6 @@ inline void copyInstanceIdStack(uniform const RTCIntersectContext* uniform ctx, // User defined instancing // // ======================================================================== // -struct Instance -{ - ALIGNED_STRUCT_(16) - RTCGeometry geometry; - RTCScene object; - uniform int userID; - AffineSpace3f local2world; - AffineSpace3f world2local; - LinearSpace3f normal2world; - Vec3f lower; - Vec3f upper; -}; - unmasked void instanceBoundsFunc(const struct RTCBoundsFunctionArguments* uniform args) { const uniform Instance* uniform instance = (const uniform Instance* uniform) args->geometryUserPtr; @@ -300,15 +290,6 @@ void updateInstance (RTCScene scene, uniform Instance* uniform instance) // User defined sphere geometry // // ======================================================================== // -struct Sphere -{ - ALIGNED_STRUCT_(16) - Vec3f p; //!< position of the sphere - float r; //!< radius of the sphere - RTCGeometry geometry; - uniform unsigned int geomID; -}; - unmasked void sphereBoundsFunc(const struct RTCBoundsFunctionArguments* uniform args) { const uniform Sphere* uniform spheres = (const uniform Sphere* uniform) args->geometryUserPtr; @@ -930,84 +911,72 @@ uniform unsigned int createGroundPlane (RTCScene scene) return geomID; } -/* scene data */ -RTCScene g_scene = NULL; -RTCScene g_scene0 = NULL; -RTCScene g_scene1 = NULL; -RTCScene g_scene2 = NULL; -uniform Sphere* uniform g_spheres = NULL; -uniform Sphere* uniform g_sphere0 = NULL; -uniform Sphere* uniform g_sphere1 = NULL; - -uniform Instance* uniform g_instance[4] = { NULL, NULL, NULL, NULL }; - -uniform Vec3f colors[5][4]; - /* called by the C++ code for initialization */ export void device_init (uniform int8* uniform cfg) { /* create scene */ - g_scene = rtcNewScene(g_device); + TutorialData_Constructor(&data); + g_scene = data.g_scene = rtcNewScene(g_device); /* create scene with 4 analytical spheres */ - g_scene0 = rtcNewScene(g_device); - rtcSetSceneBuildQuality(g_scene0,RTC_BUILD_QUALITY_LOW); - g_spheres = createAnalyticalSpheres(g_scene0,4); - g_spheres[0].p = make_Vec3f( 0, 0,+1); g_spheres[0].r = 0.5f; - g_spheres[1].p = make_Vec3f(+1, 0, 0); g_spheres[1].r = 0.5f; - g_spheres[2].p = make_Vec3f( 0, 0,-1); g_spheres[2].r = 0.5f; - g_spheres[3].p = make_Vec3f(-1, 0, 0); g_spheres[3].r = 0.5f; - rtcCommitScene(g_scene0); + data.g_scene0 = rtcNewScene(g_device); + rtcSetSceneBuildQuality(data.g_scene0,RTC_BUILD_QUALITY_LOW); + data.g_spheres = createAnalyticalSpheres(data.g_scene0,4); + data.g_spheres[0].p = make_Vec3f( 0, 0,+1); data.g_spheres[0].r = 0.5f; + data.g_spheres[1].p = make_Vec3f(+1, 0, 0); data.g_spheres[1].r = 0.5f; + data.g_spheres[2].p = make_Vec3f( 0, 0,-1); data.g_spheres[2].r = 0.5f; + data.g_spheres[3].p = make_Vec3f(-1, 0, 0); data.g_spheres[3].r = 0.5f; + rtcCommitScene(data.g_scene0); /* create scene with 4 triangulated spheres */ - g_scene1 = rtcNewScene(g_device); - createTriangulatedSphere(g_scene1,make_Vec3f( 0, 0,+1),0.5f); - createTriangulatedSphere(g_scene1,make_Vec3f(+1, 0, 0),0.5f); - createTriangulatedSphere(g_scene1,make_Vec3f( 0, 0,-1),0.5f); - createTriangulatedSphere(g_scene1,make_Vec3f(-1, 0, 0),0.5f); - rtcCommitScene(g_scene1); + data.g_scene1 = rtcNewScene(g_device); + createTriangulatedSphere(data.g_scene1,make_Vec3f( 0, 0,+1),0.5f); + createTriangulatedSphere(data.g_scene1,make_Vec3f(+1, 0, 0),0.5f); + createTriangulatedSphere(data.g_scene1,make_Vec3f( 0, 0,-1),0.5f); + createTriangulatedSphere(data.g_scene1,make_Vec3f(-1, 0, 0),0.5f); + rtcCommitScene(data.g_scene1); /* create scene with 2 triangulated and 2 analytical spheres */ - g_scene2 = rtcNewScene(g_device); - createTriangulatedSphere(g_scene2,make_Vec3f( 0, 0,+1),0.5f); - g_sphere0 = createAnalyticalSphere (g_scene2,make_Vec3f(+1, 0, 0),0.5f); - createTriangulatedSphere(g_scene2,make_Vec3f( 0, 0,-1),0.5f); - g_sphere1 = createAnalyticalSphere (g_scene2,make_Vec3f(-1, 0, 0),0.5f); - rtcCommitScene(g_scene2); + data.g_scene2 = rtcNewScene(g_device); + createTriangulatedSphere(data.g_scene2,make_Vec3f( 0, 0,+1),0.5f); + data.g_sphere0 = createAnalyticalSphere (data.g_scene2,make_Vec3f(+1, 0, 0),0.5f); + createTriangulatedSphere(data.g_scene2,make_Vec3f( 0, 0,-1),0.5f); + data.g_sphere1 = createAnalyticalSphere (data.g_scene2,make_Vec3f(-1, 0, 0),0.5f); + rtcCommitScene(data.g_scene2); /* instantiate geometry */ - g_instance[0] = createInstance(g_scene,g_scene0,0,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); - g_instance[1] = createInstance(g_scene,g_scene1,1,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); - g_instance[2] = createInstance(g_scene,g_scene2,2,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); - g_instance[3] = createInstance(g_scene,g_scene2,3,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); - createGroundPlane(g_scene); - rtcCommitScene(g_scene); + data.g_instance[0] = createInstance(data.g_scene,data.g_scene0,0,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); + data.g_instance[1] = createInstance(data.g_scene,data.g_scene1,1,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); + data.g_instance[2] = createInstance(data.g_scene,data.g_scene2,2,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); + data.g_instance[3] = createInstance(data.g_scene,data.g_scene2,3,make_Vec3f(-2,-2,-2),make_Vec3f(+2,+2,+2)); + createGroundPlane(data.g_scene); + rtcCommitScene(data.g_scene); /* set all colors */ - colors[0][0] = make_Vec3f(0.25f, 0.00f, 0.00f); - colors[0][1] = make_Vec3f(0.50f, 0.00f, 0.00f); - colors[0][2] = make_Vec3f(0.75f, 0.00f, 0.00f); - colors[0][3] = make_Vec3f(1.00f, 0.00f, 0.00f); - - colors[1][0] = make_Vec3f(0.00f, 0.25f, 0.00f); - colors[1][1] = make_Vec3f(0.00f, 0.50f, 0.00f); - colors[1][2] = make_Vec3f(0.00f, 0.75f, 0.00f); - colors[1][3] = make_Vec3f(0.00f, 1.00f, 0.00f); - - colors[2][0] = make_Vec3f(0.00f, 0.00f, 0.25f); - colors[2][1] = make_Vec3f(0.00f, 0.00f, 0.50f); - colors[2][2] = make_Vec3f(0.00f, 0.00f, 0.75f); - colors[2][3] = make_Vec3f(0.00f, 0.00f, 1.00f); - - colors[3][0] = make_Vec3f(0.25f, 0.25f, 0.00f); - colors[3][1] = make_Vec3f(0.50f, 0.50f, 0.00f); - colors[3][2] = make_Vec3f(0.75f, 0.75f, 0.00f); - colors[3][3] = make_Vec3f(1.00f, 1.00f, 0.00f); - - colors[4][0] = make_Vec3f(1.0f, 1.0f, 1.0f); - colors[4][1] = make_Vec3f(1.0f, 1.0f, 1.0f); - colors[4][2] = make_Vec3f(1.0f, 1.0f, 1.0f); - colors[4][3] = make_Vec3f(1.0f, 1.0f, 1.0f); + data.colors[0][0] = make_Vec3f(0.25f, 0.00f, 0.00f); + data.colors[0][1] = make_Vec3f(0.50f, 0.00f, 0.00f); + data.colors[0][2] = make_Vec3f(0.75f, 0.00f, 0.00f); + data.colors[0][3] = make_Vec3f(1.00f, 0.00f, 0.00f); + + data.colors[1][0] = make_Vec3f(0.00f, 0.25f, 0.00f); + data.colors[1][1] = make_Vec3f(0.00f, 0.50f, 0.00f); + data.colors[1][2] = make_Vec3f(0.00f, 0.75f, 0.00f); + data.colors[1][3] = make_Vec3f(0.00f, 1.00f, 0.00f); + + data.colors[2][0] = make_Vec3f(0.00f, 0.00f, 0.25f); + data.colors[2][1] = make_Vec3f(0.00f, 0.00f, 0.50f); + data.colors[2][2] = make_Vec3f(0.00f, 0.00f, 0.75f); + data.colors[2][3] = make_Vec3f(0.00f, 0.00f, 1.00f); + + data.colors[3][0] = make_Vec3f(0.25f, 0.25f, 0.00f); + data.colors[3][1] = make_Vec3f(0.50f, 0.50f, 0.00f); + data.colors[3][2] = make_Vec3f(0.75f, 0.75f, 0.00f); + data.colors[3][3] = make_Vec3f(1.00f, 1.00f, 0.00f); + + data.colors[4][0] = make_Vec3f(1.0f, 1.0f, 1.0f); + data.colors[4][1] = make_Vec3f(1.0f, 1.0f, 1.0f); + data.colors[4][2] = make_Vec3f(1.0f, 1.0f, 1.0f); + data.colors[4][3] = make_Vec3f(1.0f, 1.0f, 1.0f); } inline Vec3f face_forward(const Vec3f& dir, const Vec3f& _Ng) { @@ -1016,7 +985,9 @@ inline Vec3f face_forward(const Vec3f& dir, const Vec3f& _Ng) { } /* task that renders a single screen tile */ -Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, uniform RayStats& stats) +Vec3f renderPixelStandard(const uniform TutorialData& data, + float x, float y, const uniform ISPCCamera& camera, + uniform RayStats& stats) { uniform RTCIntersectContext context; rtcInitIntersectContext(&context); @@ -1028,7 +999,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un RTC_INVALID_GEOMETRY_ID, RTC_INVALID_GEOMETRY_ID); /* intersect ray with scene */ - rtcIntersectV(g_scene,&context,RTCRayHit_(ray)); + rtcIntersectV(data.g_scene,&context,RTCRayHit_(ray)); RayStats_addRay(stats); /* shade pixels */ @@ -1039,15 +1010,15 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Vec3f Ns = ray.Ng; if (ray.instID[0] != RTC_INVALID_GEOMETRY_ID) { - Ns = xfmVector(g_instance[ray.instID[0]]->normal2world,make_Vec3f(Ns)); + Ns = xfmVector(data.g_instance[ray.instID[0]]->normal2world,make_Vec3f(Ns)); } Ns = face_forward(ray.dir,normalize(Ns)); /* calculate diffuse color of geometries */ Vec3f diffuse = make_Vec3f(0.0f); - if (ray.instID[0] == 0) diffuse = colors[ray.instID[0]][ray.primID]; - else if (ray.instID[0] == -1) diffuse = colors[4][ray.primID]; - else diffuse = colors[ray.instID[0]][ray.geomID]; + if (ray.instID[0] == 0) diffuse = data.colors[ray.instID[0]][ray.primID]; + else if (ray.instID[0] == -1) diffuse = data.colors[4][ray.primID]; + else diffuse = data.colors[ray.instID[0]][ray.geomID]; color = color + diffuse*0.5; /* initialize shadow ray */ @@ -1055,7 +1026,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un Ray shadow = make_Ray(ray.org + 0.999f*ray.tfar*ray.dir, neg(lightDir), 0.001f, inf); /* trace shadow ray */ - rtcOccludedV(g_scene,&context,RTCRay_(shadow)); + rtcOccludedV(data.g_scene,&context,RTCRay_(shadow)); RayStats_addShadowRay(stats); /* add light contribution */ @@ -1065,6 +1036,23 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un return color; } +void renderPixelStandard(const uniform TutorialData& data, + int x, int y, + uniform int* uniform pixels, + const uniform unsigned int width, + const uniform unsigned int height, + const float time, + const uniform ISPCCamera& camera, uniform RayStats& stats) +{ + Vec3f color = renderPixelStandard(data,x,y,camera,stats); + + /* write color to framebuffer */ + unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); + unsigned int g = (unsigned int) (255.0f * clamp(color.y,0.0f,1.0f)); + unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f)); + pixels[y*width+x] = (b << 16) + (g << 8) + r; +} + /* renders a single screen tile */ void renderTileStandard(uniform int taskIndex, uniform int threadIndex, @@ -1085,16 +1073,7 @@ void renderTileStandard(uniform int taskIndex, foreach_tiled (y = y0 ... y1, x = x0 ... x1) { - if (all(__mask == 0)) continue; - - /* calculate pixel color */ - Vec3f color = renderPixelStandard((float)x,(float)y,camera,g_stats[threadIndex]); - - /* write color to framebuffer */ - unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f)); - unsigned int g = (unsigned int) (255.0f * clamp(color.y,0.0f,1.0f)); - unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f)); - pixels[y*width+x] = (b << 16) + (g << 8) + r; + renderPixelStandard(data,x,y,pixels,width,height,time,camera,g_stats[threadIndex]); } } @@ -1183,9 +1162,9 @@ void renderTileStandardStream(uniform int taskIndex, /* calculate diffuse color of geometries */ Vec3f diffuse = make_Vec3f(0.0f); - if (primary.instID[0] == 0) diffuse = colors[primary.instID[0]][primary.primID]; - else if (primary.instID[0] == -1) diffuse = colors[4][primary.primID]; - else diffuse = colors[primary.instID[0]][primary.geomID]; + if (primary.instID[0] == 0) diffuse = data.colors[primary.instID[0]][primary.primID]; + else if (primary.instID[0] == -1) diffuse = data.colors[4][primary.primID]; + else diffuse = data.colors[primary.instID[0]][primary.geomID]; color_stream[N] = color_stream[N] + diffuse*0.5; /* initialize shadow ray */ @@ -1216,15 +1195,15 @@ void renderTileStandardStream(uniform int taskIndex, Ray& primary = primary_stream[N]; Vec3f Ns = primary.Ng; if (primary.instID[0] != RTC_INVALID_GEOMETRY_ID) { - Ns = xfmVector(g_instance[primary.instID[0]]->normal2world,make_Vec3f(Ns)); + Ns = xfmVector(data.g_instance[primary.instID[0]]->normal2world,make_Vec3f(Ns)); } Ns = face_forward(primary.dir,normalize(Ns)); - /* add light contrinution */ + /* add light contribution */ Vec3f diffuse = make_Vec3f(0.0f); - if (primary.instID[0] == 0) diffuse = colors[primary.instID[0]][primary.primID]; - else if (primary.instID[0] == -1) diffuse = colors[4][primary.primID]; - else diffuse = colors[primary.instID[0]][primary.geomID]; + if (primary.instID[0] == 0) diffuse = data.colors[primary.instID[0]][primary.primID]; + else if (primary.instID[0] == -1) diffuse = data.colors[4][primary.primID]; + else diffuse = data.colors[primary.instID[0]][primary.geomID]; Ray& shadow = shadow_stream[N]; if (shadow.tfar >= 0.0f) { color_stream[N] = color_stream[N] + diffuse*clamp(-dot(lightDir,Ns),0.0f,1.0f); @@ -1294,28 +1273,21 @@ export void device_render (uniform int* uniform pixels, xfm.vz = make_Vec3f(-sin(t1),0,cos(t1)); /* calculate transformations to move instances in circles */ - g_instance[0]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(+cos(t0),0.0f,+sin(t0))); - g_instance[1]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(-cos(t0),0.0f,-sin(t0))); - g_instance[2]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(-sin(t0),0.0f,+cos(t0))); - g_instance[3]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(+sin(t0),0.0f,-cos(t0))); + data.g_instance[0]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(+cos(t0),0.0f,+sin(t0))); + data.g_instance[1]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(-cos(t0),0.0f,-sin(t0))); + data.g_instance[2]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(-sin(t0),0.0f,+cos(t0))); + data.g_instance[3]->local2world = make_AffineSpace3f(xfm,2.2f*make_Vec3f(+sin(t0),0.0f,-cos(t0))); /* update scene */ - updateInstance(g_scene,g_instance[0]); - updateInstance(g_scene,g_instance[1]); - updateInstance(g_scene,g_instance[2]); - updateInstance(g_scene,g_instance[3]); - rtcCommitScene (g_scene); + updateInstance(data.g_scene,data.g_instance[0]); + updateInstance(data.g_scene,data.g_instance[1]); + updateInstance(data.g_scene,data.g_instance[2]); + updateInstance(data.g_scene,data.g_instance[3]); + rtcCommitScene (data.g_scene); } /* called by the C++ code for cleanup */ export void device_cleanup () { - rtcReleaseScene (g_scene); g_scene = NULL; - rtcReleaseScene (g_scene0); g_scene0 = NULL; - rtcReleaseScene (g_scene1); g_scene1 = NULL; - rtcReleaseScene (g_scene2); g_scene2 = NULL; - rtcReleaseDevice(g_device); g_device = NULL; - delete[] g_spheres; g_spheres = NULL; - delete g_sphere0; g_sphere0 = NULL; - delete g_sphere1; g_sphere1 = NULL; + TutorialData_Destructor(&data); } diff --git a/tutorials/user_geometry/user_geometry_device.isph b/tutorials/user_geometry/user_geometry_device.isph new file mode 100644 index 0000000000..078c3b9400 --- /dev/null +++ b/tutorials/user_geometry/user_geometry_device.isph @@ -0,0 +1,69 @@ +// Copyright 2009-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "../common/tutorial/tutorial_device.isph" + +struct Sphere +{ + ALIGNED_STRUCT_(16) + Vec3f p; //!< position of the sphere + float r; //!< radius of the sphere + RTCGeometry geometry; + uniform unsigned int geomID; +}; + +struct Instance +{ + ALIGNED_STRUCT_(16) + RTCGeometry geometry; + RTCScene object; + uniform int userID; + AffineSpace3f local2world; + AffineSpace3f world2local; + LinearSpace3f normal2world; + Vec3f lower; + Vec3f upper; +}; + +struct TutorialData +{ + /* scene data */ + RTCScene g_scene; + RTCScene g_scene0; + RTCScene g_scene1; + RTCScene g_scene2; + uniform Sphere* uniform g_spheres; + uniform Sphere* uniform g_sphere0; + uniform Sphere* uniform g_sphere1; + + uniform Instance* uniform g_instance[4]; + + uniform Vec3f colors[5][4]; +}; + +inline void TutorialData_Constructor(uniform TutorialData* uniform This) +{ + This->g_scene = NULL; + This->g_scene0 = NULL; + This->g_scene1 = NULL; + This->g_scene2 = NULL; + This->g_spheres = NULL; + This->g_sphere0 = NULL; + This->g_sphere1 = NULL; + This->g_instance[0] = NULL; + This->g_instance[1] = NULL; + This->g_instance[2] = NULL; + This->g_instance[3] = NULL; +} + +inline void TutorialData_Destructor(uniform TutorialData* uniform This) +{ + rtcReleaseScene (This->g_scene); This->g_scene = NULL; + rtcReleaseScene (This->g_scene0); This->g_scene0 = NULL; + rtcReleaseScene (This->g_scene1); This->g_scene1 = NULL; + rtcReleaseScene (This->g_scene2); This->g_scene2 = NULL; + rtcReleaseDevice(g_device); g_device = NULL; + delete[] This->g_spheres; This->g_spheres = NULL; + delete This->g_sphere0; This->g_sphere0 = NULL; + delete This->g_sphere1; This->g_sphere1 = NULL; +} diff --git a/tutorials/verify/CMakeLists.txt b/tutorials/verify/CMakeLists.txt index 35034b2608..775eee49a2 100644 --- a/tutorials/verify/CMakeLists.txt +++ b/tutorials/verify/CMakeLists.txt @@ -1,43 +1,42 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 IF(NOT EMBREE_API_NAMESPACE) ADD_LIBRARY(c99_compile_test STATIC api_c99.c) ENDIF() -ADD_EXECUTABLE(verify ../../kernels/embree.rc verify.cpp ../common/tutorial/application.cpp ../../kernels/common/geometry.cpp) -TARGET_LINK_LIBRARIES(verify sys math scenegraph embree tasking) -SET_PROPERTY(TARGET verify PROPERTY FOLDER tutorials) -SET_PROPERTY(TARGET verify APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -INSTALL(TARGETS verify DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples) -SIGN_TARGET(verify) +ADD_EXECUTABLE(embree_verify ../../kernels/embree.rc verify.cpp ../common/tutorial/application.cpp ../../kernels/common/geometry.cpp) +TARGET_LINK_LIBRARIES(embree_verify sys math scenegraph embree tasking) +SET_PROPERTY(TARGET embree_verify PROPERTY FOLDER tutorials) +SET_PROPERTY(TARGET embree_verify APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") +INSTALL(TARGETS embree_verify DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples) +SIGN_TARGET(embree_verify) IF (BUILD_TESTING AND EMBREE_TESTING_INTENSITY GREATER 0) IF (EMBREE_TESTING_INTENSITY GREATER 1) - ADD_TEST(NAME verify COMMAND verify --no-colors --intensity 2) + ADD_TEST(NAME embree_verify COMMAND embree_verify --no-colors --intensity 2) ELSE() - ADD_TEST(NAME verify COMMAND verify --no-colors) + ADD_TEST(NAME embree_verify COMMAND embree_verify --no-colors) ENDIF() - SET_TESTS_PROPERTIES(verify PROPERTIES TIMEOUT 7000) + SET_TESTS_PROPERTIES(embree_verify PROPERTIES TIMEOUT 7000) IF (EMBREE_TESTING_MEMCHECK) - ADD_MEMCHECK_TEST(verify_memcheck verify + ADD_MEMCHECK_TEST(embree_verify_memcheck embree_verify --no-colors --intensity 0.1 --skip .*memory_consumption.* --skip .*regression_.*_build_join # causes some issues with TBB --skip .*SSE4.* # to run faster --skip .*AVX.* # valgrind does not support AVX --skip .*AVX2.* # valgrind does not support AVX2 - --skip .*AVX512KNL.* # valgrind does not support AVX512KNL - --skip .*AVX512SKX.* # valgrind does not support AVX512SKX + --skip .*AVX512.* # valgrind does not support AVX512 ) - set_tests_properties(verify_memcheck PROPERTIES TIMEOUT 10800) + set_tests_properties(embree_verify_memcheck PROPERTIES TIMEOUT 15000) ENDIF() IF (EMBREE_TESTING_BENCHMARK) - ADD_TEST(NAME verify_benchmarks COMMAND verify + ADD_TEST(NAME embree_verify_benchmarks COMMAND embree_verify --no-colors --cdash --benchmark-tolerance 0.05 --database "${EMBREE_TESTING_BENCHMARK_DATABASE}" @@ -45,6 +44,6 @@ IF (BUILD_TESTING AND EMBREE_TESTING_INTENSITY GREATER 0) --skip .*_120.* --skip .*_1k.* --skip .*_10k.* --skip .*100k.* # skip all smaller build benchmarks --run .*embree_reported_memory.* ) - set_tests_properties(verify_benchmarks PROPERTIES TIMEOUT 10800) + set_tests_properties(embree_verify_benchmarks PROPERTIES TIMEOUT 10800) ENDIF() ENDIF() diff --git a/tutorials/verify/api_c99.c b/tutorials/verify/api_c99.c index 2efae20e97..2438760fc0 100644 --- a/tutorials/verify/api_c99.c +++ b/tutorials/verify/api_c99.c @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../../include/embree3/rtcore.h" diff --git a/tutorials/verify/rtcore_helpers.h b/tutorials/verify/rtcore_helpers.h index 3d7b054783..cbbc80f284 100644 --- a/tutorials/verify/rtcore_helpers.h +++ b/tutorials/verify/rtcore_helpers.h @@ -1,9 +1,9 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../../kernels/common/default.h" #include "../../include/embree3/rtcore.h" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE #include "../common/math/random_sampler.h" namespace embree diff --git a/tutorials/verify/verify.cpp b/tutorials/verify/verify.cpp index d3b015a482..e5a44e21d0 100644 --- a/tutorials/verify/verify.cpp +++ b/tutorials/verify/verify.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define _CRT_SECURE_NO_WARNINGS @@ -8,6 +8,7 @@ #include "../common/scenegraph/geometry_creation.h" #include "../common/math/closest_point.h" #include "../../common/algorithms/parallel_for.h" +#include "../../common/simd/simd.h" #include "../../kernels/common/context.h" #include "../../kernels/common/geometry.h" #include "../../kernels/common/scene.h" @@ -66,7 +67,7 @@ namespace embree { RTCError error = rtcGetDeviceError(device); if (error != RTC_ERROR_NONE) - throw std::runtime_error("Error occured: "+string_of(error)); + throw std::runtime_error("Error occurred: "+string_of(error)); } void AssertAnyError(RTCDevice device) @@ -597,27 +598,27 @@ namespace embree updateDatabase(state,bestStat,avgdb); /* print test result */ - std::cout << std::setw(8) << std::setprecision(3) << std::fixed << bestStat.getAvg() << " " << unit << " (+/-" << 100.0f*bestStat.getAvgSigma()/bestStat.getAvg() << "%)"; - if (passed) std::cout << state->green(" [PASSED]" ) << " (" << 100.0f*(bestStat.getAvg()-avgdb)/avgdb << "%) (" << i << " attempts)" << std::endl << std::flush; - else std::cout << state->red (" [FAILED]" ) << " (" << 100.0f*(bestStat.getAvg()-avgdb)/avgdb << "%) (" << i << " attempts)" << std::endl << std::flush; + double rate0 = 0; if (bestStat.getAvg()) rate0 = 100.0f*bestStat.getAvgSigma()/bestStat.getAvg(); + double rate1 = 0; if (avgdb ) rate1 = 100.0f*(bestStat.getAvg()-avgdb)/avgdb; + + std::cout << std::setw(8) << std::setprecision(3) << std::fixed << bestStat.getAvg() << " " << unit << " (+/-" << rate0 << "%)"; + if (passed) std::cout << state->green(" [PASSED]" ) << " (" << rate1 << "%) (" << i << " attempts)" << std::endl << std::flush; + else std::cout << state->red (" [FAILED]" ) << " (" << rate1 << "%) (" << i << " attempts)" << std::endl << std::flush; if (state->database != "") plotDatabase(state); /* print dart measurement */ - if (state->cdash) - { - //std::cout << "" << bestStat.getAvg() << "" << std::endl; - //std::cout << "" << bestStat.getAvgSigma() << "" << std::endl; - + //if (state->cdash) + //{ /* send plot only when test failed */ - if (!passed) - { - FileName base = state->database+FileName(name); - std::string command = std::string("cd ")+state->database.str()+std::string(" && gnuplot ") + FileName(name).addExt(".plot").str(); - if (system(command.c_str()) == 0) - std::cout << "" << base.addExt(".png") << "" << std::endl; - } - } + //if (!passed) + //{ + // FileName base = state->database+FileName(name); + // std::string command = std::string("cd ")+state->database.str()+std::string(" && gnuplot ") + FileName(name).addExt(".plot").str(); + // if (system(command.c_str()) == 0) + // std::cout << "" << base.addExt(".png") << "" << std::endl; + //} + //} sleepSeconds(0.1); cleanup(state); @@ -654,7 +655,7 @@ namespace embree std::atomic passed(true); -#if defined(__WIN32__) && !defined(__X86_64__) +#if defined(__WIN32__) && !defined(__64BIT__) /* deactivating parallel test execution on win32 platforms due to out-of-memory exceptions */ parallel = false; #endif @@ -1668,7 +1669,7 @@ namespace embree RTCGeometry hgeom3 = rtcGetGeometry(scene,geom3); AssertNoError(device); - for (size_t i=0; i<16; i++) + for (size_t i=0; i<17; i++) { bool enabled0 = i & 1, enabled1 = i & 2, enabled2 = i & 4, enabled3 = i & 8; if (enabled0) rtcEnableGeometry(hgeom0); else rtcDisableGeometry(hgeom0); AssertNoError(device); @@ -1699,6 +1700,88 @@ namespace embree } }; + struct DisableAndDetachGeometryTest : public VerifyApplication::Test + { + SceneFlags sflags; + + DisableAndDetachGeometryTest (std::string name, int isa, SceneFlags sflags) + : VerifyApplication::Test(name,isa,VerifyApplication::TEST_SHOULD_PASS), sflags(sflags) {} + + VerifyApplication::TestReturnValue run(VerifyApplication* state, bool silent) + { + RTCIntersectContext context; + rtcInitIntersectContext(&context); + + std::string cfg = state->rtcore + ",isa="+stringOfISA(isa); + RTCDeviceRef device = rtcNewDevice(cfg.c_str()); + errorHandler(nullptr,rtcGetDeviceError(device)); + VerifyScene scene(device,sflags); + AssertNoError(device); + unsigned geom[] = { + scene.addSphere (sampler,RTC_BUILD_QUALITY_MEDIUM,Vec3fa(-1,0,-1),1.0f,50).first, + scene.addQuadSphere (sampler,RTC_BUILD_QUALITY_MEDIUM,Vec3fa(-1,0,+1),1.0f,50).first, + scene.addSubdivSphere(sampler,RTC_BUILD_QUALITY_MEDIUM,Vec3fa(+1,0,-1),1.0f,5,4).first, + scene.addHair (sampler,RTC_BUILD_QUALITY_MEDIUM,Vec3fa(+1,0,+1),1.0f,1.0f,1).first, + }; + RTCGeometry hgeom[] = { + rtcGetGeometry(scene,geom[0]), + rtcGetGeometry(scene,geom[1]), + rtcGetGeometry(scene,geom[2]), + rtcGetGeometry(scene,geom[3]), + }; + AssertNoError(device); + + for (size_t j=0; j<4; ++j) + { + rtcEnableGeometry(hgeom[j]); + } + rtcCommitScene (scene); + AssertNoError(device); + + bool allOk = true; + for (size_t i=0; i<5; i++) + { + RTCRayHit ray0 = makeRay(Vec3fa(-1,10,-1),Vec3fa(0,-1,0)); + RTCRayHit ray1 = makeRay(Vec3fa(-1,10,+1),Vec3fa(0,-1,0)); + RTCRayHit ray2 = makeRay(Vec3fa(+1,10,-1),Vec3fa(0,-1,0)); + RTCRayHit ray3 = makeRay(Vec3fa(+1,10,+1),Vec3fa(0,-1,0)); + rtcIntersect1(scene,&context,&ray0); + rtcIntersect1(scene,&context,&ray1); + rtcIntersect1(scene,&context,&ray2); + rtcIntersect1(scene,&context,&ray3); + bool ok0 = i<=0 ? ray0.hit.geomID == 0 : ray0.hit.geomID == RTC_INVALID_GEOMETRY_ID; + bool ok1 = i<=1 ? ray1.hit.geomID == 1 : ray1.hit.geomID == RTC_INVALID_GEOMETRY_ID; + bool ok2 = i<=2 ? ray2.hit.geomID == 2 : ray2.hit.geomID == RTC_INVALID_GEOMETRY_ID; + bool ok3 = i<=3 ? ray3.hit.geomID == 3 : ray3.hit.geomID == RTC_INVALID_GEOMETRY_ID; + if (!ok0 || !ok1 || !ok2 || !ok3) + { + std::cout << "!" << std::flush; + allOk = false; + } + else + { + std::cout << "." << std::flush; + } + + if (i<4) + { + rtcDisableGeometry(hgeom[i]); + AssertNoError(device); + rtcDetachGeometry(scene,geom[i]); + AssertNoError(device); + rtcCommitScene (scene); + AssertNoError(device); + } + } + AssertNoError(device); + + if (allOk) + return VerifyApplication::PASSED; + else + return VerifyApplication::FAILED; + } + }; + struct UpdateTest : public VerifyApplication::IntersectTest { SceneFlags sflags; @@ -1753,10 +1836,10 @@ namespace embree rtcCommitScene (scene); AssertNoError(device); - RTCRayHit ray0 = makeRay(pos0+Vec3fa(0,10,0),Vec3fa(0,-1,0)); // hits geomID == 0 - RTCRayHit ray1 = makeRay(pos1+Vec3fa(0,10,0),Vec3fa(0,-1,0)); // hits geomID == 1 - RTCRayHit ray2 = makeRay(pos2+Vec3fa(0,10,0),Vec3fa(0,-1,0)); // hits geomID == 2 - RTCRayHit ray3 = makeRay(pos3+Vec3fa(0,10,0),Vec3fa(0,-1,0)); // hits geomID == 3 + RTCRayHit ray0 = makeRay(pos0+Vec3fa(0.1f,10,0.1f),Vec3fa(0,-1,0)); // hits geomID == 0 + RTCRayHit ray1 = makeRay(pos1+Vec3fa(0.1f,10,0.1f),Vec3fa(0,-1,0)); // hits geomID == 1 + RTCRayHit ray2 = makeRay(pos2+Vec3fa(0.1f,10,0.1f),Vec3fa(0,-1,0)); // hits geomID == 2 + RTCRayHit ray3 = makeRay(pos3+Vec3fa(0.1f,10,0.1f),Vec3fa(0,-1,0)); // hits geomID == 3 RTCRayHit testRays[4] = { ray0, ray1, ray2, ray3 }; const unsigned int maxRays = 100; @@ -1993,7 +2076,7 @@ namespace embree std::string cfg = state->rtcore + ",isa="+stringOfISA(isa); RTCDeviceRef device = rtcNewDevice(cfg.c_str()); errorHandler(nullptr,rtcGetDeviceError(device)); - size_t M = num_interpolation_vertices*N+16; // padds the arrays with some valid data + size_t M = num_interpolation_vertices*N+16; // pads the arrays with some valid data RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION); AssertNoError(device); @@ -2087,7 +2170,7 @@ namespace embree RTCDeviceRef device = rtcNewDevice(cfg.c_str()); errorHandler(nullptr,rtcGetDeviceError(device)); - size_t M = num_interpolation_vertices*N+16; // padds the arrays with some valid data + size_t M = num_interpolation_vertices*N+16; // pads the arrays with some valid data RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE); AssertNoError(device); @@ -2182,7 +2265,7 @@ namespace embree RTCDeviceRef device = rtcNewDevice(cfg.c_str()); errorHandler(nullptr,rtcGetDeviceError(device)); - size_t M = 16*N+16; // padds the arrays with some valid data + size_t M = 16*N+16; // pads the arrays with some valid data RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_GRID); AssertNoError(device); @@ -2269,7 +2352,7 @@ namespace embree RTCDeviceRef device = rtcNewDevice(cfg.c_str()); errorHandler(nullptr,rtcGetDeviceError(device)); - size_t M = num_interpolation_hair_vertices*N+16; // padds the arrays with some valid data + size_t M = num_interpolation_hair_vertices*N+16; // pads the arrays with some valid data RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); AssertNoError(device); @@ -2940,7 +3023,7 @@ namespace embree } AssertNoError(device); - double failRate = double(numFailures) / double(numTests); + double failRate = double(numFailures) / double(max(size_t(1),numTests)); bool failed = failRate > 0.00002; if (!silent) { printf(" (%f%%)", 100.0f*failRate); fflush(stdout); } return (VerifyApplication::TestReturnValue)(!failed); @@ -3009,7 +3092,7 @@ namespace embree } AssertNoError(device); - double failRate = double(numFailures) / double(numTests); + double failRate = double(numFailures) / double(max(size_t(1),numTests)); bool failed = failRate > 0.00002; if (!silent) { printf(" (%f%%)", 100.0f*failRate); fflush(stdout); } return (VerifyApplication::TestReturnValue)(!failed); @@ -5135,7 +5218,7 @@ namespace embree database(""), update_database(false), benchmark_tolerance(0.05f), usecolors(true) { - rtcore = ""; // do not start threads nor set affinty for normal tests + rtcore = ""; // do not start threads nor set affinity for normal tests device = rtcNewDevice(rtcore.c_str()); #if defined(__WIN32__) @@ -5160,11 +5243,8 @@ namespace embree #if defined(EMBREE_TARGET_AVX2) if (hasISA(AVX2)) isas.push_back(AVX2); #endif -#if defined(EMBREE_TARGET_AVX512KNL) - if (hasISA(AVX512KNL)) isas.push_back(AVX512KNL); -#endif -#if defined(EMBREE_TARGET_AVX512SKX) - if (hasISA(AVX512SKX)) isas.push_back(AVX512SKX); +#if defined(EMBREE_TARGET_AVX512) + if (hasISA(AVX512)) isas.push_back(AVX512); #endif /* create list of all intersect modes to test */ @@ -5300,6 +5380,11 @@ namespace embree groups.top()->add(new EnableDisableGeometryTest(to_string(sflags),isa,sflags)); groups.pop(); + push(new TestGroup("disable_detach_geometry",true,true)); + for (auto sflags : sceneFlagsDynamic) + groups.top()->add(new DisableAndDetachGeometryTest(to_string(sflags),isa,sflags)); + groups.pop(); + push(new TestGroup("update",true,true)); for (auto sflags : sceneFlagsDynamic) { for (auto imode : intersectModes) { @@ -6029,6 +6114,11 @@ namespace embree int main(int argc, char** argv) { embree::VerifyApplication app; - return app.main(argc,argv); + int code = app.main(argc,argv); + + /* wait for user input under Windows when opened in separate window */ + embree::waitForKeyPressedUnderWindows(); + + return code; } diff --git a/tutorials/verify/verify.h b/tutorials/verify/verify.h index cc75fe2d19..2cff3f78de 100644 --- a/tutorials/verify/verify.h +++ b/tutorials/verify/verify.h @@ -1,11 +1,11 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* we include the Embree headers the very first to make sure they * always compile without any internal Embree specific stuff. */ #include "../../include/embree3/rtcore.h" #include "../../include/embree3/rtcore_ray.h" -RTC_NAMESPACE_OPEN +RTC_NAMESPACE_USE /* now we include all Embree internal files we need for testing */ #include "../../kernels/common/default.h" diff --git a/tutorials/viewer/CMakeLists.txt b/tutorials/viewer/CMakeLists.txt index 58d38693b7..fad0716d36 100644 --- a/tutorials/viewer/CMakeLists.txt +++ b/tutorials/viewer/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/viewer/viewer.cpp b/tutorials/viewer/viewer.cpp index bb70162df8..6a762f3859 100644 --- a/tutorials/viewer/viewer.cpp +++ b/tutorials/viewer/viewer.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -24,7 +25,7 @@ namespace embree void postParseCommandLine() override { /* load default scene if none specified */ - if (scene->size() == 0 && sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/cornell_box.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } @@ -33,5 +34,8 @@ namespace embree } int main(int argc, char** argv) { - return embree::Tutorial().main(argc,argv); + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv); + } + return embree::Tutorial().main(argc, argv); } diff --git a/tutorials/viewer/viewer_device.cpp b/tutorials/viewer/viewer_device.cpp index 575c9b5e18..ee24ac62a8 100644 --- a/tutorials/viewer/viewer_device.cpp +++ b/tutorials/viewer/viewer_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "viewer_device.h" @@ -63,7 +63,6 @@ void updateMeshEdgeLevelBufferTask (int taskIndex, int threadIndex, ISPCScene* ISPCGeometry* geometry = g_ispc_scene->geometries[taskIndex]; if (geometry->type != SUBDIV_MESH) return; ISPCSubdivMesh* mesh = (ISPCSubdivMesh*) geometry; - unsigned int geomID = mesh->geom.geomID; if (mesh->numFaces < 10000) { updateEdgeLevelBuffer(mesh,cam_pos,0,mesh->numFaces); rtcUpdateGeometryBuffer(geometry->geometry, RTC_BUFFER_TYPE_LEVEL, 0); @@ -126,61 +125,10 @@ RTCScene convertScene(ISPCScene* scene_in) RTCScene scene_out = ConvertScene(g_device, g_ispc_scene, RTC_BUILD_QUALITY_MEDIUM); rtcSetSceneProgressMonitorFunction(scene_out,monitorProgressFunction,nullptr); - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) rtcCommitScene(geometry->scene); - } - } - /* commit changes to scene */ return scene_out; } - -void postIntersectGeometry(const Ray& ray, DifferentialGeometry& dg, ISPCGeometry* geometry, int& materialID) -{ - if (geometry->type == TRIANGLE_MESH) - { - ISPCTriangleMesh* mesh = (ISPCTriangleMesh*) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == QUAD_MESH) - { - ISPCQuadMesh* mesh = (ISPCQuadMesh*) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == SUBDIV_MESH) - { - ISPCSubdivMesh* mesh = (ISPCSubdivMesh*) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == CURVES) - { - ISPCHairSet* mesh = (ISPCHairSet*) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == GRID_MESH) - { - ISPCGridMesh* mesh = (ISPCGridMesh*) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == POINTS) - { - ISPCPointSet* set = (ISPCPointSet*) geometry; - materialID = set->geom.materialID; - } - else if (geometry->type == GROUP) { - unsigned int geomID = ray.geomID; { - postIntersectGeometry(ray,dg,((ISPCGroup*) geometry)->geometries[geomID],materialID); - } - } - else - assert(false); -} - AffineSpace3fa calculate_interpolated_space (ISPCInstance* instance, float gtime) { if (instance->numTimeSteps == 1) @@ -196,37 +144,29 @@ AffineSpace3fa calculate_interpolated_space (ISPCInstance* instance, float gtime typedef ISPCInstance* ISPCInstancePtr; -inline int postIntersect(const TutorialData& data, const Ray& ray, DifferentialGeometry& dg) +unsigned int postIntersect(const TutorialData& data, const Ray& ray, DifferentialGeometry& dg) { - int materialID = 0; - unsigned int instID = ray.instID[0]; { - unsigned int geomID = ray.geomID; { - ISPCGeometry* geometry = nullptr; - if (data.instancing_mode != ISPC_INSTANCING_NONE) { - ISPCInstance* instance = (ISPCInstancePtr) data.ispc_scene->geometries[instID]; - geometry = instance->child; - } else { - geometry = data.ispc_scene->geometries[geomID]; - } - postIntersectGeometry(ray,dg,geometry,materialID); - } - } - - if (data.instancing_mode != ISPC_INSTANCING_NONE) + AffineSpace3fa local2world = AffineSpace3fa::scale(Vec3fa(1)); + ISPCGeometry** geometries = data.ispc_scene->geometries; + + for (int i=0; igeometries[instID]; - - /* convert normals */ - //AffineSpace3fa space = (1.0f-ray.time())*AffineSpace3fa(instance->space0) + ray.time()*AffineSpace3fa(instance->space1); - AffineSpace3fa space = calculate_interpolated_space(instance,ray.time()); - dg.Ng = xfmVector(space,dg.Ng); - dg.Ns = xfmVector(space,dg.Ns); - } + const unsigned int instID = ray.instID[i]; + if (instID == -1) break; + + ISPCInstance* instance = (ISPCInstancePtr) geometries[instID]; + local2world = local2world * calculate_interpolated_space(instance,ray.time()); + + assert(instance->child->type == GROUP); + geometries = ((ISPCGroup*)instance->child)->geometries; } + ISPCGeometry* mesh = geometries[ray.geomID]; + unsigned int materialID = mesh->materialID; + + dg.Ng = xfmVector(local2world,dg.Ng); + dg.Ns = xfmVector(local2world,dg.Ns); + return materialID; } @@ -285,7 +225,7 @@ void renderPixelStandard(const TutorialData& data, if (ray.geomID != RTC_INVALID_GEOMETRY_ID) // FIXME: workaround for ISPC bug, location reached with empty execution mask { Vec3fa dPdu,dPdv; - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { rtcInterpolate1(rtcGetGeometry(data.scene,geomID),ray.primID,ray.u,ray.v,RTC_BUFFER_TYPE_VERTEX,0,nullptr,&dPdu.x,&dPdv.x,3); } dg.Ns = cross(dPdv,dPdu); @@ -389,6 +329,9 @@ extern "C" void device_render (int* pixels, updateEdgeLevels(g_ispc_scene,camera.xfm.p); rtcCommitScene (data.scene); } + + if (g_animation_mode) + UpdateScene(g_ispc_scene, time); } } diff --git a/tutorials/viewer/viewer_device.h b/tutorials/viewer/viewer_device.h index 883122a534..80ddcea430 100644 --- a/tutorials/viewer/viewer_device.h +++ b/tutorials/viewer/viewer_device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" @@ -11,6 +11,7 @@ namespace embree { extern "C" ISPCScene* g_ispc_scene; extern "C" int g_instancing_mode; extern "C" float g_min_width; +extern "C" int g_animation_mode; struct TutorialData { diff --git a/tutorials/viewer/viewer_device.ispc b/tutorials/viewer/viewer_device.ispc index f42876d0a6..0c017194b0 100644 --- a/tutorials/viewer/viewer_device.ispc +++ b/tutorials/viewer/viewer_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "viewer_device.isph" @@ -61,7 +61,6 @@ task void updateMeshEdgeLevelBufferTask( uniform ISPCScene* uniform scene_in, co uniform ISPCGeometry* uniform geometry = g_ispc_scene->geometries[taskIndex]; if (geometry->type != SUBDIV_MESH) return; uniform ISPCSubdivMesh* uniform mesh = (uniform ISPCSubdivMesh* uniform) geometry; - uniform unsigned int geomID = mesh->geom.geomID; if (mesh->numFaces < 10000) { updateEdgeLevelBuffer(mesh,cam_pos,0,mesh->numFaces); rtcUpdateGeometryBuffer(geometry->geometry, RTC_BUFFER_TYPE_LEVEL, 0); @@ -116,62 +115,11 @@ RTCScene convertScene(uniform ISPCScene* uniform scene_in) RTCScene scene_out = ConvertScene(g_device, g_ispc_scene, RTC_BUILD_QUALITY_MEDIUM); rtcSetSceneProgressMonitorFunction(scene_out,monitorProgressFunction,NULL); - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (uniform unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* uniform geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) rtcCommitScene(geometry->scene); - } - } - /* commit changes to scene */ return scene_out; } - -void postIntersectGeometry(const Ray& ray, DifferentialGeometry& dg, uniform ISPCGeometry* uniform geometry, int& materialID) -{ - if (geometry->type == TRIANGLE_MESH) - { - uniform ISPCTriangleMesh* uniform mesh = (uniform ISPCTriangleMesh* uniform) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == QUAD_MESH) - { - uniform ISPCQuadMesh* uniform mesh = (uniform ISPCQuadMesh* uniform) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == SUBDIV_MESH) - { - uniform ISPCSubdivMesh* uniform mesh = (uniform ISPCSubdivMesh* uniform) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == CURVES) - { - uniform ISPCHairSet* uniform mesh = (uniform ISPCHairSet* uniform) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == GRID_MESH) - { - uniform ISPCGridMesh* uniform mesh = (uniform ISPCGridMesh* uniform) geometry; - materialID = mesh->geom.materialID; - } - else if (geometry->type == POINTS) - { - uniform ISPCPointSet* uniform set = (uniform ISPCPointSet* uniform) geometry; - materialID = set->geom.materialID; - } - else if (geometry->type == GROUP) { - foreach_unique (geomID in ray.geomID) { - postIntersectGeometry(ray,dg,((uniform ISPCGroup*) geometry)->geometries[geomID],materialID); - } - } - else - assert(false); -} - -AffineSpace3f calculate_interpolated_space (uniform ISPCInstance* uniform instance, float gtime) +AffineSpace3f calculate_interpolated_space (uniform ISPCInstance* instance, float gtime) { if (instance->numTimeSteps == 1) return make_AffineSpace3f(instance->spaces[0]); @@ -184,39 +132,31 @@ AffineSpace3f calculate_interpolated_space (uniform ISPCInstance* uniform instan return (1.0f-ftime)*make_AffineSpace3f(instance->spaces[itime+0]) + ftime*make_AffineSpace3f(instance->spaces[itime+1]); } -typedef ISPCInstance* uniform ISPCInstancePtr; +typedef ISPCInstance* ISPCInstancePtr; -inline int postIntersect(const uniform TutorialData& data, const Ray& ray, DifferentialGeometry& dg) +unsigned int postIntersect(const uniform TutorialData& data, const Ray& ray, DifferentialGeometry& dg) { - int materialID = 0; - foreach_unique (instID in ray.instID[0]) { - foreach_unique (geomID in ray.geomID) { - ISPCGeometry* uniform geometry = NULL; - if (data.instancing_mode != ISPC_INSTANCING_NONE) { - ISPCInstance* uniform instance = (ISPCInstancePtr) data.ispc_scene->geometries[instID]; - geometry = instance->child; - } else { - geometry = data.ispc_scene->geometries[geomID]; - } - postIntersectGeometry(ray,dg,geometry,materialID); - } - } - - if (data.instancing_mode != ISPC_INSTANCING_NONE) + AffineSpace3f local2world = make_AffineSpace3f_scale(make_Vec3f(1)); + ISPCGeometry* uniform* geometries = data.ispc_scene->geometries; + + for (uniform int i=0; igeometries[instID]; - - /* convert normals */ - //AffineSpace3f space = (1.0f-ray.time)*make_AffineSpace3f(instance->space0) + ray.time*make_AffineSpace3f(instance->space1); - AffineSpace3f space = calculate_interpolated_space(instance,ray.time); - dg.Ng = xfmVector(space,dg.Ng); - dg.Ns = xfmVector(space,dg.Ns); - } + const unsigned int instID = ray.instID[i]; + if (instID == -1) break; + + ISPCInstance* instance = (ISPCInstancePtr) geometries[instID]; + local2world = local2world * calculate_interpolated_space(instance,ray.time); + + assert(instance->child->type == GROUP); + geometries = ((ISPCGroup*)instance->child)->geometries; } + ISPCGeometry* mesh = geometries[ray.geomID]; + unsigned int materialID = mesh->materialID; + + dg.Ng = xfmVector(local2world,dg.Ng); + dg.Ns = xfmVector(local2world,dg.Ns); + return materialID; } @@ -375,6 +315,9 @@ export void device_render (uniform int* uniform pixels, updateEdgeLevels(g_ispc_scene,camera.xfm.p); rtcCommitScene (data.scene); } + + if (g_animation_mode) + UpdateScene(g_ispc_scene, time); } } diff --git a/tutorials/viewer/viewer_device.isph b/tutorials/viewer/viewer_device.isph index 4a8888eb9f..632c20c690 100644 --- a/tutorials/viewer/viewer_device.isph +++ b/tutorials/viewer/viewer_device.isph @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph" @@ -9,6 +9,7 @@ extern uniform ISPCScene* uniform g_ispc_scene; extern uniform int g_instancing_mode; extern uniform float g_min_width; +extern uniform int g_animation_mode; struct TutorialData { diff --git a/tutorials/viewer_anim/CMakeLists.txt b/tutorials/viewer_anim/CMakeLists.txt index 5420c2f555..fe3f6f5e56 100644 --- a/tutorials/viewer_anim/CMakeLists.txt +++ b/tutorials/viewer_anim/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/viewer_anim/viewer_anim.cpp b/tutorials/viewer_anim/viewer_anim.cpp index 7928cf249e..4fb1e8bd0c 100644 --- a/tutorials/viewer_anim/viewer_anim.cpp +++ b/tutorials/viewer_anim/viewer_anim.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -13,7 +14,7 @@ namespace embree void postParseCommandLine() override { /* load default scene if none specified */ - if (sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/cornell_box.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } @@ -23,5 +24,8 @@ namespace embree } int main(int argc, char** argv) { + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv); + } return embree::Tutorial().main(argc,argv); } diff --git a/tutorials/viewer_anim/viewer_anim_device.cpp b/tutorials/viewer_anim/viewer_anim_device.cpp index fe8d04bc2f..d34ff19d90 100644 --- a/tutorials/viewer_anim/viewer_anim_device.cpp +++ b/tutorials/viewer_anim/viewer_anim_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.h" @@ -39,7 +39,7 @@ void convertTriangleMesh(ISPCTriangleMesh* mesh, RTCScene scene_out) rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, mesh->triangles, 0, sizeof(ISPCTriangle), mesh->numTriangles); rtcCommitGeometry(geom); mesh->geom.geometry = geom; - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } void convertQuadMesh(ISPCQuadMesh* mesh, RTCScene scene_out) @@ -53,7 +53,7 @@ void convertQuadMesh(ISPCQuadMesh* mesh, RTCScene scene_out) rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT4, mesh->quads, 0, sizeof(ISPCQuad), mesh->numQuads); rtcCommitGeometry(geom); mesh->geom.geometry = geom; - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } void convertSubdivMesh(ISPCSubdivMesh* mesh, RTCScene scene_out) @@ -76,7 +76,7 @@ void convertSubdivMesh(ISPCSubdivMesh* mesh, RTCScene scene_out) rtcSetGeometrySubdivisionMode(geom, 0, mesh->position_subdiv_mode); rtcCommitGeometry(geom); mesh->geom.geometry = geom; - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } void convertCurveGeometry(ISPCHairSet* hair, RTCScene scene_out) @@ -94,7 +94,7 @@ void convertCurveGeometry(ISPCHairSet* hair, RTCScene scene_out) rtcSetGeometryTessellationRate(geom,(float)hair->tessellation_rate); rtcCommitGeometry(geom); hair->geom.geometry = geom; - hair->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } unsigned int getNumObjects(ISPCScene* scene_in) { diff --git a/tutorials/viewer_anim/viewer_anim_device.ispc b/tutorials/viewer_anim/viewer_anim_device.ispc index 7bfe5426fc..80397bf494 100644 --- a/tutorials/viewer_anim/viewer_anim_device.ispc +++ b/tutorials/viewer_anim/viewer_anim_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.isph" @@ -37,7 +37,7 @@ void convertTriangleMesh(uniform ISPCTriangleMesh* uniform mesh, RTCScene scene_ rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, mesh->triangles, 0, sizeof(uniform ISPCTriangle), mesh->numTriangles); rtcCommitGeometry(geom); mesh->geom.geometry = geom; - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } void convertQuadMesh(uniform ISPCQuadMesh* uniform mesh, RTCScene scene_out) @@ -51,7 +51,7 @@ void convertQuadMesh(uniform ISPCQuadMesh* uniform mesh, RTCScene scene_out) rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT4, mesh->quads, 0, sizeof(uniform ISPCQuad), mesh->numQuads); rtcCommitGeometry(geom); mesh->geom.geometry = geom; - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } void convertSubdivMesh(uniform ISPCSubdivMesh* uniform mesh, RTCScene scene_out) @@ -74,7 +74,7 @@ void convertSubdivMesh(uniform ISPCSubdivMesh* uniform mesh, RTCScene scene_out) rtcSetGeometrySubdivisionMode(geom, 0, mesh->position_subdiv_mode); rtcCommitGeometry(geom); mesh->geom.geometry = geom; - mesh->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } void convertCurveGeometry(uniform ISPCHairSet* uniform hair, RTCScene scene_out) @@ -92,7 +92,7 @@ void convertCurveGeometry(uniform ISPCHairSet* uniform hair, RTCScene scene_out) rtcSetGeometryTessellationRate(geom,(float)hair->tessellation_rate); rtcCommitGeometry(geom); hair->geom.geometry = geom; - hair->geom.geomID = rtcAttachGeometry(scene_out,geom); + rtcAttachGeometry(scene_out,geom); } uniform unsigned int getNumObjects(uniform ISPCScene* uniform scene_in) { diff --git a/tutorials/viewer_stream/CMakeLists.txt b/tutorials/viewer_stream/CMakeLists.txt index e6c670a306..d4dfce34dc 100644 --- a/tutorials/viewer_stream/CMakeLists.txt +++ b/tutorials/viewer_stream/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/viewer_stream/viewer_stream.cpp b/tutorials/viewer_stream/viewer_stream.cpp index c4f22e0bfd..f345f5ee44 100644 --- a/tutorials/viewer_stream/viewer_stream.cpp +++ b/tutorials/viewer_stream/viewer_stream.cpp @@ -1,7 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" +#include "../common/tutorial/benchmark_render.h" namespace embree { @@ -13,7 +14,7 @@ namespace embree void postParseCommandLine() override { /* load default scene if none specified */ - if (sceneFilename.size() == 0) { + if (scene_empty_post_parse()) { FileName file = FileName::executableFolder() + FileName("models/cornell_box.ecs"); parseCommandLine(new ParseStream(new LineCommentFilter(file, "#")), file.path()); } @@ -23,5 +24,8 @@ namespace embree } int main(int argc, char** argv) { - return embree::Tutorial().main(argc,argv); + if (embree::TutorialBenchmark::benchmark(argc, argv)) { + return embree::TutorialBenchmark(embree::renderBenchFunc).main(argc, argv); + } + return embree::Tutorial().main(argc, argv); } diff --git a/tutorials/viewer_stream/viewer_stream_device.cpp b/tutorials/viewer_stream/viewer_stream_device.cpp index 65adc2c385..48be1b2cff 100644 --- a/tutorials/viewer_stream/viewer_stream_device.cpp +++ b/tutorials/viewer_stream/viewer_stream_device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.h" @@ -67,7 +67,6 @@ void updateMeshEdgeLevelBufferTask (int taskIndex, int threadIndex, ISPCScene* ISPCGeometry* geometry = g_ispc_scene->geometries[taskIndex]; if (geometry->type != SUBDIV_MESH) return; ISPCSubdivMesh* mesh = (ISPCSubdivMesh*) geometry; - unsigned int geomID = mesh->geom.geomID; if (mesh->numFaces < 10000) { updateEdgeLevelBuffer(mesh,cam_pos,0,mesh->numFaces); rtcUpdateGeometryBuffer(geometry->geometry,RTC_BUFFER_TYPE_LEVEL,0); @@ -111,16 +110,6 @@ void updateEdgeLevels(ISPCScene* scene_in, const Vec3fa& cam_pos) RTCScene convertScene(ISPCScene* scene_in) { RTCScene scene_out = ConvertScene(g_device, scene_in,RTC_BUILD_QUALITY_MEDIUM); - - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) rtcCommitScene(geometry->scene); - } - } - return scene_out; } @@ -221,7 +210,7 @@ void postIntersectGeometry(const Ray& ray, DifferentialGeometry& dg, ISPCGeometr materialID = mesh->geom.materialID; } else if (geometry->type == GROUP) { - unsigned int geomID = ray.geomID; { + auto geomID = ray.geomID; { postIntersectGeometry(ray,dg,((ISPCGroup*) geometry)->geometries[geomID],materialID); } } @@ -247,8 +236,8 @@ typedef ISPCInstance* ISPCInstancePtr; inline int postIntersect(const Ray& ray, DifferentialGeometry& dg) { int materialID = 0; - unsigned int instID = ray.instID[0]; { - unsigned int geomID = ray.geomID; { + auto instID = ray.instID[0]; { + auto geomID = ray.geomID; { ISPCGeometry* geometry = nullptr; if (g_instancing_mode != ISPC_INSTANCING_NONE) { ISPCInstance* instance = (ISPCInstancePtr) g_ispc_scene->geometries[instID]; @@ -262,7 +251,7 @@ inline int postIntersect(const Ray& ray, DifferentialGeometry& dg) if (g_instancing_mode != ISPC_INSTANCING_NONE) { - unsigned int instID = ray.instID[0]; + auto instID = ray.instID[0]; { /* get instance and geometry pointers */ ISPCInstance* instance = (ISPCInstancePtr) g_ispc_scene->geometries[instID]; diff --git a/tutorials/viewer_stream/viewer_stream_device.ispc b/tutorials/viewer_stream/viewer_stream_device.ispc index 03a0cfa22a..fc830668b3 100644 --- a/tutorials/viewer_stream/viewer_stream_device.ispc +++ b/tutorials/viewer_stream/viewer_stream_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/math/random_sampler.isph" @@ -65,7 +65,6 @@ task void updateMeshEdgeLevelBufferTask( uniform ISPCScene* uniform scene_in, co uniform ISPCGeometry* uniform geometry = g_ispc_scene->geometries[taskIndex]; if (geometry->type != SUBDIV_MESH) return; uniform ISPCSubdivMesh* uniform mesh = (uniform ISPCSubdivMesh* uniform) geometry; - uniform unsigned int geomID = mesh->geom.geomID; if (mesh->numFaces < 10000) { updateEdgeLevelBuffer(mesh,cam_pos,0,mesh->numFaces); rtcUpdateGeometryBuffer(geometry->geometry,RTC_BUFFER_TYPE_LEVEL,0); @@ -101,16 +100,6 @@ void updateEdgeLevels(uniform ISPCScene* uniform scene_in, const uniform Vec3fa& RTCScene convertScene(uniform ISPCScene* uniform scene_in) { RTCScene scene_out = ConvertScene(g_device, scene_in,RTC_BUILD_QUALITY_MEDIUM); - - /* commit individual objects in case of instancing */ - if (g_instancing_mode != ISPC_INSTANCING_NONE) - { - for (uniform unsigned int i=0; inumGeometries; i++) { - ISPCGeometry* uniform geometry = g_ispc_scene->geometries[i]; - if (geometry->type == GROUP) rtcCommitScene(geometry->scene); - } - } - return scene_out; } diff --git a/tutorials/voronoi/CMakeLists.txt b/tutorials/voronoi/CMakeLists.txt index 713dcab014..bbc5c4d91b 100644 --- a/tutorials/voronoi/CMakeLists.txt +++ b/tutorials/voronoi/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 INCLUDE(tutorial) diff --git a/tutorials/voronoi/voronoi.cpp b/tutorials/voronoi/voronoi.cpp index ef2602ac0a..26235d08f5 100644 --- a/tutorials/voronoi/voronoi.cpp +++ b/tutorials/voronoi/voronoi.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial.h" diff --git a/tutorials/voronoi/voronoi_device.cpp b/tutorials/voronoi/voronoi_device.cpp index 6412a28595..f9928deb3a 100644 --- a/tutorials/voronoi/voronoi_device.cpp +++ b/tutorials/voronoi/voronoi_device.cpp @@ -1,13 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.h" -#include - -/* include ImGUI */ -#include "../common/imgui/imgui.h" - #include #include diff --git a/tutorials/voronoi/voronoi_device.ispc b/tutorials/voronoi/voronoi_device.ispc index b4d4f93b14..73e6559500 100644 --- a/tutorials/voronoi/voronoi_device.ispc +++ b/tutorials/voronoi/voronoi_device.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/tutorial/tutorial_device.isph"