Compare commits

...
Author SHA1 Message Date
cbenthin c0d1b3a74a cleanups 2017-10-06 13:11:57 +02:00
cbenthin 7c539db74c explicit store after the ray loop cause much better code generation... 2017-10-05 19:21:42 +02:00
cbenthin 68f0344542 minor optimizations 2017-10-05 17:06:51 +02:00
cbenthin 4f0de63859 quick hack for occlusion SOA streams, which gets us almost back to previous perf levels 2017-10-04 18:31:23 +02:00
cbenthin c8ea4294ae reverted common direction code path 2017-10-03 15:26:05 +02:00
cbenthin 4243db227a saved current state in seperate branch 2017-10-03 11:06:39 +02:00
atafra dc961964ee cleanup 2017-10-01 16:16:20 +03:00
atafra cb1fb07edf cleanups 2017-10-01 16:05:16 +03:00
atafra d7ce521c89 fixed inefficiency in hybrid occluded_coherent() (~5% speedup) 2017-10-01 15:34:08 +03:00
atafra 3bf2e5d694 cleanup 2017-10-01 12:38:02 +03:00
atafra f3aa55fa73 cleanup 2017-09-30 16:52:52 +03:00
atafra d93226eedf cleanups 2017-09-30 15:03:18 +03:00
atafra 2d780d85fb hybrid occluded() cleanup 2017-09-30 14:21:46 +03:00
atafra e8aa112afa removed distance-based sorting from the hybrid occluded(), which improves performance significantly 2017-09-29 19:41:22 +03:00
Sven Woop c48d21814c updates 2017-09-22 15:09:48 +02:00
Sven Woop 729ece7292 update 2017-09-22 13:10:44 +02:00
Sven Woop ed8ee37967 setting product and upgrade GUI for WiX 2017-09-22 12:02:50 +02:00
Sven Woop 7a50a2d692 WiX also installs Embree to Intel folder under Program Files 2017-09-22 11:52:19 +02:00
Sven Woop 357c6f24c5 no longer installing tbb.dll into lib folder (but only to bin folder) 2017-09-22 11:49:52 +02:00
Sven Woop 83fcf53b95 replaced NSIS by WiX to generate MSI installer for Windows 2017-09-22 11:47:13 +02:00
Sven Woop c6498a29d0 compile fix for internal task scheduler 2017-09-21 07:19:34 +02:00
Sven Woop 6bf725ba7c fixed compile issues with ICC and internal task scheduler 2017-09-20 14:14:46 +02:00
CDash e9a402ecd1 reduced inline-factor to 150 for intel compiler on mac os to prevent internal compiler error 2017-09-20 06:26:17 -05:00
Sven Woop 2f6af2832d updated documentation 2017-09-19 16:28:30 +02:00
Sven Woop 640c6daa85 setting version to 2.17.0 2017-09-19 16:27:07 +02:00
Sven Woop 512811023f bugfix in rtcOccluded1 and rtcOccluded1Ex API functions for ISPC 2017-09-19 12:11:35 +02:00
Sven Woop c0a1dbb5d8 cleanups 2017-09-19 10:18:31 +02:00
Sven Woop 045c418031 fixed some Clang 5 compile warnings 2017-09-19 10:01:58 +02:00
Sven Woop 8956aee21c enabling stack protector for releases 2017-09-19 09:48:27 +02:00
Sven Woop 0d9bc8df72 enabled stack protector for releases 2017-09-19 09:45:43 +02:00
Sven Woop ca96c96cb3 disabled stack protector by default 2017-09-19 09:43:38 +02:00
Sven Woop 4c50caa6b1 Merge branch 'devel' of https://github.com/embree/embree into devel 2017-09-19 09:19:21 +02:00
Sven Woop 9edba0f4ea reduced stack requirement for verify IntersectWithMode function 2017-09-19 09:19:06 +02:00
Sven Woop f4626bb22e reduced stack requirement for subdiv code 2017-09-19 09:18:44 +02:00
cbenthin 7d66ef477b fixed few msvc compile warnings 2017-09-18 05:49:12 -07:00
cbenthin 1b3b7ecb38 fixed few msvc compile warnings 2017-09-18 05:39:24 -07:00
Sven Woop e082712373 enabling stack protector by default 2017-09-18 07:05:17 +02:00
Sven Woop 185ffc39d3 added more tests to gitlab-ci 2017-09-15 14:47:28 +02:00
Sven Woop 3f4c6ac6e3 verbose=0 for tests 2017-09-15 14:20:21 +02:00
Sven Woop 5e3b4cf0e2 updates to CI 2017-09-15 14:11:40 +02:00
Sven Woop dec21a5f65 updates to CI 2017-09-15 14:08:14 +02:00
Sven Woop 2b0c400355 updates to CI 2017-09-15 14:06:52 +02:00
Sven Woop 058e820efb updates 2017-09-15 14:04:55 +02:00
Sven Woop d633a5541d updates to test.cmake 2017-09-15 13:59:16 +02:00
Sven Woop 563fa8b32c updates to test.cmake 2017-09-15 13:51:44 +02:00
Sven Woop 0894d751f1 updates to test.cmake 2017-09-15 13:50:45 +02:00
Sven Woop 23e8a0389d updates to test.cmake 2017-09-15 13:44:51 +02:00
Sven Woop 54f29c991b updates to test.cmake 2017-09-15 13:42:12 +02:00
Sven Woop fd3af84024 updates 2017-09-15 13:34:06 +02:00
Sven Woop a9a868f252 updates to test.cmake 2017-09-15 13:24:09 +02:00
Sven Woop 870e7adc71 updates to test.cmake 2017-09-15 13:19:25 +02:00
Sven Woop bec88b6568 Merge branch 'devel' of gitlab.com:embree/embree into devel 2017-09-15 13:13:16 +02:00
Sven Woop 85a6d9c54c updates to test.py 2017-09-15 13:11:35 +02:00
Sven Woop 63919c188c updates 2017-09-15 12:40:05 +02:00
Sven Woop 76892f8577 updates to test.py script 2017-09-15 12:38:12 +02:00
Sven Woop 44e783d59d updates to test.py 2017-09-15 12:31:08 +02:00
Sven Woop 0a642420af updates to test script 2017-09-15 12:25:20 +02:00
Sven Woop d208cbb4d9 added embree test scripts 2017-09-15 11:15:39 +02:00
Sven Woop 0419f1d8cc bugfix in FindTBB.cmake 2017-09-15 09:56:31 +02:00
Sven Woop c2309bbf79 updates to CI 2017-09-15 09:48:31 +02:00
Sven Woop e9149e8e9a added .gitlab-ci.yml with experimental settings 2017-09-15 09:30:26 +02:00
Sven Woop c15bb92593 Added support for BVH8 when AVX target was not enabled but targets higher than AVX.
Previously we did not use BVH8 in this case. This makes it e.g. possible to build
Embree properly for AVX2 only.
2017-09-15 08:51:35 +02:00
Sven Woop a1b56e8adc never enabling stack protector for traversal kernels 2017-09-14 13:38:38 +02:00
Sven Woop d85aea4c1a cleanups in frustum.h 2017-09-14 11:50:19 +02:00
Sven Woop 4498acd035 setting max internal stream size to 32 for 32 bit platforms 2017-09-14 11:43:56 +02:00
Sven Woop 152073d7ac cleanups 2017-09-14 11:42:43 +02:00
Sven Woop a90002157c cleanups in bvh_intersector_stream.h 2017-09-14 11:37:15 +02:00
Sven Woop f8c8d55c44 specializing frustum for robust and fast mode 2017-09-14 11:34:56 +02:00
Sven Woop 97600fb260 cleanups 2017-09-14 11:28:54 +02:00
Sven Woop b6d6cba2a2 specializing Packet for robust and non-robust mode 2017-09-14 11:23:27 +02:00
Sven Woop ead4835d35 cleanups in Packet class 2017-09-14 11:17:30 +02:00
Sven Woop eb4906c79c adding Packet constructor 2017-09-14 11:13:55 +02:00
Sven Woop 85b65574bb NearFarPreCompute no longer templated 2017-09-14 10:55:21 +02:00
Sven Woop 363c005f8e moved more code into packet struct 2017-09-14 10:42:48 +02:00
Sven Woop 4422ca608c re-using packet box test 2017-09-14 10:05:56 +02:00
Sven Woop d38ac50b2b moving packet intersection code to packet struct 2017-09-14 09:51:53 +02:00
Sven Woop 4d05b49867 moving Packet struct 2017-09-14 09:41:20 +02:00
Sven Woop a22e54cc49 cleanups 2017-09-14 09:36:44 +02:00
Sven Woop 46d131e056 re-using frustum intersection in stream frustum kernel 2017-09-14 09:36:06 +02:00
Sven Woop f1d23c57ed updates to frustum intersection interface 2017-09-14 09:30:53 +02:00
Sven Woop 265044e73f using new frustum struct in frustum stream traverser 2017-09-14 09:25:44 +02:00
Sven Woop ca84d3425e modifying frustum interface 2017-09-14 09:08:35 +02:00
Sven Woop 418ec0bdfb unifying frustm intersection interface 2017-09-14 08:52:45 +02:00
Sven Woop 2d1f8a6a97 updates to bvh_intersector_stream.h 2017-09-14 08:45:24 +02:00
Sven Woop 9813d6a6ee re-using NearFarPreCompute struct 2017-09-14 08:40:44 +02:00
Sven Woop 255ab75c5f first step to separate frustum structure 2017-09-14 08:26:45 +02:00
Sven Woop ece6b8345c removed unused file 2017-09-14 08:09:15 +02:00
Sven Woop 59ec5d0fcd Merge branch 'devel' of https://github.com/embree/embree into devel 2017-09-14 08:08:34 +02:00
Sven Woop 2cd05a8b2b Removing KNL optimization of frustum code for ray packet mode.
This caused a 5% slowdown, but frustum path is still significantly
faster (38%) than hybrid kernel. This change will make it easier
having a single frustum infrastructure for all frustum kernels.
2017-09-14 08:06:15 +02:00
cbenthin 08e54eb4c1 cleanups 2017-09-13 13:57:01 +02:00
cbenthin fb13a85505 cleanups 2017-09-13 13:45:46 +02:00
Sven Woop fb81cb34de removed no longer required packet fallback from bvh_intersector_stream.cpp 2017-09-13 12:27:02 +02:00
Sven Woop 3ceca55050 enabling stream kernels also for SSE, this codepath was already implemented but not selected 2017-09-13 12:20:48 +02:00
Sven Woop 87d45e6096 Merge branch 'devel' of https://github.com/embree/embree into devel 2017-09-13 12:07:29 +02:00
Sven Woop 872ced9934 printing camera before rendering 2017-09-13 12:07:16 +02:00
cbenthin f987d717ef removed validIsec checks in stream filters 2017-09-13 12:01:59 +02:00
cbenthin 9b40fcb862 Merge branch 'devel' of https://github.com/embree/embree into devel 2017-09-13 11:56:58 +02:00
cbenthin 19605e0738 added fallback to packet intersectorNs to isa namespaces, removed fallback in accel.h 2017-09-13 11:56:52 +02:00
Sven Woop fe56a4dc3c renames in bvh_intersector_hybrid.h 2017-09-13 11:55:53 +02:00
Sven Woop 4994f64729 implemented robust stream traversal 2017-09-13 11:29:08 +02:00
Sven Woop 7b4af861f4 adding first robust code to bvh_intersector_stream.h 2017-09-13 11:10:20 +02:00
Sven Woop 82ef698bcf Passing Accel::Intersectors* instead of BVH* to all intersector routines.
This way all intersectors can properly fallback to other interectors.

Moved intersect helper functions from Accel to Accel::Intersectors struct.

Fixed issue in stream kernels, that did fallback to packet traversal
using scene->intersect. This is wrong as causes iteration over all BVH
types again.
2017-09-13 08:59:00 +02:00
cbenthin ca70fc388b re-added accels.validIsecN test in stream filters otherwise verify crashes 2017-09-12 21:04:08 +02:00
Sven Woop ae06ac06a9 Merge branch 'devel' of https://github.com/embree/embree into devel 2017-09-12 16:12:17 +02:00
Sven Woop e2656563b1 cleanups in stream filters, not isRobust and validISecN tests are not required 2017-09-12 16:12:04 +02:00
cbenthin 752e905ecc increased benchmark iterations for more consistent results 2017-09-12 15:17:45 +02:00
Sven Woop d9e046d0c3 cleanups 2017-09-12 12:58:17 +02:00
Sven Woop 5945b87db9 cleanups in bvh_intersector_stream.cpp 2017-09-12 12:26:40 +02:00
Sven Woop 0c92fff315 Removed MAX_RAYS_PER_OCTANT (we have no octant sorting anymore). Only using MAX_INTERNAL_STREAM_SIZE. 2017-09-12 12:24:50 +02:00
Sven Woop 360ad9d0c3 fixed interface of intersectN/occludedN functions to RayK<VSIZEX> 2017-09-12 12:03:52 +02:00
Sven Woop 6c34e0d090 variable renames in frustum traverser 2017-09-12 11:39:34 +02:00
Sven Woop 794d90069c variable renames in frustum traverser 2017-09-12 11:27:09 +02:00
Sven Woop fb8e4405c7 cleanups in frustum packet traverser, added docu to frustum packet traverser 2017-09-12 11:23:20 +02:00
Sven Woop 36d53847c7 cleanups 2017-09-12 09:45:06 +02:00
Sven Woop e45aabfb8a added docu to maxDepth BVH member 2017-09-12 09:12:14 +02:00
Sven Woop d66fbeb235 making occlusion rays always incoherent in pathtracer 2017-09-12 08:50:21 +02:00
Sven Woop af13b7704f adding coherent/incoherent tests for viewer and pathtracer 2017-09-12 08:38:29 +02:00
Sven Woop 649d39f3a8 coherent/incoherent mode can be set from command line for viewer 2017-09-12 08:30:27 +02:00
Sven Woop 9b3362a394 fixed warning 2017-09-12 08:15:40 +02:00
Sven Woop fdb80242af returning in feature_adaptive_eval for out of bounds subpatch ID 2017-09-12 08:14:24 +02:00
Sven Woop fa7d1b4f89 bugfix of potential out of range access in stringstream.h 2017-09-12 08:00:18 +02:00
cbenthin f6cdaeb732 added AVX512VL sorting code to both 4 and 8-wide code paths 2017-09-11 18:27:06 +02:00
cbenthin a9d59ed6c8 Merge remote-tracking branch 'origin/devel' into cbenthin 2017-09-11 17:21:34 +02:00
cbenthin 5633e5233d deactivating all prefetches for large nodes on Xeon but still keep L2 prefetches for KNL 2017-09-11 16:33:21 +02:00
cbenthin 2b681c5f27 removed implicit int->uint conversion in sorting code 2017-09-09 08:01:30 -05:00
cbenthin 8a8f7c78aa sync 2017-09-08 16:54:27 +02:00
Sven Woop 159e440014 updates klocwork server 2017-09-08 07:24:07 +02:00
atafra 04d8b88026 added transpose optimization for SKX 2017-09-07 18:03:21 +03:00
atafra 1f8e43141c removed unused node intersection code 2017-09-07 14:05:24 +03:00
Sven Woop 07c35e2ed2 change 2017-09-07 07:46:12 +02:00
Sven Woop a44f900b20 replaced unsigned -> unsigned int for ISPC 2017-09-07 07:12:28 +02:00
atafra 141aa737c6 minor cleanup 2017-09-07 01:41:55 +03:00
atafra f154b5f160 improved very slow fallback path in filterSOA so it's not slow anymore 2017-09-07 01:39:43 +03:00
atafra 7f82ff96ce fixes and cleanups in RayPacketSOA, RayStreamAOS, and RayStreamAOP 2017-09-07 01:26:26 +03:00
atafra 1112474494 filter cleanups 2017-09-06 13:23:57 +03:00
atafra b486e32e7c implemented coherent code path for filterAOS and filterAOP 2017-09-06 12:42:32 +03:00
87 changed files with 2809 additions and 1749 deletions
+81
View File
@@ -0,0 +1,81 @@
# have to disable proxy servers as otherwise CDash commits fail
before_script:
- export http_proxy=
- export https_proxy=
build-centos6-gcc:
script:
- "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC isa:SSE2 tasking:TBB"
#####################################################################
# WINDOWS
####################################################################
.windows-x64-RelWithDebInfo-V140-AVX2-TBB:
script: "./sripts/test.py platform:x64 build:RelWithDebInfo compiler:V140 isa:AVX2 tasking:TBB intensive:OFF"
tags: [win, v140]
.windows-x64-RelWithDebInfo-V120-AVX2-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:V120 isa:AVX2 tasking:TBB intensive:OFF"
tags: [win, v120]
.windows-x64-RelWithDebInfo-ICC17-AVX2-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC17 isa:AVX2 tasking:TBB intensive:OFF"
tags: [win, icc17]
.windows-x64-RelWithDebInfo-CLANG-AVX2-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:CLANG isa:AVX2 tasking:TBB intensive:OFF"
tags: [win, clang]
#####################################################################
# MACOSX
####################################################################
.macosx-x64-RelWithDebInfo-CLANG-AVX2:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:CLANG isa:AVX2 tasking:TBB intensive:OFF"
tags: [macosx, clang]
.macosx-x64-RelWithDebInfo-ICC16-AVX2:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC16 isa:AVX2 tasking:TBB intensive:OFF"
tags: [macosx, icc16]
#####################################################################
# LINUX
####################################################################
.linux-x64-RelWithDebInfo-CLANG-AVX2-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:CLANG isa:AVX2 tasking:TBB intensive:OFF"
tags: [linux, clang]
.linux-x64-RelWithDebInfo-GCC-AVX2-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:GCC isa:AVX2 tasking:TBB intensive:OFF"
tags: [linux, gcc]
.linux-x64-RelWithDebInfo-ICC17-AVX512KNL-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC17 isa:AVX512KNL tasking:TBB intensive:OFF"
tags: [linux, icc17]
.linux-x64-RelWithDebInfo-ICC17-AVX2-TBB-KLOCKWORK:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC17 isa:AVX2 tasking:TBB klocwork:ON"
tags: [linux, icc17, klocwork]
.linux-knl-x64-RelWithDebInfo-ICC17-AVX512KNL-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC17 isa:AVX512KNL tasking:TBB intensive:OFF"
tags: [linux, knl, icc17]
.linux-knl-x64-RelWithDebInfo-CLANG4-AVX512KNL-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:CLANG4 isa:AVX512KNL tasking:TBB intensive:OFF"
tags: [linux, knl, clang4]
.linux-skx-x64-RelWithDebInfo-ICC17-AVX512SKX-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:ICC17 isa:AVX512SKX tasking:TBB intensive:OFF"
tags: [linux, skx, icc17]
.linux-skx-x64-RelWithDebInfo-CLANG4-AVX512SKX-TBB:
script: "./scripts/test.py platform:x64 build:RelWithDebInfo compiler:CLANG4 isa:AVX512SKX tasking:TBB intensive:OFF"
tags: [linux, skx, clang4]
+24 -2
View File
@@ -1,6 +1,28 @@
Version History
---------------
### New Features in Embree 2.17.0
- Improved packet ray tracing performance for coherent rays by 10-60%
(requires RTC_INTERSECT_COHERENT flag).
- Improved ray tracing performance for incoherent rays on
AVX-512 architectures by 5%.
- Improved ray tracing performance for streams of incoherent rays
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
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
change. If you want stack-protectors disabled please turn off
EMBREE_STACK_PROTECTOR in cmake and build the binaries yourself.
- When enabling ISAs individually, the 8-wide BVH was previously only
available when the AVX ISA was also selected. This issue is now
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.
### New Features in Embree 2.16.5
- Bugfix in the robust triangle intersector that rarely caused NaNs.
- Fixed bug in hybrid traversal kernel when BVH leaf was entered with no
@@ -84,7 +106,7 @@ Version History
- Removed support for Visual Studio 2012.
- Precompiled binaries now require a CPU supporting at least the
SSE4.2 ISA.
- We no longer provide precompiled binaries for 32 bit on Windows.
- We no longer provide precompiled binaries for 32-bit on Windows.
- Under Windows one now has to use the platform toolset option in
CMake to switch to Clang or the Intel® Compiler.
- Fixed a bug for subdivision meshes when using the incoherent scene
@@ -394,7 +416,7 @@ Version History
- Improved mixed AABB/OBB-BVH for hair geometry (Xeon Phi)
- Reduced amount of pre-allocated memory for BVH builders (Xeon Phi)
- New 64 bit Morton code-based BVH builder (Xeon Phi)
- New 64-bit Morton code-based BVH builder (Xeon Phi)
- (Enhanced) Morton code-based BVH builders use now tree rotations to
improve BVH quality (Xeon Phi)
- Bug fixes (Xeon and Xeon Phi)
+2 -1
View File
@@ -17,7 +17,7 @@
SET(EMBREE_VERSION_MAJOR 2)
SET(EMBREE_VERSION_MINOR 17)
SET(EMBREE_VERSION_PATCH 0)
SET(EMBREE_VERSION_NOTE "-alpha.0")
SET(EMBREE_VERSION_NOTE "")
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)
@@ -26,6 +26,7 @@ PROJECT(embree${EMBREE_VERSION_MAJOR})
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
# find git version
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
FIND_PACKAGE(Git)
+54 -49
View File
@@ -1,4 +1,4 @@
% Embree: High Performance Ray Tracing Kernels 2.16.5
% Embree: High Performance Ray Tracing Kernels 2.17.0
% Intel Corporation
Embree Overview
@@ -46,8 +46,8 @@ Renderer]).
Supported Platforms
-------------------
Embree supports Windows (32 bit and 64 bit), Linux (64 bit) and Mac
OS X (64 bit). The code compiles with the Intel Compiler, GCC, Clang
Embree supports Windows (32-bit and 64-bit), Linux (64-bit) and Mac
OS X (64-bit). The code compiles with the Intel Compiler, GCC, Clang
and the Microsoft Compiler.
Using the Intel Compiler improves performance by approximately
@@ -94,9 +94,9 @@ Windows Installer
You can install the Embree library using the Windows installer
application
[embree-2.16.5-x64.exe](https://github.com/embree/embree/releases/download/v2.16.5/embree-2.16.5.x64.exe). This
will install the 64 bit Embree version by default in `Program
Files\Intel\Embree v2.16.5 x64`.
[embree-2.17.0-x64.exe](https://github.com/embree/embree/releases/download/v2.17.0/embree-2.17.0.x64.exe). This
will install the 64-bit Embree version by default in `Program
Files\Intel\Embree v2.17.0 x64`.
You have to set the path to the `lib` folder manually to your `PATH`
environment variable for applications to find Embree. To compile
@@ -107,13 +107,13 @@ Embree installation.
To uninstall Embree again open `Programs and Features` by clicking the
`Start button`, clicking `Control Panel`, clicking `Programs`, and
then clicking `Programs and Features`. Select `Embree
2.16.5` and uninstall it.
2.17.0` and uninstall it.
Windows ZIP File
-----------------
Embree is also delivered as a ZIP file
[embree-2.16.5.x64.windows.zip](https://github.com/embree/embree/releases/download/v2.16.5/embree-2.16.5.x64.windows.zip). After
[embree-2.17.0.x64.windows.zip](https://github.com/embree/embree/releases/download/v2.17.0/embree-2.17.0.x64.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. To compile applications with Embree you also have to set the
@@ -127,18 +127,18 @@ Linux RPMs
----------
Uncompress the 'tar.gz' file
[embree-2.16.5.x86_64.rpm.tar.gz](https://github.com/embree/embree/releases/download/v2.16.5/embree-2.16.5.x86_64.rpm.tar.gz)
[embree-2.17.0.x86_64.rpm.tar.gz](https://github.com/embree/embree/releases/download/v2.17.0/embree-2.17.0.x86_64.rpm.tar.gz)
to
obtain the individual RPM files:
tar xzf embree-2.16.5.x86_64.rpm.tar.gz
tar xzf embree-2.17.0.x86_64.rpm.tar.gz
To install the Embree using the RPM packages on your Linux system type
the following:
sudo rpm --install embree-lib-2.16.5-1.x86_64.rpm
sudo rpm --install embree-devel-2.16.5-1.noarch.rpm
sudo rpm --install embree-examples-2.16.5-1.x86_64.rpm
sudo rpm --install embree-lib-2.17.0-1.x86_64.rpm
sudo rpm --install embree-devel-2.17.0-1.noarch.rpm
sudo rpm --install embree-examples-2.17.0-1.x86_64.rpm
You also have to install the Intel® Threading Building Blocks (TBB)
using `yum`:
@@ -168,21 +168,21 @@ the tutorials to start them.
To uninstall Embree again just execute the following:
sudo rpm --erase embree-lib-2.16.5-1.x86_64
sudo rpm --erase embree-devel-2.16.5-1.noarch
sudo rpm --erase embree-examples-2.16.5-1.x86_64
sudo rpm --erase embree-lib-2.17.0-1.x86_64
sudo rpm --erase embree-devel-2.17.0-1.noarch
sudo rpm --erase embree-examples-2.17.0-1.x86_64
Linux tar.gz files
------------------
The Linux version of Embree is also delivered as a tar.gz file
[embree-2.16.5.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v2.16.5/embree-2.16.5.x86_64.linux.tar.gz). Unpack
[embree-2.17.0.x86_64.linux.tar.gz](https://github.com/embree/embree/releases/download/v2.17.0/embree-2.17.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 setup the environment properly:
tar xzf embree-2.16.5.x64.linux.tar.gz
source embree-2.16.5.x64.linux/embree-vars.sh
tar xzf embree-2.17.0.x64.linux.tar.gz
source embree-2.17.0.x64.linux/embree-vars.sh
If you want to ship Embree with your application best use the Embree
version provided through the tar.gz file.
@@ -195,7 +195,7 @@ Mac OS X PKG Installer
To install the Embree library on your Mac OS X system use the
provided package installer inside
[embree-2.16.5.x86_64.dmg](https://github.com/embree/embree/releases/download/v2.16.5/embree-2.16.5.x86_64.dmg). This
[embree-2.17.0.x86_64.dmg](https://github.com/embree/embree/releases/download/v2.17.0/embree-2.17.0.x86_64.dmg). This
will install Embree by default into `/opt/local/lib` and
`/opt/local/include` directories. The Embree tutorials are installed
into the `/Applications/Embree2` folder.
@@ -217,13 +217,13 @@ Mac OS X tar.gz file
---------------------
The Mac OS X version of Embree is also delivered as a tar.gz file
[embree-2.16.5.x86_64.macosx.tar.gz](https://github.com/embree/embree/releases/download/v2.16.5/embree-2.16.5.x86_64.macosx.tar.gz). Unpack
[embree-2.17.0.x86_64.macosx.tar.gz](https://github.com/embree/embree/releases/download/v2.17.0/embree-2.17.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 setup the environment properly:
tar xzf embree-2.16.5.x64.macosx.tar.gz
source embree-2.16.5.x64.macosx/embree-vars.sh
tar xzf embree-2.17.0.x64.macosx.tar.gz
source embree-2.17.0.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
@@ -398,8 +398,8 @@ for Visual Studio.
Run `cmake-gui`, browse to the Embree sources, set the build directory
and click Configure. Now you can select the Generator, e.g. "Visual
Studio 12 2013" for a 32 bit build or "Visual Studio 12 2013 Win64"
for a 64 bit build.
Studio 12 2013" for a 32-bit build or "Visual Studio 12 2013 Win64"
for a 64-bit build.
To use a different compile than the Microsoft Visual C++ compiler, you
additionally need to specify the proper compiler toolset through the
@@ -481,6 +481,9 @@ parameters that can be configured in CMake:
and debug symbols
(RelWithDebInfo).
EMBREE_STACK_PROTECTOR Enables protection of return OFF
address from buffer overwrites.
EMBREE_ISPC_SUPPORT Enables ISPC support of Embree. ON
EMBREE_STATIC_LIB Builds Embree as a static OFF
@@ -581,10 +584,6 @@ different ISAs selected (e.g. embree2.a, embree2_sse42.a,
embree2_avx.a, embree2_avx2.a, embree2_avx512knl.a,
embree2_avx512skx.a). You have to link these libraries in increasing
ISA order (the order shown in the example).
When selecting ISAs individually, the AVX ISA always has to get
enabled when a larger ISA than AVX is enabled, otherwise the code will
not compile.
Embree API
==========
@@ -717,13 +716,18 @@ device.
typedef void (*RTCErrorFunc2)(void* userPtr, const RTCError, const char* str);
void rtcDeviceSetErrorFunction2(RTCDevice, RTCErrorFunc2, void* userPtr);
When invoked, the registred callback function gets passed a user
When invoked, the registered callback function gets passed a user
defined pointer `userPtr`, the error code `code`, as well as some
string `str` that describes the error further. Passing `NULL` as
function pointer to `rtcDeviceSetErrorFunction2` disables the set
callback function again. The previously described error flags are also
set if an error callback function is present.
Arrays and buffers passed to Embree in most cases have strict alignment and
padding requirements to facilitate efficient SIMD processing. The required
alignment and padding vary between 16 and 64 bytes, depending on the actual
function and data type.
Scene
-----
@@ -963,7 +967,7 @@ motion blur:
The triangle indices can be set by mapping and writing to the index
buffer (`RTC_INDEX_BUFFER`) and the triangle vertices can be set by
mapping and writing into the vertex buffer (`RTC_VERTEX_BUFFER`). The
index buffer contains an array of three 32 bit indices, while the
index buffer contains an array of three 32-bit indices, while the
vertex buffer contains an array of three float values. The vertex
buffer can be at most 16GB large. When the vertex buffer is managed
internally the stride between vertices is 16 bytes. For multi segment
@@ -1016,7 +1020,7 @@ without motion blur:
The quad indices can be set by mapping and writing to the index buffer
(`RTC_INDEX_BUFFER`) and the quad vertices can be set by mapping and
writing into the vertex buffer (`RTC_VERTEX_BUFFER`). The index buffer
contains an array of four 32 bit indices, while the vertex buffer
contains an array of four 32-bit indices, while the vertex buffer
contains an array of three float values. The vertex buffer can be at
most 16GB large. When the vertex buffer is managed internally the
stride between vertices is 16 bytes. For multi segment motion blur,
@@ -1075,7 +1079,7 @@ The number of faces (`numFaces`), edges/indices (`numEdges`), vertices
The following buffers have to get setup by the application: the face
buffer (`RTC_FACE_BUFFER`) contains the number edges/indices (3 to 15) of
each of the `numFaces` faces, the index buffer (`RTC_INDEX_BUFFER`)
contains multiple (3 to 15) 32 bit vertex indices for each face and
contains multiple (3 to 15) 32-bit vertex indices for each face and
`numEdges` indices in total, the vertex buffer (`RTC_VERTEX_BUFFER`)
stores `numVertices` vertices as single precision `x`, `y`, `z` floating
point coordinates aligned to 16 bytes. The value of the 4th float used
@@ -1088,7 +1092,7 @@ geometry topology (topology 0) thus use `RTC_INDEX_BUFFER0`. Data
interpolation may use different topologies as described later.
Optionally, the application can setup the hole buffer (`RTC_HOLE_BUFFER`)
with `numHoles` many 32 bit indices of faces that should be considered
with `numHoles` many 32-bit indices of faces that should be considered
non-existing in all topologies.
Optionally, the application can fill the level buffer
@@ -1109,7 +1113,7 @@ uniform tessellation rate.
Optionally, the application can fill the sparse edge crease buffers to
make some edges appear sharper. The edge crease index buffer
(`RTC_EDGE_CREASE_INDEX_BUFFER`) contains `numEdgeCreases` many pairs
of 32 bit vertex indices that specify unoriented edges in the
of 32-bit vertex indices that specify unoriented edges in the
geometry topology. The edge crease weight buffer
(`RTC_EDGE_CREASE_WEIGHT_BUFFER`) stores for each of theses crease
edges a positive floating point weight. The larger this weight, the
@@ -1125,7 +1129,7 @@ topology, but copied to all other topologies automatically.
Optionally, the application can fill the sparse vertex crease buffers
to make some vertices appear sharper. The vertex crease index buffer
(`RTC_VERTEX_CREASE_INDEX_BUFFER`), contains `numVertexCreases` many
32 bit vertex indices to specify a set of vertices from the geometry
32-bit vertex indices to specify a set of vertices from the geometry
topology. The vertex crease weight buffer
(`RTC_VERTEX_CREASE_WEIGHT_BUFFER`) specifies for each of these
vertices a positive floating point weight. The larger this weight, the
@@ -1284,7 +1288,7 @@ writing into the vertex buffer (`RTC_VERTEX_BUFFER`). In case of
motion blur, the vertex buffers (`RTC_VERTEX_BUFFER0+t`) have to get
filled for each time step `t`.
The index buffer contains an array of 32 bit indices pointing to the
The index buffer contains an array of 32-bit indices pointing to the
ID of the first of two vertices, while the vertex buffer
stores all control points in the form of a single precision position
and radius stored in `x`, `y`, `z`, `r` order in memory. The
@@ -1339,7 +1343,7 @@ mapping and writing into the vertex buffer (`RTC_VERTEX_BUFFER`). In
case of motion blur, the vertex buffers `RTC_VERTEX_BUFFER0+t` have to
get filled for each time step.
The index buffer contains an array of 32 bit indices pointing to the
The index buffer contains an array of 32-bit indices pointing to the
ID of the first of four control vertices, while the vertex buffer
stores all control points in the form of a single precision position
and radius stored in `x`, `y`, `z`, `r` order in memory. The hair
@@ -1404,7 +1408,7 @@ mapping and writing into the vertex buffer (`RTC_VERTEX_BUFFER`). In
case of motion blur, the vertex buffers `RTC_VERTEX_BUFFER0+t` have to
get filled for each time step.
The index buffer contains an array of 32 bit indices pointing to the
The index buffer contains an array of 32-bit indices pointing to the
ID of the first of four control vertices, while the vertex buffer
stores all control points in the form of a single precision position
and radius stored in `x`, `y`, `z`, `r` order in memory. The curve
@@ -1767,7 +1771,7 @@ operate on ray packets of size 8, and the `rtcIntersect16` and
`rtcOccluded16` functions operate on ray packets of size 16.
For the ray packet mode with packet size of 4, 8, or 16, the user has
to provide a pointer to 4, 8, or 16 of 32 bit integers that act as a
to provide a pointer to 4, 8, or 16 of 32-bit integers that act as a
ray activity mask (`valid` argument). If one of these integers is set
to `0x00000000` the corresponding ray is considered inactive and if
the integer is set to `0xFFFFFFFF`, the ray is considered active. Rays
@@ -1863,10 +1867,11 @@ streams of rays:
The `rtcIntersectNM` and `rtcOccludedNM` ray stream functions operate
on an array of `M` ray packets of packet size `N`. The offset in bytes
between consecutive ray packets can be specified by the `stride`
parameter. Data alignment requirements for ray streams is 16
bytes. The packet size `N` has to be larger than 0 and the stream size
`M` can be an arbitrary positive integer including 0. Tracing for
example a ray stream consisting of four 8-wide SOA ray packets just
parameter. The required data alignment and padding for ray streams is 16
bytes, but for maximum performance, streams should be aligned to the native
SIMD size (e.g. 64 bytes for AVX-512). The packet size `N` has to be larger than
0 and the stream size `M` can be an arbitrary positive integer including 0.
Tracing for example a ray stream consisting of four 8-wide SOA ray packets just
requires to set the parameters `N` to 8, `M` to 4 and the `stride` to
`sizeof(RTCRay8)`. A ray in a ray stream is considered inactive during
traversal/intersection if its `tnear` value is larger than its `tfar`
@@ -1878,7 +1883,7 @@ just a shortcut for single ray streams with a packet size of
`rtcIntersect1M` and `rtcOccluded1M` while taking a stream of pointers
to single rays as input. The `rtcIntersectNp` and `rtcOccludedNp`
functions do not require the individual components of the SOA ray
packets to be stored sequentially in memory, but at different adresses
packets to be stored sequentially in memory, but at different addresses
as specified in the `RTCRayNp` structure.
The intersection context passed to the stream version of the ray query
@@ -1977,8 +1982,8 @@ The second order derivatives are stored at the `ddPdudu`, `ddPdvdv`,
and `ddPdudv` memory locations. One can avoid storing second order
derivatives by setting these three pointers to NULL.
The `RTC_INTERPOLATE` algorithm flag of a scene has to be enabled to
perform interpolations.
All output arrays must be padded to 16 bytes. The `RTC_INTERPOLATE`
algorithm flag of a scene has to be enabled to perform interpolations.
It is explicitly allowed to call this function on disabled
geometries. This makes it possible to use a separate subdivision mesh
@@ -2042,7 +2047,7 @@ the different elements of the shared buffer and the `size` parameter
specified the number of elements stored inside the buffer. This
support for offset and stride allows the application quite some
freedom in the data layout of these buffers, however, some
restrictions apply. Index buffers always store 32 bit indices and
restrictions apply. Index buffers always store 32-bit indices and
vertex buffers always store single precision floating point data. The
start address `ptr+offset` and `stride` always have to be aligned to 4
bytes, otherwise the `rtcSetBuffer2` function will fail. The `size`
@@ -2112,7 +2117,7 @@ while modifying the scene with other threads.
Geometry Mask
-------------
A 32 bit geometry mask can be assigned to triangle meshes and hair
A 32-bit geometry mask can be assigned to triangle meshes and hair
geometries using the `rtcSetMask` call.
rtcSetMask(scene, geomID, mask);
+1 -2
View File
@@ -66,7 +66,7 @@ ELSE ()
FIND_LIBRARY(TBB_LIBRARY tbb)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc)
ELSEIF (EXISTS ${EMBREE_TBB_ROOT}/src)
ELSEIF (EXISTS ${EMBREE_TBB_ROOT}/cmake/TBBBuild.cmake)
OPTION(EMBREE_TBB_STATIC_LIB "Build TBB as a static library (building TBB as a static library is NOT recommended)")
if (EMBREE_TBB_STATIC_LIB)
include(${EMBREE_TBB_ROOT}/cmake/TBBBuild.cmake)
@@ -117,7 +117,6 @@ MARK_AS_ADVANCED(TBB_LIBRARY_MALLOC)
IF (WIN32)
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
INSTALL(PROGRAMS ${TBB_LIBDIR}/tbb.lib ${TBB_LIBDIR}/tbbmalloc.lib DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
ELSEIF (EMBREE_ZIP_MODE)
IF (APPLE)
+10
View File
@@ -36,6 +36,11 @@ IF (WIN32)
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_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
@@ -88,6 +93,11 @@ ELSE()
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()
SET(CMAKE_CXX_FLAGS_DEBUG "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
+5
View File
@@ -41,6 +41,11 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable
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()
SET(CMAKE_CXX_FLAGS_DEBUG "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
+17 -2
View File
@@ -33,6 +33,11 @@ IF (WIN32)
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(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qdiag-disable:11074 ") # remark #11074: Inlining inhibited by limit max-size
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qdiag-disable:11075 ") # remark #11075: To get full report use -Qopt-report:4 -Qopt-report-phase ipo
@@ -105,6 +110,12 @@ ELSE()
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(NOT CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel") # links intel runtime statically
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-intel-extensions") # disables some intel extensions which cause symbols to be exported
@@ -122,8 +133,12 @@ ELSE()
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -restrict") # enable restrict keyword
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -no-inline-max-total-size") # no size limit when performing inlining
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -no-inline-max-per-compile") # no maximal number of inlinings per compilation unit
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -inline-factor=200") # increase default inline factors limits by 2x
IF (NOT APPLE)
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -inline-factor=200") # increase default inline factors limits by 2x
ELSE(NOT APPLE)
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -inline-factor=150")
ENDIF()
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enables assertions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configures TBB in debug mode
+5
View File
@@ -28,6 +28,11 @@ IF (EMBREE_STACK_PROTECTOR)
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(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} ${FLAGS_SSE2}")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
+5 -21
View File
@@ -125,7 +125,7 @@ INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION ${
# CPack specific stuff
##############################################################
SET(CPACK_PACKAGE_NAME "Embree")
SET(CPACK_PACKAGE_NAME "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_RELOCATABLE TRUE)
@@ -161,33 +161,18 @@ IF(WIN32)
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(ARCH x64)
SET(PROGRAMFILES "\$PROGRAMFILES64")
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} x64")
ELSE()
SET(ARCH win32)
SET(PROGRAMFILES "\$PROGRAMFILES")
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} Win32")
ENDIF()
# NSIS specific settings
IF (NOT EMBREE_ZIP_MODE)
SET(CPACK_GENERATOR NSIS)
SET(CPACK_GENERATOR WIX)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}")
SET(CPACK_COMPONENTS_ALL lib devel examples)
SET(CPACK_NSIS_INSTALL_ROOT "${PROGRAMFILES}\\\\Intel")
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "Embree v${EMBREE_VERSION} ${ARCH}")
SET(CPACK_NSIS_DISPLAY_NAME "Embree v${EMBREE_VERSION} ${ARCH}")
SET(CPACK_NSIS_PACKAGE_NAME "Embree v${EMBREE_VERSION} ${ARCH}")
SET(CPACK_NSIS_URL_INFO_ABOUT http://embree.github.io/)
#SET(CPACK_NSIS_HELP_LINK http://embree.github.io/downloads.html#windows)
SET(CPACK_NSIS_MUI_ICON ${PROJECT_SOURCE_DIR}/scripts/install_windows/icon32.ico)
SET(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT})
#SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS} "\n CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\"")
#SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS} "\n CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\documentation\\\"")
#SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS} "\n CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\tutorials\\\" \n")
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\documentation\\\"")
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\tutorials\\\"")
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\"\n")
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "Intel\\\\Embree v${EMBREE_VERSION} ${ARCH}")
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
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CPACK_PACKAGE_FILE_NAME}.exe ${CMAKE_BUILD_TYPE})
ENDIF()
@@ -230,7 +215,6 @@ ELSEIF(APPLE)
# Linux specific settings
ELSE()
IF (NOT EMBREE_ZIP_MODE)
SET(CPACK_GENERATOR RPM)
+1 -1
View File
@@ -30,7 +30,7 @@ namespace embree
ParseLocation location() { return cin->loc(); }
std::string next();
private:
__forceinline bool isSeparator(int c) const { return c <= 256 && isSepMap[c]; }
__forceinline bool isSeparator(int c) const { return c<256 && isSepMap[c]; }
private:
Ref<Stream<int> > cin; /*! source character stream */
bool isSepMap[256]; /*! map for fast classification of separators */
+1 -1
View File
@@ -49,7 +49,7 @@ namespace embree
__forceinline vboolf(bool a, bool b, bool c, bool d)
: v(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline vboolf(int mask) { assert(mask >= 0 && mask < 16); v = _mm_lookupmask_ps[mask]; }
__forceinline vboolf(unsigned int mask) { assert(mask >= 0 && mask < 16); v = _mm_lookupmask_ps[mask]; }
__forceinline vboolf(unsigned int mask) { assert(mask < 16); v = _mm_lookupmask_ps[mask]; }
/* return int32 mask */
__forceinline __m128i mask32() const {
+15
View File
@@ -428,6 +428,9 @@ namespace embree
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline vfloat16 unpacklo(const vfloat16& a, const vfloat16& b) { return _mm512_unpacklo_ps(a, b); }
__forceinline vfloat16 unpackhi(const vfloat16& a, const vfloat16& b) { return _mm512_unpackhi_ps(a, b); }
template<int i>
__forceinline vfloat16 shuffle(const vfloat16& v) {
return _mm512_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
@@ -530,6 +533,7 @@ 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);
@@ -539,6 +543,17 @@ namespace embree
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);
vfloat16 c1c3_d1d3 = unpackhi(r1, r3);
c0 = unpacklo(a0a2_b0b2, a1a3_b1b3);
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,
+16
View File
@@ -69,6 +69,14 @@ namespace embree
static __forceinline void storeu(void* ptr, const vfloat4& v) { _mm_storeu_ps((float*)ptr,v); }
#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); }
@@ -547,6 +555,14 @@ namespace embree
#endif
#if defined(__AVX512VL__)
template<int i>
__forceinline vfloat4 align_shift_right(const vfloat4& a, const vfloat4& b) {
return _mm_castsi128_ps(_mm_alignr_epi32(_mm_castps_si128(a), _mm_castps_si128(b), i));
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Sorting Network
////////////////////////////////////////////////////////////////////////////////
+8
View File
@@ -101,6 +101,14 @@ namespace embree
static __forceinline void storeu(void* ptr, const vfloat8& v) { return _mm256_storeu_ps((float*)ptr,v); }
#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); }
+20
View File
@@ -77,6 +77,14 @@ namespace embree
static __forceinline void storeu(void* ptr, const vint4& v) { _mm_storeu_si128((__m128i*)ptr,v); }
#if defined(__AVX512VL__)
static __forceinline vint4 compact(const vboolf4& mask, vint4 &v) {
return _mm_mask_compress_epi32(v, mask, v);
}
static __forceinline vint4 compact(const vboolf4& mask, vint4 &a, const vint4& b) {
return _mm_mask_compress_epi32(a, mask, b);
}
static __forceinline vint4 load (const vboolf4& mask, const void* ptr) { return _mm_mask_load_epi32 (_mm_setzero_si128(),mask,ptr); }
static __forceinline vint4 loadu(const vboolf4& mask, const void* ptr) { return _mm_mask_loadu_epi32(_mm_setzero_si128(),mask,ptr); }
@@ -400,6 +408,18 @@ namespace embree
__forceinline int toScalar(const vint4& v) { return _mm_cvtsi128_si32(v); }
#if defined(__AVX512VL__)
__forceinline vint4 permute(const vint4 &a, const vint4 &index) {
return _mm_castps_si128(_mm_permutevar_ps(_mm_castsi128_ps(a),index));
}
template<int i>
__forceinline vint4 align_shift_right(const vint4& a, const vint4& b) {
return _mm_alignr_epi32(a, b, i);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
+13 -1
View File
@@ -89,6 +89,14 @@ namespace embree
static __forceinline void storeu(void* ptr, const vint8& v) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(v)); }
#if defined(__AVX512VL__)
static __forceinline vint8 compact(const vboolf8& mask, vint8 &v) {
return _mm256_mask_compress_epi32(v, mask, v);
}
static __forceinline vint8 compact(const vboolf8& mask, vint8 &a, const vint8& b) {
return _mm256_mask_compress_epi32(a, mask, b);
}
static __forceinline vint8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_epi32 (_mm256_setzero_si256(),mask,ptr); }
static __forceinline vint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_epi32(_mm256_setzero_si256(),mask,ptr); }
@@ -363,7 +371,11 @@ namespace embree
template<int i>
__forceinline vint8 align_shift_right(const vint8& a, const vint8& b) {
return _mm256_alignr_epi8(a, b, i);
#if defined(__AVX512VL__)
return _mm256_alignr_epi32(a, b, i);
#else
return _mm256_alignr_epi8(a, b, 4*i);
#endif
}
////////////////////////////////////////////////////////////////////////////////
+15 -6
View File
@@ -50,7 +50,7 @@ namespace embree
}
/*! run this task */
__dllexport void TaskScheduler::Task::run (Thread& thread) // FIXME: avoid as many __dllexports as possible
void TaskScheduler::Task::run_internal (Thread& thread) // FIXME: avoid as many __dllexports as possible
{
/* try to run if not already stolen */
if (try_switch_state(INITIALIZED,DONE))
@@ -71,14 +71,19 @@ namespace embree
/* steal until all dependencies have completed */
steal_loop(thread,
[&] () { return dependencies>0; },
[&] () { while (thread.tasks.execute_local(thread,this)); });
[&] () { while (thread.tasks.execute_local_internal(thread,this)); });
/* now signal our parent task that we are finished */
if (parent)
parent->add_dependencies(-1);
}
__dllexport bool TaskScheduler::TaskQueue::execute_local(Thread& thread, Task* parent)
/*! run this task */
__dllexport void TaskScheduler::Task::run (Thread& thread) {
run_internal(thread);
}
bool TaskScheduler::TaskQueue::execute_local_internal(Thread& thread, Task* parent)
{
/* stop if we run out of local tasks or reach the waiting task */
if (right == 0 || &tasks[right-1] == parent)
@@ -86,7 +91,7 @@ namespace embree
/* execute task */
size_t oldRight = right;
tasks[right-1].run(thread);
tasks[right-1].run_internal(thread);
if (right != oldRight) {
THROW_RUNTIME_ERROR("you have to wait for spawned subtasks");
}
@@ -102,6 +107,10 @@ namespace embree
return right != 0;
}
__dllexport bool TaskScheduler::TaskQueue::execute_local(Thread& thread, Task* parent) {
return execute_local_internal(thread,parent);
}
bool TaskScheduler::TaskQueue::steal(Thread& thread)
{
size_t l = left;
@@ -316,7 +325,7 @@ namespace embree
{
Thread* thread = TaskScheduler::thread();
if (thread == nullptr) return true;
while (thread->tasks.execute_local(*thread,thread->task)) {};
while (thread->tasks.execute_local_internal(*thread,thread->task)) {};
return thread->scheduler->cancellingException == nullptr;
}
@@ -335,7 +344,7 @@ namespace embree
[&] () { return anyTasksRunning > 0; },
[&] () {
anyTasksRunning++;
while (thread.tasks.execute_local(thread,nullptr));
while (thread.tasks.execute_local_internal(thread,nullptr));
anyTasksRunning--;
});
}
+3
View File
@@ -109,6 +109,8 @@ namespace embree
/*! run this task */
__dllexport void run(Thread& thread);
void run_internal(Thread& thread);
public:
std::atomic<int> state; //!< state this task is in
std::atomic<int> dependencies; //!< dependencies to wait for
@@ -149,6 +151,7 @@ namespace embree
}
__dllexport bool execute_local(Thread& thread, Task* parent);
bool execute_local_internal(Thread& thread, Task* parent);
bool steal(Thread& thread);
size_t getTaskSizeAtLeft();
+9 -9
View File
@@ -165,15 +165,15 @@ RTCORE_DEPRECATED uniform unsigned int rtcNewInstance (RTCScene target,
the provided scene. If any geometry is hit, the instance ID (instID)
member of the ray will get set to the geometry ID of the
instance. */
uniform unsigned rtcNewInstance2 (RTCScene target, //!< the scene the instance belongs to
RTCScene source, //!< the scene to instantiate
uniform size_t numTimeSteps = 1 //!< number of timesteps, one matrix per timestep
uniform unsigned int rtcNewInstance2 (RTCScene target, //!< the scene the instance belongs to
RTCScene source, //!< the scene to instantiate
uniform size_t numTimeSteps = 1 //!< number of timesteps, one matrix per timestep
);
uniform unsigned rtcNewInstance3 (RTCScene target, //!< the scene the instance belongs to
RTCScene source, //!< the scene to instantiate
uniform size_t numTimeSteps = 1, //!< number of timesteps, one matrix per timestep
uniform unsigned int geomID = -1 //!< optional geometry ID to assign
uniform unsigned int rtcNewInstance3 (RTCScene target, //!< the scene the instance belongs to
RTCScene source, //!< the scene to instantiate
uniform size_t numTimeSteps = 1, //!< number of timesteps, one matrix per timestep
uniform unsigned int geomID = -1 //!< optional geometry ID to assign
);
/*! \brief Creates a new geometry instance.
@@ -564,7 +564,7 @@ uniform unsigned int rtcNewLineSegments2(RTCScene scene, //!<
/*! Sets a uniform tessellation rate for subdiv meshes and hair
* geometry. For subdivision meshes the RTC_LEVEL_BUFFER can also be used
* optionally to set a different tessellation rate per edge.*/
void rtcSetTessellationRate (RTCScene scene, uniform unsigned geomID, uniform float tessellationRate);
void rtcSetTessellationRate (RTCScene scene, uniform unsigned int geomID, uniform float tessellationRate);
/*! \brief Sets 32 bit ray mask. */
void rtcSetMask (RTCScene scene, uniform unsigned int geomID, uniform int mask);
@@ -578,7 +578,7 @@ RTCORE_DEPRECATED void rtcSetBoundaryMode(RTCScene scene, uniform unsigned int g
void rtcSetSubdivisionMode(RTCScene scene, uniform unsigned int geomID, uniform unsigned int topologyID, uniform RTCSubdivisionMode mode);
/*! \brief Binds a user vertex buffer to some index buffer topology. */
void rtcSetIndexBuffer(RTCScene scene, uniform unsigned geomID, uniform RTCBufferType vertexBuffer, uniform RTCBufferType indexBuffer);
void rtcSetIndexBuffer(RTCScene scene, uniform unsigned int geomID, uniform RTCBufferType vertexBuffer, uniform RTCBufferType indexBuffer);
/*! \brief Maps specified buffer. This function can be used to set index and
* vertex buffers of geometries. */
+4 -4
View File
@@ -153,12 +153,12 @@ void rtcSetIntersectFunction (RTCScene scene, uniform unsigned int geomID, unifo
/*! Set intersect function for stream of rays. The rtcIntersectN function
* will call the passed function for intersecting the user
* geometry. */
void rtcSetIntersectFunction1Mp (RTCScene scene, uniform unsigned geomID, uniform RTCIntersectFunc1Mp intersect);
void rtcSetIntersectFunction1Mp (RTCScene scene, uniform unsigned int geomID, uniform RTCIntersectFunc1Mp intersect);
/*! Set intersect function for ray packets of size N. The rtcIntersectN function
* will call the passed function for intersecting the user
* geometry. */
void rtcSetIntersectFunctionN (RTCScene scene, uniform unsigned geomID, uniform RTCIntersectFuncN intersect);
void rtcSetIntersectFunctionN (RTCScene scene, uniform unsigned int geomID, uniform RTCIntersectFuncN intersect);
/*! Set occlusion function for uniform rays. The rtcOccluded1 function
* will call the passed function for intersecting the user
@@ -173,12 +173,12 @@ void rtcSetOccludedFunction (RTCScene scene, uniform unsigned int geomID, unifor
/*! Set occlusion function for a stream of single rays. The rtcOccludedN function
* will call the passed function for intersecting the user
* geometry. */
void rtcSetOccludedFunction1Mp (RTCScene scene, uniform unsigned geomID, uniform RTCOccludedFunc1Mp occluded);
void rtcSetOccludedFunction1Mp (RTCScene scene, uniform unsigned int geomID, uniform RTCOccludedFunc1Mp occluded);
/*! Set occlusion function for a ray packets of size N. The rtcOccludedN function
* will call the passed function for intersecting the user
* geometry. */
void rtcSetOccludedFunctionN (RTCScene scene, uniform unsigned geomID, uniform RTCOccludedFuncN occluded);
void rtcSetOccludedFunctionN (RTCScene scene, uniform unsigned int geomID, uniform RTCOccludedFuncN occluded);
/*! @} */
+1 -1
View File
@@ -18,4 +18,4 @@
#define RTCORE_VERSION_MINOR 17
#define RTCORE_VERSION_PATCH 0
#define RTCORE_VERSION 21700
#define RTCORE_VERSION_STRING "2.17.0-alpha.0"
#define RTCORE_VERSION_STRING "2.17.0"
+14
View File
@@ -14,6 +14,14 @@
## limitations under the License. ##
## ======================================================================== ##
MACRO(DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS)
FOREACH(src ${ARGN})
IF (src MATCHES ".*intersector.*")
DISABLE_STACK_PROTECTOR_FOR_FILE(${src})
ENDIF()
ENDFOREACH()
ENDMACRO()
SOURCE_GROUP("Source Files\\bvh4" "/bvh4/" )
SOURCE_GROUP("Source Files\\bvh8" "/bvh8/" )
SOURCE_GROUP("Source Files\\geometry" "/geometry/" )
@@ -208,6 +216,7 @@ MACRO (CheckGlobals library)
ENDIF()
ENDMACRO()
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES})
ADD_ISPC_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES} $<TARGET_OBJECTS:algorithms>)
SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}")
SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA")
@@ -225,6 +234,7 @@ ENDIF()
#ENDIF ()
IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42)
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_SSE42})
ADD_LIBRARY(embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42})
SET_TARGET_PROPERTIES(embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}")
SET_PROPERTY(TARGET embree_sse42 PROPERTY FOLDER kernels)
@@ -233,6 +243,7 @@ IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42)
ENDIF ()
IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX)
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX})
ADD_LIBRARY(embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX})
SET_TARGET_PROPERTIES(embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}")
SET_PROPERTY(TARGET embree_avx PROPERTY FOLDER kernels)
@@ -241,6 +252,7 @@ IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX)
ENDIF()
IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2)
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2})
ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2})
SET_TARGET_PROPERTIES(embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}")
SET_PROPERTY(TARGET embree_avx2 PROPERTY FOLDER kernels)
@@ -249,6 +261,7 @@ IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2)
ENDIF()
IF (EMBREE_ISA_AVX512KNL AND EMBREE_LIBRARY_FILES_AVX512KNL)
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512KNL})
ADD_LIBRARY(embree_avx512knl STATIC ${EMBREE_LIBRARY_FILES_AVX512KNL})
SET_TARGET_PROPERTIES(embree_avx512knl PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512KNL}")
SET_PROPERTY(TARGET embree_avx512knl PROPERTY FOLDER kernels)
@@ -257,6 +270,7 @@ IF (EMBREE_ISA_AVX512KNL AND EMBREE_LIBRARY_FILES_AVX512KNL)
ENDIF()
IF (EMBREE_ISA_AVX512SKX AND EMBREE_LIBRARY_FILES_AVX512SKX)
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512SKX})
ADD_LIBRARY(embree_avx512skx STATIC ${EMBREE_LIBRARY_FILES_AVX512SKX})
SET_TARGET_PROPERTIES(embree_avx512skx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512SKX}")
SET_PROPERTY(TARGET embree_avx512skx PROPERTY FOLDER kernels)
+7 -5
View File
@@ -134,7 +134,7 @@ namespace embree
/*! Maximal depth of the BVH. */
static const size_t maxBuildDepth = 32;
static const size_t maxBuildDepthLeaf = maxBuildDepth+8;
static const size_t maxDepth = maxBuildDepth+maxBuildDepthLeaf;
static const size_t maxDepth = 2*maxBuildDepthLeaf; // 2x because of two level builder
/*! Maximal number of primitive blocks in a leaf. */
static const size_t maxLeafBlocks = items_mask-tyLeaf;
@@ -169,6 +169,7 @@ namespace embree
prefetchL2(((char*)ptr)+3*64);
}
if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
/* KNL still needs L2 prefetches for large nodes */
prefetchL2(((char*)ptr)+4*64);
prefetchL2(((char*)ptr)+5*64);
prefetchL2(((char*)ptr)+6*64);
@@ -191,10 +192,11 @@ namespace embree
prefetchL1(((char*)ptr)+3*64);
}
if ((N >= 8) && (types > BVH_FLAG_ALIGNED_NODE)) {
prefetchL1(((char*)ptr)+4*64);
prefetchL1(((char*)ptr)+5*64);
prefetchL1(((char*)ptr)+6*64);
prefetchL1(((char*)ptr)+7*64);
/* deactivate for large nodes on Xeon, as it introduces regressions */
//prefetchL1(((char*)ptr)+4*64);
//prefetchL1(((char*)ptr)+5*64);
//prefetchL1(((char*)ptr)+6*64);
//prefetchL1(((char*)ptr)+7*64);
}
}
else
+23 -19
View File
@@ -182,6 +182,8 @@ namespace embree
DECLARE_SYMBOL2(Accel::Intersector16,BVH4VirtualIntersector16Chunk);
DECLARE_SYMBOL2(Accel::Intersector16,BVH4VirtualMBIntersector16Chunk);
DECLARE_SYMBOL2(Accel::IntersectorN,BVH4IntersectorStreamPacketFallback);
DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Line4iIntersectorStream);
DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Bezier1vIntersectorStream);
DECLARE_SYMBOL2(Accel::IntersectorN,BVH4Bezier1iIntersectorStream);
@@ -497,6 +499,8 @@ namespace embree
//IF_ENABLED_HAIR(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2 (features,BVH4Bezier1vIntersectorStream_OBB));
//IF_ENABLED_HAIR(SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2 (features,BVH4Bezier1iIntersectorStream_OBB));
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(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));
@@ -524,7 +528,7 @@ namespace embree
intersectors.intersector4 = BVH4Bezier1vIntersector4Hybrid();
intersectors.intersector8 = BVH4Bezier1vIntersector8Hybrid();
intersectors.intersector16 = BVH4Bezier1vIntersector16Hybrid();
//intersectors.intersectorN = BVH4Bezier1vIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -538,7 +542,7 @@ namespace embree
intersectors.intersector4 = BVH4Bezier1iIntersector4Hybrid();
intersectors.intersector8 = BVH4Bezier1iIntersector8Hybrid();
intersectors.intersector16 = BVH4Bezier1iIntersector16Hybrid();
//intersectors.intersectorN = BVH4Bezier1iIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -552,7 +556,7 @@ namespace embree
intersectors.intersector4 = BVH4Line4iIntersector4();
intersectors.intersector8 = BVH4Line4iIntersector8();
intersectors.intersector16 = BVH4Line4iIntersector16();
//intersectors.intersectorN = BVH4Line4iIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -566,7 +570,7 @@ namespace embree
intersectors.intersector4 = BVH4Line4iMBIntersector4();
intersectors.intersector8 = BVH4Line4iMBIntersector8();
intersectors.intersector16 = BVH4Line4iMBIntersector16();
//intersectors.intersectorN = BVH4Line4iMBIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -580,7 +584,7 @@ namespace embree
intersectors.intersector4 = BVH4Bezier1vIntersector4Hybrid_OBB();
intersectors.intersector8 = BVH4Bezier1vIntersector8Hybrid_OBB();
intersectors.intersector16 = BVH4Bezier1vIntersector16Hybrid_OBB();
//intersectors.intersectorN = BVH4Bezier1vIntersectorStream_OBB();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -594,7 +598,7 @@ namespace embree
intersectors.intersector4 = BVH4Bezier1iIntersector4Hybrid_OBB();
intersectors.intersector8 = BVH4Bezier1iIntersector8Hybrid_OBB();
intersectors.intersector16 = BVH4Bezier1iIntersector16Hybrid_OBB();
//intersectors.intersectorN = BVH4Bezier1iIntersectorStream_OBB();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -608,7 +612,7 @@ namespace embree
intersectors.intersector4 = BVH4OBBBezier1iMBIntersector4Hybrid_OBB();
intersectors.intersector8 = BVH4OBBBezier1iMBIntersector8Hybrid_OBB();
intersectors.intersector16 = BVH4OBBBezier1iMBIntersector16Hybrid_OBB();
//intersectors.intersectorN = BVH4OBBBezier1iMBIntersectorStream_OBB();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -700,7 +704,7 @@ namespace embree
intersectors.intersector4 = BVH4Triangle4vMBIntersector4HybridMoeller();
intersectors.intersector8 = BVH4Triangle4vMBIntersector8HybridMoeller();
intersectors.intersector16 = BVH4Triangle4vMBIntersector16HybridMoeller();
//intersectors.intersectorN = BVH4Triangle4vMBIntersectorStreamMoeller();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -713,7 +717,7 @@ namespace embree
intersectors.intersector4 = BVH4Triangle4vMBIntersector4HybridPluecker();
intersectors.intersector8 = BVH4Triangle4vMBIntersector8HybridPluecker();
intersectors.intersector16 = BVH4Triangle4vMBIntersector16HybridPluecker();
//intersectors.intersectorN = BVH4Triangle4vMBIntersectorStreamPluecker();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -733,7 +737,7 @@ namespace embree
intersectors.intersector4 = BVH4Triangle4iMBIntersector4HybridMoeller();
intersectors.intersector8 = BVH4Triangle4iMBIntersector8HybridMoeller();
intersectors.intersector16 = BVH4Triangle4iMBIntersector16HybridMoeller();
//intersectors.intersectorN = BVH4Triangle4iMBIntersectorStreamMoeller();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -746,7 +750,7 @@ namespace embree
intersectors.intersector4 = BVH4Triangle4iMBIntersector4HybridPluecker();
intersectors.intersector8 = BVH4Triangle4iMBIntersector8HybridPluecker();
intersectors.intersector16 = BVH4Triangle4iMBIntersector16HybridPluecker();
//intersectors.intersectorN = BVH4Triangle4iMBIntersectorStreamPluecker();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -836,7 +840,7 @@ namespace embree
intersectors.intersector4 = BVH4Quad4iMBIntersector4HybridMoeller();
intersectors.intersector8 = BVH4Quad4iMBIntersector8HybridMoeller();
intersectors.intersector16= BVH4Quad4iMBIntersector16HybridMoeller();
//intersectors.intersectorN = BVH4Quad4iMBIntersectorStreamMoeller();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -849,7 +853,7 @@ namespace embree
intersectors.intersector4 = BVH4Quad4iMBIntersector4HybridPluecker();
intersectors.intersector8 = BVH4Quad4iMBIntersector8HybridPluecker();
intersectors.intersector16= BVH4Quad4iMBIntersector16HybridPluecker();
//intersectors.intersectorN = BVH4Quad4iMBIntersectorStreamPluecker();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -896,7 +900,7 @@ namespace embree
intersectors.intersector4 = BVH4VirtualMBIntersector4Chunk();
intersectors.intersector8 = BVH4VirtualMBIntersector8Chunk();
intersectors.intersector16 = BVH4VirtualMBIntersector16Chunk();
//intersectors.intersectorN = BVH4VirtualMBIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -910,7 +914,7 @@ namespace embree
intersectors.intersector4 = BVH4SubdivPatch1Intersector4();
intersectors.intersector8 = BVH4SubdivPatch1Intersector8();
intersectors.intersector16 = BVH4SubdivPatch1Intersector16();
//intersectors.intersectorN = BVH4SubdivPatch1IntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -924,7 +928,7 @@ namespace embree
intersectors.intersector4 = BVH4SubdivPatch1EagerIntersector4();
intersectors.intersector8 = BVH4SubdivPatch1EagerIntersector8();
intersectors.intersector16 = BVH4SubdivPatch1EagerIntersector16();
//intersectors.intersectorN = BVH4SubdivPatch1EagerIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -938,7 +942,7 @@ namespace embree
intersectors.intersector4 = BVH4SubdivPatch1CachedIntersector4();
intersectors.intersector8 = BVH4SubdivPatch1CachedIntersector8();
intersectors.intersector16 = BVH4SubdivPatch1CachedIntersector16();
//intersectors.intersectorN = BVH4SubdivPatch1CachedIntersectorStream();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -952,7 +956,7 @@ namespace embree
intersectors.intersector4 = BVH4SubdivPatch1MBIntersector4();
intersectors.intersector8 = BVH4SubdivPatch1MBIntersector8();
intersectors.intersector16 = BVH4SubdivPatch1MBIntersector16();
//intersectors.intersectorN = BVH4SubdivPatch1MBStreamIntersector();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -966,7 +970,7 @@ namespace embree
intersectors.intersector4 = BVH4SubdivPatch1CachedMBIntersector4();
intersectors.intersector8 = BVH4SubdivPatch1CachedMBIntersector8();
intersectors.intersector16 = BVH4SubdivPatch1CachedMBIntersector16();
//intersectors.intersectorN = BVH4SubdivPatch1CachedMBStreamIntersector();
intersectors.intersectorN = BVH4IntersectorStreamPacketFallback();
#endif
return intersectors;
}
+2
View File
@@ -268,6 +268,8 @@ namespace embree
//DEFINE_SYMBOL2(Accel::IntersectorN,BVH4Bezier1vIntersectorStream_OBB);
//DEFINE_SYMBOL2(Accel::IntersectorN,BVH4Bezier1iIntersectorStream_OBB);
DEFINE_SYMBOL2(Accel::IntersectorN, BVH4IntersectorStreamPacketFallback);
DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4IntersectorStreamMoeller);
DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4IntersectorStreamMoellerNoFilter);
DEFINE_SYMBOL2(Accel::IntersectorN, BVH4Triangle4iIntersectorStreamMoeller);
+20 -13
View File
@@ -14,7 +14,9 @@
// limitations under the License. //
// ======================================================================== //
#if defined (EMBREE_TARGET_AVX)
#include "../common/isa.h" // to define EMBREE_TARGET_SIMD8
#if defined (EMBREE_TARGET_SIMD8)
#include "bvh8_factory.h"
#include "../bvh/bvh.h"
@@ -155,6 +157,8 @@ namespace embree
DECLARE_SYMBOL2(Accel::Intersector16,BVH8VirtualIntersector16Chunk);
DECLARE_SYMBOL2(Accel::Intersector16,BVH8VirtualMBIntersector16Chunk);
DECLARE_SYMBOL2(Accel::IntersectorN,BVH8IntersectorStreamPacketFallback);
//DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Line4iIntersectorStream);
//DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Bezier1vIntersectorStream_OBB);
//DECLARE_SYMBOL2(Accel::IntersectorN,BVH8Bezier1iIntersectorStream_OBB);
@@ -412,6 +416,9 @@ namespace embree
IF_ENABLED_USER(SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,BVH8VirtualMBIntersector16Chunk));
/* select stream intersectors */
SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(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));
@@ -526,7 +533,7 @@ namespace embree
intersectors.intersector4 = BVH8Bezier1vIntersector4Hybrid_OBB();
intersectors.intersector8 = BVH8Bezier1vIntersector8Hybrid_OBB();
intersectors.intersector16 = BVH8Bezier1vIntersector16Hybrid_OBB();
//intersectors.intersectorN = BVH8Bezier1vIntersectorStream_OBB();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -540,7 +547,7 @@ namespace embree
intersectors.intersector4 = BVH8Bezier1iIntersector4Hybrid_OBB();
intersectors.intersector8 = BVH8Bezier1iIntersector8Hybrid_OBB();
intersectors.intersector16 = BVH8Bezier1iIntersector16Hybrid_OBB();
//intersectors.intersectorN = BVH8Bezier1iIntersectorStream_OBB();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -554,7 +561,7 @@ namespace embree
intersectors.intersector4 = BVH8OBBBezier1iMBIntersector4Hybrid_OBB();
intersectors.intersector8 = BVH8OBBBezier1iMBIntersector8Hybrid_OBB();
intersectors.intersector16 = BVH8OBBBezier1iMBIntersector16Hybrid_OBB();
//intersectors.intersectorN = BVH8OBBBezier1iMBIntersectorStream_OBB();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -568,7 +575,7 @@ namespace embree
intersectors.intersector4 = BVH8Line4iIntersector4();
intersectors.intersector8 = BVH8Line4iIntersector8();
intersectors.intersector16 = BVH8Line4iIntersector16();
//intersectors.intersectorN = BVH8Line4iIntersectorStream();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -582,7 +589,7 @@ namespace embree
intersectors.intersector4 = BVH8Line4iMBIntersector4();
intersectors.intersector8 = BVH8Line4iMBIntersector8();
intersectors.intersector16 = BVH8Line4iMBIntersector16();
//intersectors.intersectorN = BVH8Line4iMBIntersectorStream();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -666,7 +673,7 @@ namespace embree
intersectors.intersector4 = BVH8Triangle4vMBIntersector4HybridMoeller();
intersectors.intersector8 = BVH8Triangle4vMBIntersector8HybridMoeller();
intersectors.intersector16 = BVH8Triangle4vMBIntersector16HybridMoeller();
//intersectors.intersectorN = BVH8Triangle4vMBIntersectorStreamMoeller();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -679,7 +686,7 @@ namespace embree
intersectors.intersector4 = BVH8Triangle4vMBIntersector4HybridPluecker();
intersectors.intersector8 = BVH8Triangle4vMBIntersector8HybridPluecker();
intersectors.intersector16 = BVH8Triangle4vMBIntersector16HybridPluecker();
//intersectors.intersectorN = BVH8Triangle4vMBIntersectorStreamPluecker();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -699,7 +706,7 @@ namespace embree
intersectors.intersector4 = BVH8Triangle4iMBIntersector4HybridMoeller();
intersectors.intersector8 = BVH8Triangle4iMBIntersector8HybridMoeller();
intersectors.intersector16 = BVH8Triangle4iMBIntersector16HybridMoeller();
//intersectors.intersectorN = BVH8Triangle4iMBIntersectorStreamMoeller();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -712,7 +719,7 @@ namespace embree
intersectors.intersector4 = BVH8Triangle4iMBIntersector4HybridPluecker();
intersectors.intersector8 = BVH8Triangle4iMBIntersector8HybridPluecker();
intersectors.intersector16 = BVH8Triangle4iMBIntersector16HybridPluecker();
//intersectors.intersectorN = BVH8Triangle4iMBIntersectorStreamPluecker();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -802,7 +809,7 @@ namespace embree
intersectors.intersector4 = BVH8Quad4iMBIntersector4HybridMoeller();
intersectors.intersector8 = BVH8Quad4iMBIntersector8HybridMoeller();
intersectors.intersector16 = BVH8Quad4iMBIntersector16HybridMoeller();
//intersectors.intersectorN = BVH8Quad4iMBIntersectorStreamMoeller();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -815,7 +822,7 @@ namespace embree
intersectors.intersector4 = BVH8Quad4iMBIntersector4HybridPluecker();
intersectors.intersector8 = BVH8Quad4iMBIntersector8HybridPluecker();
intersectors.intersector16 = BVH8Quad4iMBIntersector16HybridPluecker();
//intersectors.intersectorN = BVH8Quad4iMBIntersectorStreamPluecker();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
@@ -870,7 +877,7 @@ namespace embree
intersectors.intersector4 = BVH8VirtualMBIntersector4Chunk();
intersectors.intersector8 = BVH8VirtualMBIntersector8Chunk();
intersectors.intersector16 = BVH8VirtualMBIntersector16Chunk();
//intersectors.intersectorN = BVH8VirtualMBIntersectorStream();
intersectors.intersectorN = BVH8IntersectorStreamPacketFallback();
#endif
return intersectors;
}
+2
View File
@@ -217,6 +217,8 @@ namespace embree
//DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Bezier1vIntersectorStream_OBB);
//DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Bezier1iIntersectorStream_OBB);
DEFINE_SYMBOL2(Accel::IntersectorN,BVH8IntersectorStreamPacketFallback);
DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoeller);
DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4IntersectorStreamMoellerNoFilter);
DEFINE_SYMBOL2(Accel::IntersectorN,BVH8Triangle4iIntersectorStreamMoeller);
+6 -4
View File
@@ -37,9 +37,10 @@ namespace embree
namespace isa
{
template<int N, int types, bool robust, typename PrimitiveIntersector1>
void BVHNIntersector1<N,types,robust,PrimitiveIntersector1>::intersect(const BVH* __restrict__ bvh, Ray& __restrict__ ray, IntersectContext* context)
void BVHNIntersector1<N,types,robust,PrimitiveIntersector1>::intersect(const Accel::Intersectors* __restrict__ This, Ray& __restrict__ ray, IntersectContext* __restrict__ context)
{
/*! perform per ray precalculations required by the primitive intersector */
const BVH* __restrict__ bvh = (const BVH*) This->ptr;
Precalculations pre(ray,bvh);
/*! stack state */
@@ -124,18 +125,19 @@ namespace embree
}
template<int N, int types, bool robust, typename PrimitiveIntersector1>
void BVHNIntersector1<N,types,robust,PrimitiveIntersector1>::occluded(const BVH* __restrict__ bvh, Ray& __restrict__ ray, IntersectContext* context)
void BVHNIntersector1<N,types,robust,PrimitiveIntersector1>::occluded(const Accel::Intersectors* __restrict__ This, Ray& __restrict__ ray, IntersectContext* __restrict__ context)
{
/*! early out for already occluded rays */
if (unlikely(ray.geomID == 0))
return;
/*! perform per ray precalculations required by the primitive intersector */
const BVH* __restrict__ bvh = (const BVH*) This->ptr;
Precalculations pre(ray,bvh);
/*! stack state */
NodeRef stack[stackSize]; //!< stack of nodes that still need to get traversed
NodeRef* stackPtr = stack+1; //!< current stack pointer
NodeRef stack[stackSize]; //!< stack of nodes that still need to get traversed
NodeRef* stackPtr = stack+1; //!< current stack pointer
NodeRef* stackEnd = stack+stackSize;
stack[0] = bvh->root;
+2 -2
View File
@@ -42,8 +42,8 @@ namespace embree
static const size_t Nx = (types == BVH_AN1 || types == BVH_QN1) ? vextend<N>::size : N;
public:
static void intersect(const BVH* This, Ray& ray, IntersectContext* context);
static void occluded (const BVH* This, Ray& ray, IntersectContext* context);
static void intersect(const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
};
}
}
+213 -70
View File
@@ -34,9 +34,11 @@
#define SWITCH_DURING_DOWN_TRAVERSAL 1
#define FORCE_SINGLE_MODE 0
#define ENABLE_FAST_COHERENT_CODEPATHS 1
#define STREAM_IN_HYBRID 0
namespace embree
{
namespace isa
@@ -124,13 +126,15 @@ namespace embree
}
template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single>
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::intersect(vint<K>* __restrict__ valid_i, BVH* __restrict__ bvh, RayK<K>& __restrict__ ray, IntersectContext* context)
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::intersect(vint<K>* __restrict__ valid_i, Accel::Intersectors* __restrict__ This, RayK<K>& __restrict__ ray, IntersectContext* __restrict__ context)
{
BVH* __restrict__ bvh = (BVH*) This->ptr;
#if ENABLE_FAST_COHERENT_CODEPATHS == 1
assert(context);
if (unlikely(types == BVH_AN1 && context->user && isCoherent(context->user->flags)))
{
intersect_coherent(valid_i,bvh,ray,context);
intersect_coherent(valid_i,This,ray,context);
return;
}
#endif
@@ -145,7 +149,6 @@ namespace embree
size_t valid_bits = movemask(valid);
if (unlikely(valid_bits == 0)) return;
/* verify correct input */
assert(all(valid,ray.valid()));
assert(all(valid,ray.tnear >= 0.0f));
@@ -177,12 +180,9 @@ namespace embree
/* determine switch threshold based on flags */
const size_t switchThreshold = (context->user && isCoherent(context->user->flags)) ? 2 : switchThresholdIncoherent;
vint<K> octant = \
select(vfloat<K>(rdir.x) < 0.0f,vint<K>(1),vint<K>(zero)) |
select(vfloat<K>(rdir.y) < 0.0f,vint<K>(2),vint<K>(zero)) |
select(vfloat<K>(rdir.z) < 0.0f,vint<K>(4),vint<K>(zero));
octant = select(valid,octant,vint<K>(0xffffffff));
vint<K> octant = ray.octant();
octant = select(valid, octant, vint<K>(0xffffffff));
do
{
const size_t valid_index = __bsf(valid_bits);
@@ -264,7 +264,7 @@ namespace embree
const NodeRef child = node->children[i];
if (unlikely(child == BVH::emptyNode)) break;
vfloat<K> lnearP;
vbool<K> lhit(valid_node);
vbool<K> lhit = valid_node;
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
/* if we hit the child we choose to continue with that child if it
@@ -368,8 +368,13 @@ namespace embree
template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single>
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::intersect_coherent(vint<K>* __restrict__ valid_i, BVH* __restrict__ bvh, RayK<K>& __restrict__ ray, IntersectContext* context)
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::intersect_coherent(vint<K>* __restrict__ valid_i,
Accel::Intersectors* __restrict__ This,
RayK<K>& __restrict__ ray,
IntersectContext* context)
{
BVH* __restrict__ bvh = (BVH*) This->ptr;
/* filter out invalid rays */
vbool<K> valid = *valid_i == -1;
#if defined(EMBREE_IGNORE_INVALID_RAYS)
@@ -407,7 +412,7 @@ namespace embree
const vfloat<K> ray_tnear = select(octant_valid,org_ray_tnear,vfloat<K>(pos_inf));
vfloat<K> ray_tfar = select(octant_valid,org_ray_tfar ,vfloat<K>(neg_inf));
Frustum frustum(octant_valid,rdir,org,ray_tnear,ray_tfar);
Frustum<N,Nx,K,robust> frustum(octant_valid,org,rdir,ray_tnear,ray_tfar);
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
@@ -434,8 +439,8 @@ namespace embree
const NodeRef nodeRef = cur;
const AlignedNode* __restrict__ const node = nodeRef.alignedNode();
__aligned(64) float fmin[16];
size_t m_frusta_node = frustum.intersect(nodeRef,fmin);
vfloat<Nx> fmin;
size_t m_frusta_node = frustum.intersect(node,fmin);
if (unlikely(!m_frusta_node)) goto pop;
cur = BVH::emptyNode;
@@ -448,7 +453,7 @@ namespace embree
do {
const size_t i = __bscf(m_frusta_node);
vfloat<K> lnearP;
vbool<K> lhit( false );
vbool<K> lhit = false; // motion blur is not supported, so the initial value will be ignored
STAT3(normal.trav_nodes,1,1,1);
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
@@ -493,7 +498,6 @@ namespace embree
std::swap(stackPtr[-3],stackPtr[-2]);
}
}
}
/* intersect leaf */
@@ -506,17 +510,13 @@ namespace embree
size_t lazy_node = 0;
PrimitiveIntersectorK::intersect(valid_leaf,pre,ray,context,prim,items,lazy_node);
#if 1
/* reduce max distance interval on successful intersection */
if (likely(any((ray.tfar < ray_tfar) & valid_leaf)))
{
ray_tfar = select(valid_leaf,ray.tfar,ray_tfar);
//frusta_max_dist = reduce_max(ray_tfar);
frustum.updateMaxDist(ray_tfar);
}
#else
ray_tfar = select(valid_leaf,ray.tfar,ray_tfar);
#endif
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
@@ -597,13 +597,15 @@ namespace embree
}
template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single>
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::occluded(vint<K>* __restrict__ valid_i, BVH* __restrict__ bvh, RayK<K>& __restrict__ ray, IntersectContext* context)
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::occluded(vint<K>* __restrict__ valid_i, Accel::Intersectors* __restrict__ This, RayK<K>& __restrict__ ray, IntersectContext* context)
{
BVH* __restrict__ bvh = (BVH*) This->ptr;
#if ENABLE_FAST_COHERENT_CODEPATHS == 1
assert(context);
if (unlikely(types == BVH_AN1 && context->user && isCoherent(context->user->flags)))
{
occluded_coherent(valid_i,bvh,ray,context);
occluded_coherent(valid_i,This,ray,context);
return;
}
#endif
@@ -615,7 +617,7 @@ namespace embree
#endif
/* return if there are no valid rays */
const size_t valid_bits = movemask(valid);
size_t valid_bits = movemask(valid);
if (unlikely(valid_bits == 0)) return;
/* verify correct input */
@@ -633,6 +635,154 @@ namespace embree
const Vec3vf<K> org(ray_org), org_rdir = org * rdir;
ray_tnear = select(valid,ray_tnear,vfloat<K>(pos_inf));
ray_tfar = select(valid,ray_tfar ,vfloat<K>(neg_inf));
#if STREAM_IN_HYBRID == 1
Vec3vi<K> nearXYZ;
nearXYZ.x = select(rdir.x >= 0.0f,vint<K>(0*(int)sizeof(vfloat<N>)),vint<K>(1*(int)sizeof(vfloat<N>)));
nearXYZ.y = select(rdir.y >= 0.0f,vint<K>(2*(int)sizeof(vfloat<N>)),vint<K>(3*(int)sizeof(vfloat<N>)));
nearXYZ.z = select(rdir.z >= 0.0f,vint<K>(4*(int)sizeof(vfloat<N>)),vint<K>(5*(int)sizeof(vfloat<N>)));
const int shiftTable[8] = { (int)1 << 0, (int)1 << 1, (int)1 << 2, (int)1 << 3, (int)1 << 4, (int)1 << 5, (int)1 << 6, (int)1 << 7 };
{
/*! stack state */
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
//StackItemT<NodeRef>* stackEnd = stack + stackSizeSingle;
stack[0].ptr = bvh->root;
stack[0].dist = movemask(valid);
while (1) pop:
{
if (unlikely(stackPtr == stack)) break;
STAT3(shadow.trav_stack_pop,1,1,1);
stackPtr--;
NodeRef cur = NodeRef(stackPtr->ptr);
size_t cur_mask = stackPtr->dist & movemask(!terminated);
if (unlikely(cur_mask == 0)) continue;
while (true)
{
/*! stop if we found a leaf node */
if (unlikely(cur.isLeaf())) break;
const AlignedNode* __restrict__ const node = cur.alignedNode();
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_x));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_y));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_y));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_z));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_z));
size_t bits = cur_mask;
#if defined(__AVX__)
STAT3(shadow.trav_hit_boxes[__popcnt(cur_mask)],1,1,1);
#endif
assert(bits);
const vbool<Nx> valid_children = bminX <= bmaxX;
vint<Nx> vmask(zero);
do
{
STAT3(shadow.trav_nodes,1,1,1);
const size_t i = __bscf(bits);
assert(i < K);
//const vint<Nx> bitmask = vint<Nx>((int)1 << i);
const vint<Nx> bitmask(shiftTable[i]);
const vfloat<Nx> tNearX = msub(bminX, rdir.x[i], org_rdir.x[i]);
const vfloat<Nx> tNearY = msub(bminY, rdir.y[i], org_rdir.y[i]);
const vfloat<Nx> tNearZ = msub(bminZ, rdir.z[i], org_rdir.z[i]);
const vfloat<Nx> tFarX = msub(bmaxX, rdir.x[i], org_rdir.x[i]);
const vfloat<Nx> tFarY = msub(bmaxY, rdir.y[i], org_rdir.y[i]);
const vfloat<Nx> tFarZ = msub(bmaxZ, rdir.z[i], org_rdir.z[i]);
const vfloat<Nx> tNear = maxi(mini(tNearX,tFarX), mini(tNearY,tFarY), mini(tNearZ,tFarZ), vfloat<Nx>(ray_tnear[i]));
const vfloat<Nx> tFar = mini(maxi(tNearX,tFarX), maxi(tNearY,tFarY), maxi(tNearZ,tFarZ), vfloat<Nx>(ray_tfar[i]));
const vbool<Nx> hit_mask = tNear <= tFar;
#if defined(__AVX2__)
vmask = vmask | (bitmask & vint<Nx>(hit_mask));
#else
vmask = select(hit_mask, vmask | bitmask, vmask);
#endif
} while(bits);
size_t mask = movemask( (vmask != vint<Nx>(zero)) & valid_children);
if (unlikely(mask == 0)) goto pop;
/* select next child and push other children */
//const BaseNode* node = cur.baseNode(types);
/*! one child is hit, continue with that child */
size_t r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = vmask[r];
/* simple in order sequence */
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) continue;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
for (; ;)
{
r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = vmask[r];
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) break;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
/*! this is a leaf node */
assert(cur != BVH::emptyNode);
STAT3(shadow.trav_leaves,1,1,1);
size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
size_t bits = cur_mask;
size_t lazy_node = 0;
for (; bits!=0; )
{
const size_t k = __bscf(bits);
if (PrimitiveIntersectorK::occluded(pre,ray,k,context,prim,num,lazy_node)) {
ray.geomID[k] = 0;
set(terminated, k);
}
/* lazy node */
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
if (all(terminated)) break;
}
}
// while(valid_bits);
#else
const vfloat<K> inf = vfloat<K>(pos_inf);
/* compute near/far per ray */
@@ -711,33 +861,23 @@ namespace embree
const NodeRef child = node->children[i];
if (unlikely(child == BVH::emptyNode)) break;
vfloat<K> lnearP;
vbool<K> lhit(valid_node);
vbool<K> lhit = valid_node;
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
/* if we hit the child we choose to continue with that child if it
is closer than the current next child, or we push it onto the stack */
/* if we hit the child we push the previously hit node onto the stack, and continue with the currently hit child */
if (likely(any(lhit)))
{
assert(sptr_node < stackEnd);
assert(child != BVH::emptyNode);
const vfloat<K> childDist = select(lhit,lnearP,inf);
/* push cur node onto stack and continue with hit child */
if (any(childDist < curDist))
{
if (likely(cur != BVH::emptyNode)) {
*sptr_node = cur; sptr_node++;
*sptr_near = curDist; sptr_near++;
}
curDist = childDist;
cur = child;
}
/* push hit child onto stack */
else {
*sptr_node = child; sptr_node++;
*sptr_near = childDist; sptr_near++;
/* push 'cur' node onto stack and continue with hit child */
if (likely(cur != BVH::emptyNode)) {
*sptr_node = cur; sptr_node++;
*sptr_near = curDist; sptr_near++;
}
curDist = childDist;
cur = child;
}
}
if (unlikely(cur == BVH::emptyNode))
@@ -772,23 +912,31 @@ namespace embree
size_t items; const Primitive* prim = (Primitive*) cur.leaf(items);
size_t lazy_node = 0;
#if defined(__AVX__)
STAT3(shadow.trav_hit_boxes[popcnt(vbool<K>(!terminated))],1,1,1);
#endif
terminated |= PrimitiveIntersectorK::occluded(!terminated,pre,ray,context,prim,items,lazy_node);
if (all(terminated)) break;
ray_tfar = select(terminated,vfloat<K>(neg_inf),ray_tfar);
ray_tfar = select(terminated, vfloat<K>(neg_inf), ray_tfar); // ignore node intersections for terminated rays
if (unlikely(lazy_node)) {
*sptr_node = lazy_node; sptr_node++;
*sptr_near = neg_inf; sptr_near++;
}
}
#endif
vint<K>::store(valid & terminated,&ray.geomID,0);
AVX_ZERO_UPPER();
}
template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK, bool single>
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::occluded_coherent(vint<K>* __restrict__ valid_i, BVH* __restrict__ bvh, RayK<K>& __restrict__ ray, IntersectContext* context)
void BVHNIntersectorKHybrid<N,K,types,robust,PrimitiveIntersectorK,single>::occluded_coherent(vint<K>* __restrict__ valid_i, Accel::Intersectors* __restrict__ This,
RayK<K>& __restrict__ ray, IntersectContext* context)
{
BVH* __restrict__ bvh = (BVH*) This->ptr;
/* filter out invalid rays */
vbool<K> valid = *valid_i == -1;
#if defined(EMBREE_IGNORE_INVALID_RAYS)
@@ -802,7 +950,7 @@ namespace embree
/* verify correct input */
assert(all(valid,ray.valid()));
assert(all(valid,ray.tnear >= 0.0f));
assert(!(types & BVH_MB) || all(valid,(ray.time >= 0.0f) & (ray.time <= 1.0f)));
assert(!(types & BVH_MB) || all(valid, (ray.time >= 0.0f) & (ray.time <= 1.0f)));
Precalculations pre(valid,ray);
/* load ray */
@@ -815,27 +963,24 @@ namespace embree
const Vec3vf<K> org(ray_org);
const Vec3vf<K> org_rdir = org * rdir;
vint<K> octant = \
select(vfloat<K>(rdir.x) < 0.0f,vint<K>(1),vint<K>(zero)) |
select(vfloat<K>(rdir.y) < 0.0f,vint<K>(2),vint<K>(zero)) |
select(vfloat<K>(rdir.z) < 0.0f,vint<K>(4),vint<K>(zero));
octant = select(valid,octant,vint<K>(0xffffffff));
vint<K> octant = ray.octant();
octant = select(valid, octant, vint<K>(0xffffffff));
do
{
const size_t valid_index = __bsf(valid_bits);
vbool<K> octant_valid = octant[valid_index] == octant;
valid_bits &= ~(size_t)movemask(octant_valid);
const vfloat<K> ray_tnear = select(octant_valid,org_ray_tnear,vfloat<K>(pos_inf));
const vfloat<K> ray_tfar = select(octant_valid,org_ray_tfar ,vfloat<K>(neg_inf));
const vfloat<K> ray_tnear = select(octant_valid, org_ray_tnear, vfloat<K>(pos_inf));
vfloat<K> ray_tfar = select(octant_valid, org_ray_tfar, vfloat<K>(neg_inf));
const Frustum frustum(octant_valid,rdir,org,ray_tnear,ray_tfar);
const Frustum<N,Nx,K,robust> frustum(octant_valid, org, rdir, ray_tnear, ray_tfar);
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
stack[0].ptr = bvh->root;
stack[0].dist = movemask(octant_valid);
StackItemMaskT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemMaskT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
stack[0].ptr = bvh->root;
stack[0].mask = (unsigned int)movemask(octant_valid);
while (1) pop:
{
@@ -846,7 +991,7 @@ namespace embree
NodeRef cur = NodeRef(stackPtr->ptr);
/* cull node of active rays have already been terminated */
unsigned int m_active = stackPtr->dist & (~movemask(terminated));
unsigned int m_active = stackPtr->mask & (~movemask(terminated));
if (unlikely(m_active == 0)) continue;
@@ -857,8 +1002,8 @@ namespace embree
const NodeRef nodeRef = cur;
const AlignedNode* __restrict__ const node = nodeRef.alignedNode();
__aligned(64) float fmin[16];
size_t m_frusta_node = frustum.intersect(nodeRef,fmin);
vfloat<Nx> fmin;
size_t m_frusta_node = frustum.intersect(node,fmin);
if (unlikely(!m_frusta_node)) goto pop;
cur = BVH::emptyNode;
@@ -871,7 +1016,7 @@ namespace embree
do {
const size_t i = __bscf(m_frusta_node);
vfloat<K> lnearP;
vbool<K> lhit( false );
vbool<K> lhit = false; // motion blur is not supported, so the initial value will be ignored
STAT3(normal.trav_nodes,1,1,1);
BVHNNodeIntersectorK<N,K,types,robust>::intersect(nodeRef,i,org,ray_dir,rdir,org_rdir,ray_tnear,ray_tfar,ray.time,lnearP,lhit);
@@ -883,11 +1028,11 @@ namespace embree
if (likely(cur != BVH::emptyNode)) {
num_child_hits++;
stackPtr->ptr = cur;
stackPtr->dist = m_active;
stackPtr->mask = m_active;
stackPtr++;
}
cur = child;
m_active = movemask(lhit);
m_active = (unsigned int)movemask(lhit);
}
} while(m_frusta_node);
@@ -907,20 +1052,18 @@ namespace embree
terminated |= PrimitiveIntersectorK::occluded(!terminated,pre,ray,context,prim,items,lazy_node);
octant_valid &= !terminated;
if (unlikely(none(octant_valid))) break;
ray_tfar = select(terminated, vfloat<K>(neg_inf), ray_tfar); // ignore node intersections for terminated rays
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
stackPtr->dist = movemask(octant_valid);
stackPtr->mask = (unsigned int)movemask(octant_valid);
stackPtr++;
}
}
} while(valid_bits);
vint<K>::store(valid & terminated,&ray.geomID,0);
vint<K>::store(valid & terminated, &ray.geomID, 0);
AVX_ZERO_UPPER();
}
}
}
+5 -177
View File
@@ -19,6 +19,7 @@
#include "bvh.h"
#include "../common/ray.h"
#include "../common/stack_item.h"
#include "frustum.h"
namespace embree
{
@@ -38,7 +39,6 @@ namespace embree
typedef typename BVH::NodeRef NodeRef;
typedef typename BVH::BaseNode BaseNode;
typedef typename BVH::AlignedNode AlignedNode;
typedef typename BVH::AlignedNodeMB AlignedNodeMB;
static const size_t stackSizeSingle = 1+(N-1)*BVH::maxDepth+3; // +3 due to 16-wide store
static const size_t stackSizeChunk = 1+(N-1)*BVH::maxDepth;
@@ -49,178 +49,6 @@ namespace embree
(K==16) ? 14 : // 14 seems to work best for KNL due to better ordered chunk traversal
0;
struct Frustum
{
__forceinline Frustum(const vbool<K> &octant_valid,
const Vec3vf<K> &rdir,
const Vec3vf<K> &org,
const vfloat<K> &ray_tnear,
const vfloat<K> &ray_tfar)
{
const Vec3fa reduced_min_rdir( reduce_min(select(octant_valid,rdir.x,pos_inf)),
reduce_min(select(octant_valid,rdir.y,pos_inf)),
reduce_min(select(octant_valid,rdir.z,pos_inf)) );
const Vec3fa reduced_max_rdir( reduce_max(select(octant_valid,rdir.x,neg_inf)),
reduce_max(select(octant_valid,rdir.y,neg_inf)),
reduce_max(select(octant_valid,rdir.z,neg_inf)) );
const Vec3fa reduced_min_org( reduce_min(select(octant_valid,org.x,pos_inf)),
reduce_min(select(octant_valid,org.y,pos_inf)),
reduce_min(select(octant_valid,org.z,pos_inf)) );
const Vec3fa reduced_max_org( reduce_max(select(octant_valid,org.x,neg_inf)),
reduce_max(select(octant_valid,org.y,neg_inf)),
reduce_max(select(octant_valid,org.z,neg_inf)) );
min_rdir = select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_min_rdir, reduced_max_rdir);
max_rdir = select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_max_rdir, reduced_min_rdir);
if (!robust)
{
min_org_rdir = min_rdir * select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_max_org, reduced_min_org);
max_org_rdir = max_rdir * select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_min_org, reduced_max_org);
}
else
{
min_org_rdir = select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_max_org, reduced_min_org);
max_org_rdir = select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_min_org, reduced_max_org);
}
min_dist = reduce_min(select(octant_valid,ray_tnear,vfloat<K>(pos_inf)));
max_dist = reduce_max(select(octant_valid,ray_tfar ,vfloat<K>(neg_inf)));
#if defined(__AVX512ER__) // KNL+
min_max_rdirX = align_shift_right<16/2>(vfloat16(max_rdir.x),vfloat16(min_rdir.x));
min_max_rdirY = align_shift_right<16/2>(vfloat16(max_rdir.y),vfloat16(min_rdir.y));
min_max_rdirZ = align_shift_right<16/2>(vfloat16(max_rdir.z),vfloat16(min_rdir.z));
min_max_org_rdirX = align_shift_right<16/2>(vfloat16(max_org_rdir.x),vfloat16(min_org_rdir.x));
min_max_org_rdirY = align_shift_right<16/2>(vfloat16(max_org_rdir.y),vfloat16(min_org_rdir.y));
min_max_org_rdirZ = align_shift_right<16/2>(vfloat16(max_org_rdir.z),vfloat16(min_org_rdir.z));
maskX = (vfloat<16>(min_rdir.x) >= 0.0f) ^ vbool16(0xff00);
maskY = (vfloat<16>(min_rdir.y) >= 0.0f) ^ vbool16(0xff00);
maskZ = (vfloat<16>(min_rdir.z) >= 0.0f) ^ vbool16(0xff00);
#else
nearX = (min_rdir.x < 0.0f) ? 1*sizeof(vfloat<N>) : 0*sizeof(vfloat<N>);
nearY = (min_rdir.y < 0.0f) ? 3*sizeof(vfloat<N>) : 2*sizeof(vfloat<N>);
nearZ = (min_rdir.z < 0.0f) ? 5*sizeof(vfloat<N>) : 4*sizeof(vfloat<N>);
farX = nearX ^ sizeof(vfloat<N>);
farY = nearY ^ sizeof(vfloat<N>);
farZ = nearZ ^ sizeof(vfloat<N>);
#endif
}
__forceinline unsigned int intersect(const NodeRef &nodeRef, float * const __restrict__ dist) const
{
/* only default alignedNodes are currently supported */
const AlignedNode* __restrict__ const node = nodeRef.alignedNode();
#if defined(__AVX512ER__)
const vfloat16 lowerX = vfloat16(*(const vfloat<N>*)((const char*)&node->lower_x));
const vfloat16 lowerY = vfloat16(*(const vfloat<N>*)((const char*)&node->lower_y));
const vfloat16 lowerZ = vfloat16(*(const vfloat<N>*)((const char*)&node->lower_z));
const vfloat16 upperX = vfloat16(*(const vfloat<N>*)((const char*)&node->upper_x));
const vfloat16 upperY = vfloat16(*(const vfloat<N>*)((const char*)&node->upper_y));
const vfloat16 upperZ = vfloat16(*(const vfloat<N>*)((const char*)&node->upper_z));
const vfloat16 bminmaxX = select(maskX,lowerX,upperX);
const vfloat16 bminmaxY = select(maskY,lowerY,upperY);
const vfloat16 bminmaxZ = select(maskZ,lowerZ,upperZ);
if (robust)
{
const vfloat16 fminmaxX = (bminmaxX - min_max_org_rdirX) * min_max_rdirX;
const vfloat16 fminmaxY = (bminmaxY - min_max_org_rdirY) * min_max_rdirY;
const vfloat16 fminmaxZ = (bminmaxZ - min_max_org_rdirZ) * min_max_rdirZ;
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 vfloat16 fmin = round_down*max(fminmaxX, fminmaxY, fminmaxZ, vfloat16(min_dist));
vfloat16::store(dist,fmin);
const vfloat16 fmax = round_up*min(fminmaxX, fminmaxY, fminmaxZ, vfloat16(max_dist));
const vbool16 vmask_node_hit = le(vbool16((((int)1 << N)-1)),fmin,align_shift_right<8>(fmax,fmax));
return movemask(vmask_node_hit);
}
else
{
const vfloat16 fminmaxX = msub(bminmaxX, min_max_rdirX, min_max_org_rdirX);
const vfloat16 fminmaxY = msub(bminmaxY, min_max_rdirY, min_max_org_rdirY);
const vfloat16 fminmaxZ = msub(bminmaxZ, min_max_rdirZ, min_max_org_rdirZ);
const vfloat16 fmin = max(fminmaxX, fminmaxY, fminmaxZ, vfloat16(min_dist));
vfloat16::store(dist,fmin);
const vfloat16 fmax = min(fminmaxX, fminmaxY, fminmaxZ, vfloat16(max_dist));
const vbool16 vmask_node_hit = le(vbool16((((int)1 << N)-1)),fmin,align_shift_right<8>(fmax,fmax));
return movemask(vmask_node_hit);
}
#else
const vfloat<N> bminX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nearX));
const vfloat<N> bminY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nearY));
const vfloat<N> bminZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + nearZ));
const vfloat<N> bmaxX = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + farX));
const vfloat<N> bmaxY = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + farY));
const vfloat<N> bmaxZ = vfloat<N>(*(const vfloat<N>*)((const char*)&node->lower_x + farZ));
if (robust)
{
const vfloat<N> fminX = (bminX - vfloat<N>(min_org_rdir.x)) * vfloat<N>(min_rdir.x);
const vfloat<N> fminY = (bminY - vfloat<N>(min_org_rdir.y)) * vfloat<N>(min_rdir.y);
const vfloat<N> fminZ = (bminZ - vfloat<N>(min_org_rdir.z)) * vfloat<N>(min_rdir.z);
const vfloat<N> fmaxX = (bmaxX - vfloat<N>(max_org_rdir.x)) * vfloat<N>(max_rdir.x);
const vfloat<N> fmaxY = (bmaxY - vfloat<N>(max_org_rdir.y)) * vfloat<N>(max_rdir.y);
const vfloat<N> fmaxZ = (bmaxZ - vfloat<N>(max_org_rdir.z)) * vfloat<N>(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<N> fmin = max(fminX, fminY, fminZ, vfloat<N>(min_dist));
vfloat<N>::store(dist,fmin);
const vfloat<N> fmax = min(fmaxX, fmaxY, fmaxZ, vfloat<N>(max_dist));
const vbool<N> 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;
}
else
{
const vfloat<N> fminX = msub(bminX, vfloat<N>(min_rdir.x), vfloat<N>(min_org_rdir.x));
const vfloat<N> fminY = msub(bminY, vfloat<N>(min_rdir.y), vfloat<N>(min_org_rdir.y));
const vfloat<N> fminZ = msub(bminZ, vfloat<N>(min_rdir.z), vfloat<N>(min_org_rdir.z));
const vfloat<N> fmaxX = msub(bmaxX, vfloat<N>(max_rdir.x), vfloat<N>(max_org_rdir.x));
const vfloat<N> fmaxY = msub(bmaxY, vfloat<N>(max_rdir.y), vfloat<N>(max_org_rdir.y));
const vfloat<N> fmaxZ = msub(bmaxZ, vfloat<N>(max_rdir.z), vfloat<N>(max_org_rdir.z));
const vfloat<N> fmin = maxi(fminX, fminY, fminZ, vfloat<N>(min_dist));
vfloat<N>::store(dist,fmin);
const vfloat<N> fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat<N>(max_dist));
const vbool<N> vmask_node_hit = fmin <= fmax;
size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
return m_node;
}
#endif
}
__forceinline void updateMaxDist(const vfloat<K> &ray_tfar)
{
max_dist = reduce_max(ray_tfar);
}
#if defined(__AVX512ER__) // KNL+
vbool16 maskX, maskY, maskZ;
vfloat16 min_max_rdirX, min_max_rdirY, min_max_rdirZ;
vfloat16 min_max_org_rdirX, min_max_org_rdirY, min_max_org_rdirZ;
#else
size_t nearX, nearY, nearZ;
size_t farX, farY, farZ;
#endif
Vec3fa min_rdir;
Vec3fa max_rdir;
Vec3fa min_org_rdir;
Vec3fa max_org_rdir;
float min_dist;
float max_dist;
};
private:
static void intersect1(const BVH* bvh, NodeRef root, const size_t k, Precalculations& pre,
RayK<K>& ray, const Vec3vf<K> &ray_org, const Vec3vf<K> &ray_dir, const Vec3vf<K> &ray_rdir, const vfloat<K> &ray_tnear, const vfloat<K> &ray_tfar, const Vec3vi<K>& nearXYZ, IntersectContext* context);
@@ -228,11 +56,11 @@ namespace embree
RayK<K>& ray, const Vec3vf<K> &ray_org, const Vec3vf<K> &ray_dir, const Vec3vf<K> &ray_rdir, const vfloat<K> &ray_tnear, const vfloat<K> &ray_tfar, const Vec3vi<K>& nearXYZ, IntersectContext* context);
public:
static void intersect(vint<K>* valid, BVH* bvh, RayK<K>& ray, IntersectContext* context);
static void occluded (vint<K>* valid, BVH* bvh, RayK<K>& ray, IntersectContext* context);
static void intersect(vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
static void occluded (vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
static void intersect_coherent(vint<K>* valid, BVH* bvh, RayK<K>& ray, IntersectContext* context);
static void occluded_coherent(vint<K>* valid, BVH* bvh, RayK<K>& ray, IntersectContext* context);
static void intersect_coherent(vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
static void occluded_coherent (vint<K>* valid, Accel::Intersectors* This, RayK<K>& ray, IntersectContext* context);
};
+79 -112
View File
@@ -23,9 +23,9 @@ namespace embree
namespace isa
{
template<int N, int Nx>
struct TravRay
struct TravRay
{
__forceinline TravRay () {}
__forceinline TravRay() {}
__forceinline TravRay(const Vec3fa& ray_org, const Vec3fa& ray_dir)
: org_xyz(ray_org), dir_xyz(ray_dir)
@@ -56,8 +56,8 @@ namespace embree
}
template<int K>
__forceinline TravRay (size_t k, const Vec3vf<K> &ray_org, const Vec3vf<K> &ray_dir,
const Vec3vf<K> &ray_rdir, const Vec3vi<K>& nearXYZ, const size_t flip = sizeof(vfloat<N>))
__forceinline TravRay(size_t k, const Vec3vf<K> &ray_org, const Vec3vf<K> &ray_dir,
const Vec3vf<K> &ray_rdir, const Vec3vi<K>& nearXYZ, const size_t flip = sizeof(vfloat<N>))
{
org = Vec3vf<Nx>(ray_org.x[k], ray_org.y[k], ray_org.z[k]);
dir = Vec3vf<Nx>(ray_dir.x[k], ray_dir.y[k], ray_dir.z[k]);
@@ -82,7 +82,7 @@ namespace embree
#endif
}
__forceinline TravRay (const TravRay& ray)
__forceinline TravRay(const TravRay& ray)
{
org_xyz = ray.org_xyz;
dir_xyz = ray.dir_xyz;
@@ -127,12 +127,12 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N, int Nx>
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
template<>
__forceinline size_t intersectNode<4,4>(const typename BVH4::AlignedNode* node, const TravRay<4,4>& ray,
const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
__forceinline size_t intersectNode<4,4>(const typename BVH4::AlignedNode* node, const TravRay<4,4>& ray,
const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
{
#if defined(__AVX2__)
const vfloat4 tNearX = msub(vfloat4::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
@@ -173,8 +173,8 @@ namespace embree
#if defined(__AVX__)
template<>
__forceinline size_t intersectNode<8,8>(const typename BVH8::AlignedNode* node, const TravRay<8,8>& ray,
const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
__forceinline size_t intersectNode<8,8>(const typename BVH8::AlignedNode* node, const TravRay<8,8>& ray,
const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
{
#if defined(__AVX2__)
const vfloat8 tNearX = msub(vfloat8::load((float*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
@@ -214,10 +214,10 @@ namespace embree
#endif
#if defined(__AVX512F__)
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
template<>
__forceinline size_t intersectNode<4,16>(const typename BVH4::AlignedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<4,16>(const typename BVH4::AlignedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, 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);
@@ -234,9 +234,8 @@ namespace embree
}
template<>
__forceinline size_t intersectNode<8,16>(const typename BVH8::AlignedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<8,16>(const typename BVH8::AlignedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
#if defined(__AVX512ER__)
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);
@@ -248,19 +247,7 @@ namespace embree
const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, tnear);
const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, tfar);
const vbool16 vmask = le(vboolf16(m_valid),tNear,align_shift_right<8>(tFar, tFar));
#else
const vfloat16 tNearX = msub(vfloat16(*(vfloat8*)((const char*)&node->lower_x+ray.nearX)), ray.rdir.x, ray.org_rdir.x);
const vfloat16 tNearY = msub(vfloat16(*(vfloat8*)((const char*)&node->lower_x+ray.nearY)), ray.rdir.y, ray.org_rdir.y);
const vfloat16 tNearZ = msub(vfloat16(*(vfloat8*)((const char*)&node->lower_x+ray.nearZ)), ray.rdir.z, ray.org_rdir.z);
const vfloat16 tFarX = msub(vfloat16(*(vfloat8*)((const char*)&node->lower_x+ray.farX )), ray.rdir.x, ray.org_rdir.x);
const vfloat16 tFarY = msub(vfloat16(*(vfloat8*)((const char*)&node->lower_x+ray.farY )), ray.rdir.y, ray.org_rdir.y);
const vfloat16 tFarZ = msub(vfloat16(*(vfloat8*)((const char*)&node->lower_x+ray.farZ )), ray.rdir.z, ray.org_rdir.z);
const vfloat16 tNear = max(tNearX,tNearY,tNearZ,tnear);
const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,tfar);
const vbool16 vmask = le(vbool16(0xff),tNear,tFar);
#endif
const size_t mask = movemask(vmask);
const size_t mask = movemask(vmask);
dist = tNear;
return mask;
}
@@ -268,10 +255,10 @@ namespace embree
#endif
template<int N, int K>
__forceinline vbool<K> intersectNode(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
__forceinline vbool<K> intersectNode(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
{
#if defined(__AVX2__)
const vfloat<K> lclipMinX = msub(node->lower_x[i],rdir.x,org_rdir.x);
@@ -319,8 +306,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N,int Nx>
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist)
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, const TravRay<N,Nx>& ray,
const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist)
{
const vfloat<N> tNearX = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat<N> tNearY = (vfloat<N>::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -338,11 +325,11 @@ namespace embree
return mask;
}
#if defined(__AVX512F__)
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
template<>
__forceinline size_t intersectNodeRobust<4,16>(const typename BVHN<4>::AlignedNode* node, const TravRay<4,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
__forceinline size_t intersectNodeRobust<4,16>(const typename BVHN<4>::AlignedNode* node, const TravRay<4,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
{
const vfloat16 tNearX = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat16 tNearY = (vfloat16(*(vfloat<4>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -361,8 +348,8 @@ namespace embree
}
template<>
__forceinline size_t intersectNodeRobust<8,16>(const typename BVHN<8>::AlignedNode* node, const TravRay<8,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
__forceinline size_t intersectNodeRobust<8,16>(const typename BVHN<8>::AlignedNode* node, const TravRay<8,16>& ray,
const vfloat<16>& tnear, const vfloat<16>& tfar, vfloat<16>& dist)
{
const vfloat16 tNearX = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir.x;
const vfloat16 tNearY = (vfloat16(*(vfloat<8>*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir.y;
@@ -383,9 +370,9 @@ namespace embree
#endif
template<int N, int K>
__forceinline vbool<K> intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
__forceinline vbool<K> intersectNodeRobust(const typename BVHN<N>::AlignedNode* node, size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
{
// FIXME: use per instruction rounding for AVX512
const vfloat<K> lclipMinX = (node->lower_x[i] - org.x) * rdir.x;
@@ -408,7 +395,7 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNode(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
@@ -509,7 +496,7 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNodeRobust(const typename BVHN<N>::AlignedNodeMB* node, const TravRay<N,N>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const vfloat<N>* pNearX = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearX);
const vfloat<N>* pNearY = (const vfloat<N>*)((const char*)&node->lower_x+ray.nearY);
@@ -579,8 +566,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNodeMB4D(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNodeMB4D(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const typename BVHN<N>::AlignedNodeMB* node = ref.alignedNodeMB();
@@ -668,8 +655,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const typename BVHN<N>::AlignedNodeMB* node = ref.alignedNodeMB();
@@ -700,9 +687,9 @@ namespace embree
}
template<int N, int K>
__forceinline vbool<K> intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
__forceinline vbool<K> intersectNodeMB4DRobust(const typename BVHN<N>::NodeRef ref, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
{
const typename BVHN<N>::AlignedNodeMB* node = ref.alignedNodeMB();
@@ -739,10 +726,10 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N, int Nx>
__forceinline size_t intersectNode(const typename BVHN<N>::QuantizedNode* node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
__forceinline size_t intersectNode(const typename BVHN<N>::QuantizedNode* node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, vfloat<Nx>& dist);
template<>
__forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedNode* node, const TravRay<4,4>& ray, const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
__forceinline size_t intersectNode<4,4>(const typename BVH4::QuantizedNode* node, const TravRay<4,4>& ray, const vfloat4& tnear, const vfloat4& tfar, vfloat4& dist)
{
const vfloat4 start_x(node->start.x);
const vfloat4 scale_x(node->scale.x);
@@ -796,7 +783,7 @@ namespace embree
#if defined(__AVX__)
template<>
__forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedNode* node, const TravRay<8,8>& ray, const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
__forceinline size_t intersectNode<8,8>(const typename BVH8::QuantizedNode* node, const TravRay<8,8>& ray, const vfloat8& tnear, const vfloat8& tfar, vfloat8& dist)
{
const vfloat8 start_x(node->start.x);
const vfloat8 scale_x(node->scale.x);
@@ -849,10 +836,10 @@ namespace embree
#endif
#if defined(__AVX512F__)
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
template<>
__forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<4,16>(const typename BVH4::QuantizedNode* node, const TravRay<4,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
const vfloat16 start_x(node->start.x);
const vfloat16 scale_x(node->scale.x);
@@ -882,9 +869,8 @@ namespace embree
}
template<>
__forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
__forceinline size_t intersectNode<8,16>(const typename BVH8::QuantizedNode* node, const TravRay<8,16>& ray, const vfloat16& tnear, const vfloat16& tfar, vfloat16& dist)
{
#if defined(__AVX512ER__)
const vllong8 invalid((size_t)BVH8::emptyNode);
const vboold8 m_valid(invalid != vllong8::loadu(node->children));
const vfloat16 bminmaxX = node->dequantizeLowerUpperX<16>(ray.permX);
@@ -896,31 +882,7 @@ namespace embree
const vfloat16 tNear = max(tNearFarX, tNearFarY, tNearFarZ, tnear);
const vfloat16 tFar = min(tNearFarX, tNearFarY, tNearFarZ, tfar);
const vbool16 vmask = le(vboolf16(m_valid),tNear,align_shift_right<8>(tFar, tFar));
#else
const vfloat16 start_x(node->start.x);
const vfloat16 scale_x(node->scale.x);
const vfloat16 lower_x = madd(vfloat16(node->dequantize<8>(ray.nearX >> 2)),scale_x,start_x);
const vfloat16 upper_x = madd(vfloat16(node->dequantize<8>(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<8>(ray.nearY >> 2)),scale_y,start_y);
const vfloat16 upper_y = madd(vfloat16(node->dequantize<8>(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<8>(ray.nearZ >> 2)),scale_z,start_z);
const vfloat16 upper_z = madd(vfloat16(node->dequantize<8>(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,tnear);
const vfloat16 tFar = min(tFarX ,tFarY ,tFarZ ,tfar);
const vbool16 vmask = le(vbool16(0xff),tNear,tFar);
#endif
const size_t mask = movemask(vmask);
const size_t mask = movemask(vmask);
dist = tNear;
return mask;
}
@@ -932,8 +894,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNode* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, vfloat<N>& dist)
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNode* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, vfloat<N>& dist)
{
const Vec3vf<N> dir = xfmVector(node->naabb,ray.dir);
//const Vec3vf<N> nrdir = Vec3vf<N>(vfloat<N>(-1.0f))/dir;
@@ -956,9 +918,9 @@ namespace embree
}
template<int N, int K>
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNode* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNode* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, vfloat<K>& dist)
{
const AffineSpace3vf<K> naabb(Vec3f(node->naabb.l.vx.x[i],node->naabb.l.vx.y[i],node->naabb.l.vx.z[i]),
Vec3f(node->naabb.l.vy.x[i],node->naabb.l.vy.y[i],node->naabb.l.vy.z[i]),
@@ -988,8 +950,8 @@ namespace embree
//////////////////////////////////////////////////////////////////////////////////////
template<int N>
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
__forceinline size_t intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const TravRay<N,N>& ray,
const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist)
{
const AffineSpace3vf<N> xfm = node->space0;
const Vec3vf<N> b0_lower = zero;
@@ -1019,9 +981,9 @@ namespace embree
}
template<int N, int K>
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
__forceinline vbool<K> intersectNode(const typename BVHN<N>::UnalignedNodeMB* node, const size_t i,
const Vec3vf<K>& org_i, const Vec3vf<K>& dir_i, const Vec3vf<K>& rdir_i, const Vec3vf<K>& org_rdir_i,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist)
{
const AffineSpace3vf<K> xfm(Vec3f(node->space0.l.vx.x[i],node->space0.l.vx.y[i],node->space0.l.vx.z[i]),
Vec3f(node->space0.l.vy.x[i],node->space0.l.vy.y[i],node->space0.l.vy.z[i]),
@@ -1062,7 +1024,7 @@ namespace embree
struct BVHNNodeIntersector1;
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1073,7 +1035,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,true>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1084,7 +1046,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1095,7 +1057,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,true>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1106,7 +1068,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1117,7 +1079,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,true>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1128,7 +1090,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1_UN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN1_UN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1140,7 +1102,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_UN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_UN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1152,7 +1114,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D_UN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_AN2_AN4D_UN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1164,7 +1126,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1175,7 +1137,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1_AN2,false>
struct BVHNNodeIntersector1<N,Nx,BVH_TN_AN1_AN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<N>& tnear, const vfloat<N>& tfar, const float time, vfloat<N>& dist, size_t& mask)
{
@@ -1187,7 +1149,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,false>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1198,7 +1160,7 @@ namespace embree
};
template<int N, int Nx>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,true>
struct BVHNNodeIntersector1<N,Nx,BVH_QN1,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const TravRay<N,Nx>& ray, const vfloat<Nx>& tnear, const vfloat<Nx>& tfar, const float time, vfloat<Nx>& dist, size_t& mask)
{
@@ -1215,6 +1177,10 @@ namespace embree
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN1,false>
{
/* vmask is both an input and an output parameter! Its initial value should be the parent node
hit mask, which is used for correctly computing the current hit mask. The parent hit mask
is actually required only for motion blur node intersections (because different rays may
have different times), so for regular nodes vmask is simply overwritten. */
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i, const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
{
@@ -1224,7 +1190,7 @@ namespace embree
};
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN1,true>
struct BVHNNodeIntersectorK<N,K,BVH_AN1,true>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i, const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
@@ -1257,7 +1223,7 @@ namespace embree
};
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN1_UN1,false>
struct BVHNNodeIntersectorK<N,K,BVH_AN1_UN1,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
@@ -1270,7 +1236,7 @@ namespace embree
};
template<int N, int K>
struct BVHNNodeIntersectorK<N,K,BVH_AN2_UN2,false>
struct BVHNNodeIntersectorK<N,K,BVH_AN2_UN2,false>
{
static __forceinline bool intersect(const typename BVHN<N>::NodeRef& node, const size_t i,
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
@@ -1313,10 +1279,11 @@ namespace embree
const Vec3vf<K>& org, const Vec3vf<K>& dir, const Vec3vf<K>& rdir, const Vec3vf<K>& org_rdir,
const vfloat<K>& tnear, const vfloat<K>& tfar, const vfloat<K>& time, vfloat<K>& dist, vbool<K>& vmask)
{
if (likely(node.isAlignedNodeMB() || node.isAlignedNodeMB4D()))
if (likely(node.isAlignedNodeMB() || node.isAlignedNodeMB4D())) {
vmask &= intersectNodeMB4D<N,K>(node,i,org,dir,rdir,org_rdir,tnear,tfar,time,dist);
else /*if (unlikely(node.isUnalignedNodeMB()))*/ {
assert(node.isUnalignedNodeMB()); vmask &= intersectNode<N,K>(node.unalignedNodeMB(),i,org,dir,rdir,org_rdir,tnear,tfar,time,dist);
} else /*if (unlikely(node.isUnalignedNodeMB()))*/ {
assert(node.isUnalignedNodeMB());
vmask &= intersectNode<N,K>(node.unalignedNodeMB(),i,org,dir,rdir,org_rdir,tnear,tfar,time,dist);
}
return true;
}
-391
View File
@@ -1,391 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 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. //
// ======================================================================== //
#pragma once
#include "bvh.h"
#include "bvh_intersector_node.h"
#include "bvh_traverser1.h"
#include "../common/ray.h"
namespace embree
{
namespace isa
{
/*! BVH single ray intersector for packets. */
template<int N, int K, int types, bool robust, typename PrimitiveIntersectorK>
class BVHNIntersectorKSingle
{
/* shortcuts for frequently used types */
typedef typename PrimitiveIntersectorK::Precalculations Precalculations;
typedef typename PrimitiveIntersectorK::Primitive Primitive;
typedef BVHN<N> BVH;
typedef typename BVH::NodeRef NodeRef;
typedef typename BVH::BaseNode BaseNode;
typedef typename BVH::AlignedNode AlignedNode;
typedef Vec3<vfloat<N>> Vec3vfN;
typedef Vec3<vfloat<K>> Vec3vfK;
typedef Vec3<vint<K>> Vec3viK;
static const size_t stackSizeSingle = 1+(N-1)*BVH::maxDepth;
/* right now AVX512KNL SIMD extension only for standard node types */
static const size_t Nx = types == BVH_AN1 ? vextend<N>::size : N;
public:
#if defined(__AVX512F__)
__forceinline static 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_leq = d <= dist;
const vbool16 m_leq_shift = m_leq << 1;
dist = select(m_leq,d,dist);
ptr = select(vboold8(m_leq),p,ptr);
dist = select(m_leq_shift,dist_shift,dist);
ptr = select(vboold8(m_leq_shift),ptr_shift,ptr);
}
#endif
static __forceinline void traverseClosestHitNew(const BaseNode* node,
NodeRef& cur,
size_t mask,
const vfloat<Nx>& tNear,
StackItemT<NodeRef>*& stackPtr,
StackItemT<NodeRef>* stackEnd)
{
assert(mask != 0);
//const BaseNode* node = cur.baseNode(types);
#if defined(__AVX512F__)
/*! one child is hit, continue with that child */
const size_t hits = __popcnt(mask);
size_t r = __bscf(mask);
cur = node->child(r);
cur.prefetch(types);
if (likely(mask == 0)) {
assert(cur != BVH::emptyNode);
return;
}
const vllong8 c0(cur);
const vfloat16 d0(tNear[r]);
r = __bscf(mask);
cur = node->child(r);
cur.prefetch(types);
const vllong8 c1(cur);
const vfloat16 d1(tNear[r]);
const vboolf16 m_dist = d0 <= d1;
const vfloat16 d_near = select(m_dist, d0, d1);
const vfloat16 d_far = select(m_dist, d1, d0);
const vllong8 c_near = select(vboold8(m_dist), c0, c1);
const vllong8 c_far = select(vboold8(m_dist), c1, c0);
if (likely(mask == 0)) {
cur = toScalar(c_near);
*(float*)&stackPtr[0].dist = toScalar(d_far);
stackPtr[0].ptr = toScalar(c_far);
stackPtr++;
return;
}
r = __bscf(mask);
cur = node->child(r);
cur.prefetch(types);
const vllong8 c2(cur);
const vfloat16 d2(tNear[r]);
const vboolf16 m_dist1 = d_near <= d2;
const vfloat16 d_near1 = select(m_dist1, d_near, d2);
const vfloat16 d_far1 = select(m_dist1, d2, d_near);
const vllong8 c_near1 = select(vboold8(m_dist1), c_near, c2);
const vllong8 c_far1 = select(vboold8(m_dist1), c2, c_near);
const vboolf16 m_dist2 = d_far <= d_far1;
const vfloat16 d_near2 = select(m_dist2, d_far , d_far1);
const vfloat16 d_far2 = select(m_dist2, d_far1, d_far);
const vllong8 c_near2 = select(vboold8(m_dist2), c_far, c_far1);
const vllong8 c_far2 = select(vboold8(m_dist2), c_far1, c_far);
if (likely(mask == 0)) {
cur = toScalar(c_near1);
*(float*)&stackPtr[0].dist = toScalar(d_far2);
stackPtr[0].ptr = toScalar(c_far2);
*(float*)&stackPtr[1].dist = toScalar(d_near2);
stackPtr[1].ptr = toScalar(c_near2);
stackPtr+=2;
return;
}
vfloat16 dist(pos_inf);
vllong8 ptr(zero);
isort_update(dist,ptr,d0,c0);
isort_update(dist,ptr,d1,c1);
isort_update(dist,ptr,d2,c2);
do {
const size_t r = __bscf(mask);
cur = node->child(r);
const vfloat16 new_dist(tNear[r]);
const vllong8 new_ptr(cur);
cur.prefetch(types);
isort_update(dist,ptr,new_dist,new_ptr);
} while(mask);
cur = toScalar(ptr);
stackPtr += hits - 1;
for (size_t i=0;i<hits-1;i++)
{
dist = align_shift_right<1>(dist,dist);
ptr = align_shift_right<1>(ptr,ptr);
stackPtr[-1-i].ptr = toScalar(ptr);
*(float*)&stackPtr[-1-i].dist = toScalar(dist);
}
#else
/*! one child is hit, continue with that child */
size_t r = __bscf(mask);
cur = node->child(r);
cur.prefetch(types);
if (likely(mask == 0)) {
assert(cur != BVH::emptyNode);
return;
}
/*! two children are hit, push far child, and continue with closer child */
NodeRef c0 = cur;
const unsigned int d0 = ((unsigned int*)&tNear)[r];
r = __bscf(mask);
NodeRef c1 = node->child(r);
c1.prefetch(types);
const unsigned int d1 = ((unsigned int*)&tNear)[r];
assert(c0 != BVH::emptyNode);
assert(c1 != BVH::emptyNode);
if (likely(mask == 0)) {
assert(stackPtr < stackEnd);
if (d0 < d1) { stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++; cur = c0; return; }
else { stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++; cur = c1; return; }
}
/*! Here starts the slow path for 3 or 4 hit children. We push
* all nodes onto the stack to sort them there. */
assert(stackPtr < stackEnd);
stackPtr->ptr = c0; stackPtr->dist = d0; stackPtr++;
assert(stackPtr < stackEnd);
stackPtr->ptr = c1; stackPtr->dist = d1; stackPtr++;
/*! three children are hit, push all onto stack and sort 3 stack items, continue with closest child */
assert(stackPtr < stackEnd);
r = __bscf(mask);
NodeRef c = node->child(r);
c.prefetch(types);
unsigned int d = ((unsigned int*)&tNear)[r];
stackPtr->ptr = c;
stackPtr->dist = d;
stackPtr++;
assert(c != BVH::emptyNode);
if (likely(mask == 0)) {
sort(stackPtr[-1],stackPtr[-2],stackPtr[-3]);
cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
return;
}
/*! four children are hit, push all onto stack and sort 4 stack items, continue with closest child */
assert(stackPtr < stackEnd);
r = __bscf(mask);
c = node->child(r);
c.prefetch(types);
d = *(unsigned int*)&tNear[r];
stackPtr->ptr = c;
stackPtr->dist = d;
stackPtr++;
assert(c != BVH::emptyNode);
if (likely(mask == 0)) {
sort(stackPtr[-1],stackPtr[-2],stackPtr[-3],stackPtr[-4]);
cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
return;
}
/*! fallback case if more than 4 children are hit */
StackItemT<NodeRef>* stackFirst = stackPtr-4;
while (1)
{
assert(stackPtr < stackEnd);
r = __bscf(mask);
c = node->child(r);
c.prefetch(types);
d = *(unsigned int*)&tNear[r];
stackPtr->ptr = c; stackPtr->dist = d; stackPtr++;
assert(c != BVH::emptyNode);
if (unlikely(mask == 0)) break;
}
sort(stackFirst,stackPtr);
cur = (NodeRef) stackPtr[-1].ptr; stackPtr--;
#endif
}
static void intersect1(const BVH* bvh,
NodeRef root,
const size_t k,
Precalculations& pre,
RayK<K>& ray,
const Vec3vfK &ray_org,
const Vec3vfK &ray_dir,
const Vec3vfK &ray_rdir,
const vfloat<K> &ray_tnear,
const vfloat<K> &ray_tfar,
const Vec3viK& nearXYZ,
IntersectContext* context)
{
/*! stack state */
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
StackItemT<NodeRef>* stackEnd = stack + stackSizeSingle;
stack[0].ptr = root;
stack[0].dist = neg_inf;
/*! load the ray into SIMD registers */
TravRay<N,Nx> vray(k,ray_org,ray_dir,ray_rdir,nearXYZ);
vfloat<Nx> ray_near(ray_tnear[k]), ray_far(ray_tfar[k]);
/* pop loop */
while (true) pop:
{
/*! pop next node */
if (unlikely(stackPtr == stack)) break;
stackPtr--;
NodeRef cur = NodeRef(stackPtr->ptr);
/*! if popped node is too far, pop next one */
//if (unlikely(*(float*)&stackPtr->dist > ray.tfar[k])) continue;
if (unlikely((int)stackPtr->dist >= *(const int*)&ray.tfar[k])) continue;
/* downtraversal loop */
while (true)
{
//cur.prefetch(types);
/*! stop if we found a leaf node */
if (unlikely(cur.isLeaf())) break;
STAT3(normal.trav_nodes,1,1,1);
/* intersect node */
size_t mask = 0;
vfloat<Nx> tNear;
BVHNNodeIntersector1<N,Nx,types,robust>::intersect(cur,vray,ray_near,ray_far,pre.ftime(k),tNear,mask);
AlignedNode *node = cur.alignedNode();
/*! if no child is hit, pop next node */
if (unlikely(mask == 0))
goto pop;
/* select next child and push other children */
#if defined(__AVX512F__)
traverseClosestHitNew(node,cur,mask,tNear,stackPtr,stackEnd);
#else
BVHNNodeTraverser1<N,Nx,types>::traverseClosestHit(cur,mask,tNear,stackPtr,stackEnd);
#endif
}
/*! this is a leaf node */
assert(cur != BVH::emptyNode);
STAT3(normal.trav_leaves, 1, 1, 1);
size_t num; Primitive* prim = (Primitive*)cur.leaf(num);
size_t lazy_node = 0;
//const unsigned int old_primID = ray.primID[k];
PrimitiveIntersectorK::intersect(pre, ray, k, context, prim, num, lazy_node);
ray_far = ray.tfar[k];
/* if (unlikely(lazy_node)) { */
/* stackPtr->ptr = lazy_node; */
/* stackPtr->dist = neg_inf; */
/* stackPtr++; */
/* } */
}
}
static bool occluded1(const BVH* bvh, NodeRef root, const size_t k, Precalculations& pre,
RayK<K>& ray, const Vec3vfK &ray_org, const Vec3vfK &ray_dir, const Vec3vfK &ray_rdir, const vfloat<K> &ray_tnear, const vfloat<K> &ray_tfar,
const Vec3viK& nearXYZ, IntersectContext* context)
{
/*! stack state */
NodeRef stack[stackSizeSingle]; //!< stack of nodes that still need to get traversed
NodeRef* stackPtr = stack+1; //!< current stack pointer
NodeRef* stackEnd = stack+stackSizeSingle;
stack[0] = root;
/*! load the ray into SIMD registers */
TravRay<N,Nx> vray(k,ray_org,ray_dir,ray_rdir,nearXYZ);
const vfloat<Nx> ray_near(ray_tnear[k]), ray_far(ray_tfar[k]);
/* pop loop */
while (true) pop:
{
/*! pop next node */
if (unlikely(stackPtr == stack)) break;
stackPtr--;
NodeRef cur = (NodeRef) *stackPtr;
/* downtraversal loop */
while (true)
{
/*! stop if we found a leaf node */
if (unlikely(cur.isLeaf())) break;
STAT3(shadow.trav_nodes,1,1,1);
/* intersect node */
size_t mask = 0;
vfloat<Nx> tNear;
BVHNNodeIntersector1<N,Nx,types,robust>::intersect(cur,vray,ray_near,ray_far,pre.ftime(k),tNear,mask);
/*! if no child is hit, pop next node */
if (unlikely(mask == 0))
goto pop;
/* select next child and push other children */
BVHNNodeTraverser1<N,Nx,types>::traverseAnyHit(cur,mask,tNear,stackPtr,stackEnd);
}
/*! this is a leaf node */
assert(cur != BVH::emptyNode);
STAT3(shadow.trav_leaves,1,1,1);
size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
size_t lazy_node = 0;
if (PrimitiveIntersectorK::occluded(pre,ray,k,context,prim,num,lazy_node)) {
ray.geomID[k] = 0;
return true;
}
if (unlikely(lazy_node)) {
*stackPtr = lazy_node;
stackPtr++;
}
}
return false;
}
static void intersect(vint<K>* valid, BVH* bvh, RayK<K>& ray, IntersectContext* context);
static void occluded (vint<K>* valid, BVH* bvh, RayK<K>& ray, IntersectContext* context);
};
}
}
+219 -103
View File
@@ -34,36 +34,24 @@
#include "../common/scene.h"
#include <bitset>
// TODO: bvh->scene->intersect/occluded correct vs. global scene->intersect/occluded
#define MAX_RAYS 64
namespace embree
{
namespace isa
{
/* enable traversal of either two small streams or one large stream */
#if !defined(__AVX512F__)
static const size_t MAX_RAYS_PER_OCTANT = 8*sizeof(unsigned int);
#else
static const size_t MAX_RAYS_PER_OCTANT = 8*sizeof(size_t);
#endif
static_assert(MAX_RAYS_PER_OCTANT <= MAX_INTERNAL_STREAM_SIZE, "maximal internal stream size exceeded");
// =====================================================================================================
// =====================================================================================================
// =====================================================================================================
template<int N, int Nx, int K, int types, bool robust, typename PrimitiveIntersector>
__forceinline void BVHNIntersectorStream<N, Nx, K, types, robust, PrimitiveIntersector>::intersectCoherent(BVH* __restrict__ bvh, RayK<K>** inputRays, size_t numOctantRays, IntersectContext* context)
__forceinline void BVHNIntersectorStream<N, Nx, K, types, robust, PrimitiveIntersector>::intersect(Accel::Intersectors* __restrict__ This,
RayK<K>** inputPackets, size_t numOctantRays, IntersectContext* context)
{
BVH* __restrict__ bvh = (BVH*) This->ptr;
__aligned(64) StackItemMaskCoherent stack[stackSizeSingle]; //!< stack of nodes
assert(numOctantRays <= MAX_INTERNAL_STREAM_SIZE);
RayK<K>** __restrict__ inputPackets = (RayK<K>**)inputRays;
assert(numOctantRays <= MAX_RAYS);
__aligned(64) Packet packet[MAX_RAYS/K];
__aligned(64) Frusta frusta;
__aligned(64) Packet<K,robust> packet[MAX_INTERNAL_STREAM_SIZE/K];
__aligned(64) Frustum<N,Nx,K,robust> frusta;
bool commonOctant = true;
const size_t m_active = initPacketsAndFrusta<false>(inputPackets, numOctantRays, packet, frusta, commonOctant);
@@ -74,7 +62,7 @@ namespace embree
{
const size_t numPackets = (numOctantRays+K-1)/K;
for (size_t i = 0; i < numPackets; i++)
bvh->scene->intersect(inputPackets[i]->tnear <= inputPackets[i]->tfar,*inputPackets[i],context);
This->intersect(inputPackets[i]->tnear <= inputPackets[i]->tfar,*inputPackets[i],context);
return;
}
@@ -86,8 +74,6 @@ namespace embree
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
const NearFarPreCompute pc(frusta.min_rdir);
StackItemMaskCoherent* stackPtr = stack + 1;
while (1) pop:
@@ -111,7 +97,7 @@ namespace embree
__aligned(64) size_t maskK[N];
for (size_t i = 0; i < N; i++) maskK[i] = m_trav_active;
vfloat<Nx> dist;
const size_t m_node_hit = traverseCoherentStream(m_trav_active, packet, node, pc, frusta, maskK, dist);
const size_t m_node_hit = traverseCoherentStream(m_trav_active, packet, node, frusta, maskK, dist);
if (unlikely(m_node_hit == 0)) goto pop;
BVHNNodeTraverserStreamHitCoherent<N, Nx, types>::traverseClosestHit(cur, m_trav_active, vbool<Nx>((int)m_node_hit), dist, (size_t*)maskK, stackPtr);
@@ -130,17 +116,8 @@ namespace embree
break;
}
assert(b < N);
char *ptr = (char*)&node->lower_x + b*sizeof(float);
assert(cur == node->child(b));
const vfloat<K> minX = vfloat<K>(*(const float*)((const char*)ptr + pc.nearX));
const vfloat<K> minY = vfloat<K>(*(const float*)((const char*)ptr + pc.nearY));
const vfloat<K> minZ = vfloat<K>(*(const float*)((const char*)ptr + pc.nearZ));
const vfloat<K> maxX = vfloat<K>(*(const float*)((const char*)ptr + pc.farX));
const vfloat<K> maxY = vfloat<K>(*(const float*)((const char*)ptr + pc.farY));
const vfloat<K> maxZ = vfloat<K>(*(const float*)((const char*)ptr + pc.farZ));
m_trav_active = intersectAlignedNodePacket(packet, minX, minY, minZ, maxX, maxY, maxZ, m_trav_active);
m_trav_active = intersectAlignedNodePacket(packet, node, b, frusta.nf, m_trav_active);
}
/*! this is a leaf node */
@@ -162,7 +139,7 @@ namespace embree
assert(m_isec & bits);
bits &= ~m_isec;
Packet &p = packet[i];
Packet<K,robust> &p = packet[i];
vbool<K> m_valid = p.min_dist <= p.max_dist;
PrimitiveIntersector::intersectK(m_valid, *inputPackets[i], context, prim, num, lazy_node);
p.max_dist = min(p.max_dist, inputPackets[i]->tfar);
@@ -172,20 +149,184 @@ namespace embree
}
template<int N, int Nx, int K, int types, bool robust, typename PrimitiveIntersector>
__forceinline void BVHNIntersectorStream<N, Nx, K, types, robust, PrimitiveIntersector>::occludedCoherent(BVH* __restrict__ bvh, RayK<K>** inputRays, size_t numOctantRays, IntersectContext* context)
__forceinline void BVHNIntersectorStream<N, Nx, K, types, robust, PrimitiveIntersector>::occluded(Accel::Intersectors* __restrict__ This,
RayK<K>** inputPackets, size_t numOctantRays, IntersectContext* context)
{
__aligned(64) StackItemMaskCoherent stack[stackSizeSingle]; //!< stack of nodes
RayK<K>** __restrict__ inputPackets = (RayK<K>**)inputRays;
assert(numOctantRays <= MAX_RAYS);
BVH* __restrict__ bvh = (BVH*) This->ptr;
assert(numOctantRays <= MAX_INTERNAL_STREAM_SIZE);
/* inactive rays should have been filtered out before */
__aligned(64) Packet packet[MAX_RAYS/K];
__aligned(64) Frusta frusta;
#if 1
__aligned(64) Packet<K,false> packet[MAX_INTERNAL_STREAM_SIZE/K];
assert(numOctantRays <= 32);
const size_t numPackets = (numOctantRays+K-1)/K;
size_t m_active = 0;
for (size_t i = 0; i < numPackets; i++)
{
const vfloat<K> tnear = inputPackets[i]->tnear;
const vfloat<K> tfar = inputPackets[i]->tfar;
vbool<K> m_valid = (tnear <= tfar) & (tnear >= 0.0f);
m_active |= (size_t)movemask(m_valid) << (K*i);
const Vec3vf<K>& org = inputPackets[i]->org;
const Vec3vf<K>& dir = inputPackets[i]->dir;
vfloat<K> packet_min_dist = max(tnear, 0.0f);
vfloat<K> packet_max_dist = select(m_valid, tfar, neg_inf);
new (&packet[i]) Packet<K,false>(org,dir,packet_min_dist,packet_max_dist);
}
const int shiftTable[32] = {
(int)1 << 0, (int)1 << 1, (int)1 << 2, (int)1 << 3, (int)1 << 4, (int)1 << 5, (int)1 << 6, (int)1 << 7,
(int)1 << 8, (int)1 << 9, (int)1 << 10, (int)1 << 11, (int)1 << 12, (int)1 << 13, (int)1 << 14, (int)1 << 15,
(int)1 << 16, (int)1 << 17, (int)1 << 18, (int)1 << 19, (int)1 << 20, (int)1 << 21, (int)1 << 22, (int)1 << 23,
(int)1 << 24, (int)1 << 25, (int)1 << 26, (int)1 << 27, (int)1 << 28, (int)1 << 29, (int)1 << 30, (int)1 << 31
};
StackItemT<NodeRef> stack[stackSizeSingle]; //!< stack of nodes
StackItemT<NodeRef>* stackPtr = stack + 1; //!< current stack pointer
stack[0].ptr = bvh->root;
stack[0].dist = m_active;
size_t terminated = ~m_active;
while (1) pop:
{
if (unlikely(stackPtr == stack)) break;
STAT3(shadow.trav_stack_pop,1,1,1);
stackPtr--;
NodeRef cur = NodeRef(stackPtr->ptr);
size_t cur_mask = (size_t)stackPtr->dist & (~terminated);
if (unlikely(cur_mask == 0)) continue;
while (true)
{
/*! stop if we found a leaf node */
if (unlikely(cur.isLeaf())) break;
const AlignedNode* __restrict__ const node = cur.alignedNode();
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_x));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_y));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_y));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_z));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->upper_z));
size_t bits = cur_mask;
#if defined(__AVX__)
//STAT3(shadow.trav_hit_boxes[__popcnt(cur_mask)],1,1,1);
#endif
assert(bits);
vint<Nx> vmask(zero);
do
{
STAT3(shadow.trav_nodes,1,1,1);
const size_t rayID = __bscf(bits);
assert(rayID < MAX_INTERNAL_STREAM_SIZE);
assert(rayID /K < numPackets);
Packet<K,false> &p = packet[rayID /K];
const size_t i = rayID % K;
const vint<Nx> bitmask(shiftTable[rayID]);
const vfloat<Nx> tNearX = msub(bminX, p.rdir.x[i], p.org_rdir.x[i]);
const vfloat<Nx> tNearY = msub(bminY, p.rdir.y[i], p.org_rdir.y[i]);
const vfloat<Nx> tNearZ = msub(bminZ, p.rdir.z[i], p.org_rdir.z[i]);
const vfloat<Nx> tFarX = msub(bmaxX, p.rdir.x[i], p.org_rdir.x[i]);
const vfloat<Nx> tFarY = msub(bmaxY, p.rdir.y[i], p.org_rdir.y[i]);
const vfloat<Nx> tFarZ = msub(bmaxZ, p.rdir.z[i], p.org_rdir.z[i]);
const vfloat<Nx> tNear = maxi(mini(tNearX,tFarX), mini(tNearY,tFarY), mini(tNearZ,tFarZ), vfloat<Nx>(p.min_dist[i]));
const vfloat<Nx> tFar = mini(maxi(tNearX,tFarX), maxi(tNearY,tFarY), maxi(tNearZ,tFarZ), vfloat<Nx>(p.max_dist[i]));
const vbool<Nx> hit_mask = tNear <= tFar;
#if defined(__AVX2__)
vmask = vmask | (bitmask & vint<Nx>(hit_mask));
#else
vmask = select(hit_mask, vmask | bitmask, vmask);
#endif
} while(bits);
const vbool<Nx> valid_children = bminX <= bmaxX;
size_t mask = movemask( (vmask != vint<Nx>(zero)) & valid_children);
if (unlikely(mask == 0)) goto pop;
__aligned(64) unsigned int child_mask[Nx];
vint<Nx>::storeu(child_mask,vmask); // this explicit store here causes much better code generation
/* select next child and push other children */
//const BaseNode* node = cur.baseNode(types);
/*! one child is hit, continue with that child */
size_t r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = child_mask[r];
/* simple in order sequence */
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) continue;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
for (; ;)
{
r = __bscf(mask);
assert(r < N);
cur = node->child(r);
cur.prefetch(types);
cur_mask = child_mask[r];
assert(cur != BVH::emptyNode);
if (likely(mask == 0)) break;
stackPtr->ptr = cur;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
/*! this is a leaf node */
assert(cur != BVH::emptyNode);
STAT3(shadow.trav_leaves,1,1,1);
size_t num; Primitive* prim = (Primitive*) cur.leaf(num);
size_t bits = cur_mask;
size_t lazy_node = 0;
for (; bits!=0; )
{
const size_t rayID = __bscf(bits);
RayK<K> &ray = *inputPackets[rayID / K];
const size_t k = rayID % K;
if (PrimitiveIntersector::occluded(ray,k,context,prim,num,lazy_node)) {
ray.geomID[k] = 0;
terminated |= (size_t)1 << rayID;
}
/* lazy node */
if (unlikely(lazy_node)) {
stackPtr->ptr = lazy_node;
stackPtr->dist = cur_mask;
stackPtr++;
}
}
if (unlikely(terminated == (size_t)-1)) { break; }
}
#else
__aligned(64) Packet<K,robust> packet[MAX_INTERNAL_STREAM_SIZE/K];
__aligned(64) StackItemMaskCoherent stack[stackSizeSingle]; //!< stack of nodes
__aligned(64) Frustum<N,Nx,K,robust> frusta;
bool commonOctant = true;
size_t m_active = initPacketsAndFrusta<true>(inputPackets, numOctantRays, packet, frusta, commonOctant);
/* valid rays */
if (unlikely(m_active == 0)) return;
@@ -194,7 +335,7 @@ namespace embree
{
const size_t numPackets = (numOctantRays+K-1)/K;
for (size_t i = 0; i < numPackets; i++)
bvh->scene->occluded(inputPackets[i]->tnear <= inputPackets[i]->tfar,*inputPackets[i],context);
This->occluded(inputPackets[i]->tnear <= inputPackets[i]->tfar,*inputPackets[i],context);
return;
}
@@ -206,8 +347,6 @@ namespace embree
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
const NearFarPreCompute pc(frusta.min_rdir);
StackItemMaskCoherent* stackPtr = stack + 1;
while (1) pop:
@@ -233,7 +372,7 @@ namespace embree
for (size_t i = 0; i < N; i++) maskK[i] = m_trav_active;
vfloat<Nx> dist;
const size_t m_node_hit = traverseCoherentStream(m_trav_active, packet, node, pc, frusta, maskK, dist);
const size_t m_node_hit = traverseCoherentStream(m_trav_active, packet, node, frusta, maskK, dist);
if (unlikely(m_node_hit == 0)) goto pop;
BVHNNodeTraverserStreamHitCoherent<N, Nx, types>::traverseAnyHit(cur, m_trav_active, vbool<Nx>((int)m_node_hit), (size_t*)maskK, stackPtr);
@@ -248,17 +387,8 @@ namespace embree
for (size_t i=0;i<N;i++)
if (node->child(i) == cur) { b = i; break; }
assert(b < N);
char *ptr = (char*)&node->lower_x + b*sizeof(float);
assert(cur == node->child(b));
const vfloat<K> minX = vfloat<K>(*(const float*)((const char*)ptr + pc.nearX));
const vfloat<K> minY = vfloat<K>(*(const float*)((const char*)ptr + pc.nearY));
const vfloat<K> minZ = vfloat<K>(*(const float*)((const char*)ptr + pc.nearZ));
const vfloat<K> maxX = vfloat<K>(*(const float*)((const char*)ptr + pc.farX));
const vfloat<K> maxY = vfloat<K>(*(const float*)((const char*)ptr + pc.farY));
const vfloat<K> maxZ = vfloat<K>(*(const float*)((const char*)ptr + pc.farZ));
m_trav_active = intersectAlignedNodePacket(packet, minX, minY, minZ, maxX, maxY, maxZ, m_trav_active);
m_trav_active = intersectAlignedNodePacket(packet, node, b, frusta.nf, m_trav_active);
}
/*! this is a leaf node */
@@ -278,62 +408,14 @@ namespace embree
const size_t m_isec = ((((size_t)1 << K)-1) << (i*K));
assert(m_isec & bits);
bits &= ~m_isec;
Packet &p = packet[i];
Packet<K,robust> &p = packet[i];
vbool<K> m_valid = p.min_dist <= p.max_dist;
vbool<K> m_hit = PrimitiveIntersector::occludedK(m_valid, *inputPackets[i], context, prim, num, lazy_node);
inputPackets[i]->geomID = select(m_hit & m_valid, vint<K>(zero), inputPackets[i]->geomID);
m_active &= ~((size_t)movemask(m_hit) << (i*K));
}
} // traversal + intersection
}
// =====================================================================================================
// =====================================================================================================
// =====================================================================================================
template<int N, int Nx, int K, int types, bool robust, typename PrimitiveIntersector>
void BVHNIntersectorStream<N, Nx, K, types, robust, PrimitiveIntersector>::intersect(BVH* __restrict__ bvh, RayK<K>** inputRays, size_t numTotalRays, IntersectContext* context)
{
#if ENABLE_COHERENT_STREAM_PATH == 1
if (unlikely(PrimitiveIntersector::validIntersectorK && !robust && isCoherent(context->user->flags)))
{
intersectCoherent(bvh, inputRays, numTotalRays, context);
return;
}
#endif
/* fallback to packets */
for (size_t i = 0; i < numTotalRays; i += K)
{
const vint<K> vi = vint<K>(int(i)) + vint<K>(step);
vbool<K> valid = vi < vint<K>(int(numTotalRays));
RayK<K>& ray = *(inputRays[i / K]);
valid &= ray.tnear <= ray.tfar;
bvh->scene->intersect(valid, ray, context);
}
}
template<int N, int Nx, int K, int types, bool robust, typename PrimitiveIntersector>
void BVHNIntersectorStream<N, Nx, K, types, robust, PrimitiveIntersector>::occluded(BVH* __restrict__ bvh, RayK<K>** inputRays, size_t numTotalRays, IntersectContext* context)
{
#if ENABLE_COHERENT_STREAM_PATH == 1
if (unlikely(PrimitiveIntersector::validIntersectorK && !robust && isCoherent(context->user->flags)))
{
occludedCoherent(bvh, inputRays, numTotalRays, context);
return;
}
#endif
/* fallback to packets */
for (size_t i = 0; i < numTotalRays; i += K)
{
const vint<K> vi = vint<K>(int(i)) + vint<K>(step);
vbool<K> valid = vi < vint<K>(int(numTotalRays));
RayK<K>& ray = *(inputRays[i / K]);
valid &= ray.tnear <= ray.tfar;
bvh->scene->occluded(valid, ray, context);
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -351,5 +433,39 @@ namespace embree
typedef ArrayIntersectorKStream<VSIZEX,QuadMvIntersectorKPluecker<4 COMMA VSIZEX COMMA true > > Quad4vIntersectorStreamPluecker;
typedef ArrayIntersectorKStream<VSIZEX,QuadMiIntersectorKPluecker<4 COMMA VSIZEX COMMA true > > Quad4iIntersectorStreamPluecker;
typedef ArrayIntersectorKStream<VSIZEX,ObjectIntersectorK<VSIZEX COMMA false > > ObjectIntersectorStream;
// =====================================================================================================
// =====================================================================================================
// =====================================================================================================
template<int N, int Nx, int K>
void BVHNIntersectorStreamPacketFallback<N, Nx, K>::intersect(Accel::Intersectors* __restrict__ This, RayK<K>** inputRays, size_t numTotalRays, IntersectContext* context)
{
/* fallback to packets */
for (size_t i = 0; i < numTotalRays; i += K)
{
const vint<K> vi = vint<K>(int(i)) + vint<K>(step);
vbool<K> valid = vi < vint<K>(int(numTotalRays));
RayK<K>& ray = *(inputRays[i / K]);
valid &= ray.tnear <= ray.tfar;
This->intersect(valid, ray, context);
}
}
template<int N, int Nx, int K>
void BVHNIntersectorStreamPacketFallback<N, Nx, K>::occluded(Accel::Intersectors* __restrict__ This, RayK<K>** inputRays, size_t numTotalRays, IntersectContext* context)
{
/* fallback to packets */
for (size_t i = 0; i < numTotalRays; i += K)
{
const vint<K> vi = vint<K>(int(i)) + vint<K>(step);
vbool<K> valid = vi < vint<K>(int(numTotalRays));
RayK<K>& ray = *(inputRays[i / K]);
valid &= ray.tnear <= ray.tfar;
This->occluded(valid, ray, context);
}
}
}
}
+44 -157
View File
@@ -20,8 +20,7 @@
#include "../common/ray.h"
#include "../common/stack_item.h"
#include "bvh_traverser1.h"
#define ENABLE_COHERENT_STREAM_PATH 1
#include "frustum.h"
namespace embree
{
@@ -204,53 +203,8 @@ namespace embree
// =============================================================================================
// =============================================================================================
struct Packet
{
Vec3vf<K> rdir;
Vec3vf<K> org_rdir;
vfloat<K> min_dist;
vfloat<K> max_dist;
};
struct Frusta
{
Vec3fa min_rdir;
Vec3fa max_rdir;
Vec3fa min_org_rdir;
Vec3fa max_org_rdir;
float min_dist;
float max_dist;
};
struct NearFarPreCompute
{
#if defined(__AVX512F__)
vint16 permX, permY, permZ;
#endif
size_t nearX, nearY, nearZ;
size_t farX, farY, farZ;
__forceinline NearFarPreCompute(const Vec3fa& dir)
{
#if defined(__AVX512F__)
/* 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
nearX = (dir.x < 0.0f) ? 1*sizeof(vfloat<N>) : 0*sizeof(vfloat<N>);
nearY = (dir.y < 0.0f) ? 3*sizeof(vfloat<N>) : 2*sizeof(vfloat<N>);
nearZ = (dir.z < 0.0f) ? 5*sizeof(vfloat<N>) : 4*sizeof(vfloat<N>);
farX = nearX ^ sizeof(vfloat<N>);
farY = nearY ^ sizeof(vfloat<N>);
farZ = nearZ ^ sizeof(vfloat<N>);
}
};
template<bool occluded>
__forceinline static size_t initPacketsAndFrusta(RayK<K>** inputPackets, const size_t numOctantRays, Packet* const packet, Frusta& frusta, bool &commonOctant)
__forceinline static size_t initPacketsAndFrusta(RayK<K>** inputPackets, const size_t numOctantRays, Packet<K,robust>* const packet, Frustum<N,Nx,K,robust>& frusta, bool &commonOctant)
{
const size_t numPackets = (numOctantRays+K-1)/K;
@@ -275,26 +229,25 @@ namespace embree
m_active |= (size_t)movemask(m_valid) << (i*K);
packet[i].min_dist = max(tnear, 0.0f);
packet[i].max_dist = select(m_valid, tfar, neg_inf);
tmp_min_dist = min(tmp_min_dist, packet[i].min_dist);
tmp_max_dist = max(tmp_max_dist, packet[i].max_dist);
vfloat<K> packet_min_dist = max(tnear, 0.0f);
vfloat<K> packet_max_dist = select(m_valid, tfar, neg_inf);
tmp_min_dist = min(tmp_min_dist, packet_min_dist);
tmp_max_dist = max(tmp_max_dist, packet_max_dist);
const Vec3vf<K>& org = inputPackets[i]->org;
const Vec3vf<K>& dir = inputPackets[i]->dir;
const Vec3vf<K> rdir = rcp_safe(dir);
const Vec3vf<K> org_rdir = org * rdir;
packet[i].rdir = rdir;
packet[i].org_rdir = org_rdir;
tmp_min_rdir = min(tmp_min_rdir, select(m_valid,rdir, Vec3vf<K>(pos_inf)));
tmp_max_rdir = max(tmp_max_rdir, select(m_valid,rdir, Vec3vf<K>(neg_inf)));
new (&packet[i]) Packet<K,robust>(org,dir,packet_min_dist,packet_max_dist);
tmp_min_rdir = min(tmp_min_rdir, select(m_valid,packet[i].rdir, Vec3vf<K>(pos_inf)));
tmp_max_rdir = max(tmp_max_rdir, select(m_valid,packet[i].rdir, Vec3vf<K>(neg_inf)));
tmp_min_org = min(tmp_min_org , select(m_valid,org , Vec3vf<K>(pos_inf)));
tmp_max_org = max(tmp_max_org , select(m_valid,org , Vec3vf<K>(neg_inf)));
}
m_active &= (numOctantRays == (8 * sizeof(size_t))) ? (size_t)-1 : (((size_t)1 << numOctantRays)-1);
const Vec3fa reduced_min_rdir( reduce_min(tmp_min_rdir.x),
reduce_min(tmp_min_rdir.y),
reduce_min(tmp_min_rdir.z) );
@@ -311,38 +264,26 @@ namespace embree
reduce_max(tmp_max_org.y),
reduce_max(tmp_max_org.z) );
const float frusta_min_dist = reduce_min(tmp_min_dist);
const float frusta_max_dist = reduce_max(tmp_max_dist);
commonOctant =
(reduced_max_rdir.x < 0.0f || reduced_min_rdir.x >= 0.0f) &&
(reduced_max_rdir.y < 0.0f || reduced_min_rdir.y >= 0.0f) &&
(reduced_max_rdir.z < 0.0f || reduced_min_rdir.z >= 0.0f);
const Vec3fa frusta_min_rdir = select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_min_rdir, reduced_max_rdir);
const Vec3fa frusta_max_rdir = select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_max_rdir, reduced_min_rdir);
const Vec3fa frusta_min_org_rdir = frusta_min_rdir * select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_max_origin, reduced_min_origin);
const Vec3fa frusta_max_org_rdir = frusta_max_rdir * select(ge_mask(reduced_min_rdir, Vec3fa(zero)), reduced_min_origin, reduced_max_origin);
frusta.min_rdir = frusta_min_rdir;
frusta.max_rdir = frusta_max_rdir;
frusta.min_org_rdir = frusta_min_org_rdir;
frusta.max_org_rdir = frusta_max_org_rdir;
frusta.min_dist = frusta_min_dist;
frusta.max_dist = frusta_max_dist;
const float frusta_min_dist = reduce_min(tmp_min_dist);
const float frusta_max_dist = reduce_max(tmp_max_dist);
frusta.init(reduced_min_origin,reduced_max_origin,
reduced_min_rdir,reduced_max_rdir,
frusta_min_dist,frusta_max_dist);
return m_active;
}
__forceinline static size_t intersectAlignedNodePacket(const Packet* const packet,
const vfloat<K>& minX,
const vfloat<K>& minY,
const vfloat<K>& minZ,
const vfloat<K>& maxX,
const vfloat<K>& maxY,
const vfloat<K>& maxZ,
__forceinline static size_t intersectAlignedNodePacket(const Packet<K,robust>* const packet,
const AlignedNode* __restrict__ const node,
const size_t bid,
const NearFarPreCompute& nf,
const size_t m_active)
{
assert(m_active);
@@ -351,92 +292,31 @@ namespace embree
size_t m_trav_active = 0;
for (size_t i = startPacketID; i <= endPacketID; i++)
{
//STAT3(normal.trav_nodes,1,1,1);
const Packet& p = packet[i];
const vfloat<K> tminX = msub(minX, p.rdir.x, p.org_rdir.x);
const vfloat<K> tminY = msub(minY, p.rdir.y, p.org_rdir.y);
const vfloat<K> tminZ = msub(minZ, p.rdir.z, p.org_rdir.z);
const vfloat<K> tmaxX = msub(maxX, p.rdir.x, p.org_rdir.x);
const vfloat<K> tmaxY = msub(maxY, p.rdir.y, p.org_rdir.y);
const vfloat<K> tmaxZ = msub(maxZ, p.rdir.z, p.org_rdir.z);
const vfloat<K> tmin = maxi(tminX, tminY, tminZ, p.min_dist);
const vfloat<K> tmax = mini(tmaxX, tmaxY, tmaxZ, p.max_dist);
const vbool<K> vmask = tmin <= tmax;
const size_t m_hit = movemask(vmask);
const size_t m_hit = packet[i].template intersect<N>(node,bid,nf);
m_trav_active |= m_hit << (i*K);
}
return m_trav_active;
}
__forceinline static size_t traverseCoherentStream(const size_t m_trav_active,
Packet* const packet,
Packet<K,robust>* const packet,
const AlignedNode* __restrict__ const node,
const NearFarPreCompute& pc,
const Frusta& frusta,
const Frustum<N,Nx,K,robust>& frusta,
size_t* const maskK,
vfloat<Nx>& dist)
{
/* interval-based culling test */
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + pc.nearX));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + pc.nearY));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + pc.nearZ));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + pc.farX));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + pc.farY));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + pc.farZ));
const vfloat<Nx> fminX = msub(bminX, vfloat<Nx>(frusta.min_rdir.x), vfloat<Nx>(frusta.min_org_rdir.x));
const vfloat<Nx> fminY = msub(bminY, vfloat<Nx>(frusta.min_rdir.y), vfloat<Nx>(frusta.min_org_rdir.y));
const vfloat<Nx> fminZ = msub(bminZ, vfloat<Nx>(frusta.min_rdir.z), vfloat<Nx>(frusta.min_org_rdir.z));
const vfloat<Nx> fmaxX = msub(bmaxX, vfloat<Nx>(frusta.max_rdir.x), vfloat<Nx>(frusta.max_org_rdir.x));
const vfloat<Nx> fmaxY = msub(bmaxY, vfloat<Nx>(frusta.max_rdir.y), vfloat<Nx>(frusta.max_org_rdir.y));
const vfloat<Nx> fmaxZ = msub(bmaxZ, vfloat<Nx>(frusta.max_rdir.z), vfloat<Nx>(frusta.max_org_rdir.z));
const vfloat<Nx> fmin = maxi(fminX, fminY, fminZ, vfloat<Nx>(frusta.min_dist));
const vfloat<Nx> fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat<Nx>(frusta.max_dist));
const vbool<Nx> vmask_node_hit = fmin <= fmax;
//STAT3(normal.trav_nodes,1,1,1);
size_t m_node_hit = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
// ==================
size_t m_node_hit = frusta.intersect(node,dist);
const size_t first_index = __bsf(m_trav_active);
const size_t first_packetID = first_index / K;
const size_t first_rayID = first_index % K;
size_t m_first_hit = packet[first_packetID].template intersectRay<N,Nx>(node,first_rayID,frusta.nf);
Packet &p = packet[first_packetID];
//STAT3(normal.trav_nodes,1,1,1);
const vfloat<Nx> rminX = msub(bminX, vfloat<Nx>(p.rdir.x[first_rayID]), vfloat<Nx>(p.org_rdir.x[first_rayID]));
const vfloat<Nx> rminY = msub(bminY, vfloat<Nx>(p.rdir.y[first_rayID]), vfloat<Nx>(p.org_rdir.y[first_rayID]));
const vfloat<Nx> rminZ = msub(bminZ, vfloat<Nx>(p.rdir.z[first_rayID]), vfloat<Nx>(p.org_rdir.z[first_rayID]));
const vfloat<Nx> rmaxX = msub(bmaxX, vfloat<Nx>(p.rdir.x[first_rayID]), vfloat<Nx>(p.org_rdir.x[first_rayID]));
const vfloat<Nx> rmaxY = msub(bmaxY, vfloat<Nx>(p.rdir.y[first_rayID]), vfloat<Nx>(p.org_rdir.y[first_rayID]));
const vfloat<Nx> rmaxZ = msub(bmaxZ, vfloat<Nx>(p.rdir.z[first_rayID]), vfloat<Nx>(p.org_rdir.z[first_rayID]));
const vfloat<Nx> rmin = maxi(rminX, rminY, rminZ, vfloat<Nx>(p.min_dist[first_rayID]));
const vfloat<Nx> rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat<Nx>(p.max_dist[first_rayID]));
const vbool<Nx> vmask_first_hit = rmin <= rmax;
size_t m_first_hit = movemask(vmask_first_hit) & (((size_t)1 << N)-1);
// ==================
/* this causes a traversal order dependence with respect to the order of rays within the stream */
//dist = select(vmask_first_hit, rmin, fmin);
/* this is independent of the ordering of rays */
dist = fmin;
/* this make traversal independent of the ordering of rays */
size_t m_node = m_node_hit ^ m_first_hit;
while(unlikely(m_node))
{
const size_t b = __bscf(m_node);
const vfloat<K> minX = vfloat<K>(bminX[b]);
const vfloat<K> minY = vfloat<K>(bminY[b]);
const vfloat<K> minZ = vfloat<K>(bminZ[b]);
const vfloat<K> maxX = vfloat<K>(bmaxX[b]);
const vfloat<K> maxY = vfloat<K>(bmaxY[b]);
const vfloat<K> maxZ = vfloat<K>(bmaxZ[b]);
const size_t m_current = m_trav_active & intersectAlignedNodePacket(packet, minX, minY, minZ, maxX, maxY, maxZ, m_trav_active);
const size_t m_current = m_trav_active & intersectAlignedNodePacket(packet, node, b, frusta.nf, m_trav_active);
m_node_hit ^= m_current ? (size_t)0 : ((size_t)1 << b);
maskK[b] = m_current;
}
@@ -449,13 +329,20 @@ namespace embree
// =============================================================================================
// =============================================================================================
static void intersectCoherent(BVH* bvh, RayK<K>** inputRays, size_t numValidStreams, IntersectContext* context);
static void occludedCoherent(BVH* bvh, RayK<K>** inputRays, size_t numValidStreams, IntersectContext* context);
public:
static void intersect(BVH* bvh, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
static void occluded (BVH* bvh, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
static void intersect(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
static void occluded (Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
};
/*! BVH ray stream intersector with direct fallback to packets. */
template<int N, int Nx, int K>
class BVHNIntersectorStreamPacketFallback
{
public:
static void intersect(Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
static void occluded (Accel::Intersectors* This, RayK<K>** inputRays, size_t numRays, IntersectContext* context);
};
}
}
@@ -20,6 +20,13 @@ namespace embree
{
namespace isa
{
////////////////////////////////////////////////////////////////////////////////
/// General BVHIntersectorStreamPacketFallback Intersector
////////////////////////////////////////////////////////////////////////////////
DEFINE_INTERSECTORN(BVH4IntersectorStreamPacketFallback,BVHNIntersectorStreamPacketFallback<SIMD_MODE(4) COMMA VSIZEX>);
////////////////////////////////////////////////////////////////////////////////
/// BVH4IntersectorStream Definitions
////////////////////////////////////////////////////////////////////////////////
@@ -20,6 +20,12 @@ namespace embree
{
namespace isa
{
////////////////////////////////////////////////////////////////////////////////
/// General BVHIntersectorStreamPacketFallback Intersector
////////////////////////////////////////////////////////////////////////////////
DEFINE_INTERSECTORN(BVH8IntersectorStreamPacketFallback,BVHNIntersectorStreamPacketFallback<SIMD_MODE(8) COMMA VSIZEX>);
////////////////////////////////////////////////////////////////////////////////
/// BVH8IntersectorStream Definitions
////////////////////////////////////////////////////////////////////////////////
+161 -216
View File
@@ -17,197 +17,155 @@
#include "bvh_intersector_stream_filters.h"
#include "bvh_intersector_stream.h"
#define FORCE_STREAM_OCCLUSION_KERNEL 1
namespace embree
{
namespace isa
{
static const size_t MAX_RAYS_PER_OCTANT = 8*sizeof(size_t);
static_assert(MAX_RAYS_PER_OCTANT <= MAX_INTERNAL_STREAM_SIZE, "maximal internal stream size exceeded");
MAYBE_UNUSED static const size_t MAX_PACKET_STREAM_SIZE = MAX_INTERNAL_STREAM_SIZE / VSIZEX;
__forceinline void RayStreamFilter::filterAOS(Scene* scene, RTCRay* _rayN, size_t N, size_t stride, IntersectContext* context, bool intersect)
{
#if 1
RayStreamAOS rayN(_rayN);
for (size_t i = 0; i < N; i += VSIZEX)
{
const vintx vi = vintx(int(i)) + vintx(step);
vboolx valid = vi < vintx(int(N));
const vintx offset = vi * int(stride);
RayK<VSIZEX> ray = rayN.getRayByOffset<VSIZEX>(valid, offset);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersect(valid, ray, context);
else
scene->occluded(valid, ray, context);
rayN.setHitByOffset<VSIZEX>(valid, offset, ray, intersect);
}
/* use fast path for coherent ray mode */
#if FORCE_STREAM_OCCLUSION_KERNEL == 1
if (1)
#else
Ray* __restrict__ rayN = (Ray*)_rayN;
__aligned(64) Ray* octants[8][MAX_RAYS_PER_OCTANT];
unsigned int rays_in_octant[8];
for (size_t i=0;i<8;i++) rays_in_octant[i] = 0;
size_t inputRayID = 0;
while(1)
{
int cur_octant = -1;
/* sort rays into octants */
for (;inputRayID<N;)
{
Ray &ray = *(Ray*)((char*)rayN + inputRayID * stride);
/* filter out invalid rays */
if (unlikely(ray.tnear > ray.tfar)) { inputRayID++; continue; }
if (unlikely(!intersect && ray.geomID == 0)) { inputRayID++; continue; } // ignore already occluded rays
#if defined(EMBREE_IGNORE_INVALID_RAYS)
if (unlikely(!ray.valid())) { inputRayID++; continue; }
if (unlikely(isCoherent(context->user->flags)))
#endif
{
__aligned(64) RayK<VSIZEX> rays[MAX_PACKET_STREAM_SIZE];
__aligned(64) RayK<VSIZEX>* rayPtrs[MAX_PACKET_STREAM_SIZE];
const unsigned int octantID = movemask(vfloat4(ray.dir) < 0.0f) & 0x7;
for (size_t i = 0; i < N; i += MAX_INTERNAL_STREAM_SIZE)
{
const size_t size = min(N - i, MAX_INTERNAL_STREAM_SIZE);
assert(octantID < 8);
octants[octantID][rays_in_octant[octantID]++] = &ray;
inputRayID++;
if (unlikely(rays_in_octant[octantID] == MAX_RAYS_PER_OCTANT))
/* convert from AOS to SOA */
for (size_t j = 0; j < size; j += VSIZEX)
{
cur_octant = octantID;
break;
const vintx vij = vintx(int(i+j)) + vintx(step);
const vboolx valid = vij < vintx(int(N));
const vintx offset = vij * int(stride);
const size_t packetIndex = j / VSIZEX;
RayK<VSIZEX> ray = rayN.getRayByOffset(valid, offset);
ray.tnear = select(valid, ray.tnear, zero);
ray.tfar = select(valid, ray.tfar, neg_inf);
rays[packetIndex] = ray;
rayPtrs[packetIndex] = &rays[packetIndex]; // rayPtrs might get reordered for occludedN
}
/* trace stream */
if (intersect)
scene->intersectors.intersectN(rayPtrs, size, context);
else
scene->intersectors.occludedN(rayPtrs, size, context);
/* convert from SOA to AOS */
for (size_t j = 0; j < size; j += VSIZEX)
{
const vintx vij = vintx(int(i+j)) + vintx(step);
const vboolx valid = vij < vintx(int(N));
const vintx offset = vij * int(stride);
const size_t packetIndex = j / VSIZEX;
rayN.setHitByOffset(valid, offset, rays[packetIndex], intersect);
}
}
/* need to flush rays in octant ? */
if (unlikely(cur_octant == -1))
for (int i=0;i<8;i++)
if (rays_in_octant[i])
{
cur_octant = i;
break;
}
/* all rays traced ? */
if (unlikely(cur_octant == -1))
break;
Ray** rays = &octants[cur_octant][0];
const size_t numOctantRays = rays_in_octant[cur_octant];
/* special codepath for very small number of rays per octant */
if (numOctantRays == 1)
{
if (intersect) scene->intersect((RTCRay&)*rays[0],context);
else scene->occluded ((RTCRay&)*rays[0],context);
}
/* codepath for large number of rays per octant */
else
{
/* incoherent ray stream code path */
if (intersect) scene->intersectN((RTCRay**)rays,numOctantRays,context);
else scene->occludedN ((RTCRay**)rays,numOctantRays,context);
}
rays_in_octant[cur_octant] = 0;
}
else
{
static const size_t MAX_RAYS_PER_OCTANT = VSIZEX;
#endif
/* fallback to packets */
for (size_t i=0; i<N; i+=VSIZEX)
{
const vintx vi = vintx(int(i)) + vintx(step);
vboolx valid = vi < vintx(int(N));
const vintx offset = vi * int(stride);
RayK<VSIZEX> ray = rayN.getRayByOffset(valid, offset);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersectors.intersect(valid, ray, context);
else
scene->intersectors.occluded(valid, ray, context);
rayN.setHitByOffset(valid, offset, ray, intersect);
}
}
}
__forceinline void RayStreamFilter::filterAOP(Scene* scene, RTCRay** _rayN, size_t N, IntersectContext* context, bool intersect)
{
#if 1
/* fallback to packets */
RayStreamAOP rayN(_rayN);
for (size_t i = 0; i < N; i += VSIZEX)
/* use fast path for coherent ray mode */
if (unlikely(isCoherent(context->user->flags)))
{
const vintx vi = vintx(int(i)) + vintx(step);
vboolx valid = vi < vintx(int(N));
__aligned(64) RayK<VSIZEX> rays[MAX_PACKET_STREAM_SIZE];
__aligned(64) RayK<VSIZEX>* rayPtrs[MAX_PACKET_STREAM_SIZE];
RayK<VSIZEX> ray = rayN.getRayByIndex<VSIZEX>(valid, i);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersect(valid, ray, context);
else
scene->occluded(valid, ray, context);
rayN.setHitByIndex<VSIZEX>(valid, i, ray, intersect);
}
#else
Ray** __restrict__ rayN = (Ray**)_rayN;
__aligned(64) Ray* octants[8][MAX_RAYS_PER_OCTANT];
unsigned int rays_in_octant[8];
for (size_t i=0;i<8;i++) rays_in_octant[i] = 0;
size_t inputRayID = 0;
while(1)
{
int cur_octant = -1;
/* sort rays into octants */
for (;inputRayID<N;)
for (size_t i = 0; i < N; i += MAX_INTERNAL_STREAM_SIZE)
{
Ray &ray = *rayN[inputRayID];
/* filter out invalid rays */
if (unlikely(ray.tnear > ray.tfar)) { inputRayID++; continue; }
if (unlikely(!intersect && ray.geomID == 0)) { inputRayID++; continue; } // ignore already occluded rays
const size_t size = min(N - i, MAX_INTERNAL_STREAM_SIZE);
#if defined(EMBREE_IGNORE_INVALID_RAYS)
if (unlikely(!ray.valid())) { inputRayID++; continue; }
#endif
const unsigned int octantID = movemask(vfloat4(ray.dir) < 0.0f) & 0x7;
assert(octantID < 8);
octants[octantID][rays_in_octant[octantID]++] = &ray;
inputRayID++;
if (unlikely(rays_in_octant[octantID] == MAX_RAYS_PER_OCTANT))
/* convert from AOP to SOA */
for (size_t j = 0; j < size; j += VSIZEX)
{
cur_octant = octantID;
break;
const vintx vij = vintx(int(i+j)) + vintx(step);
const vboolx valid = vij < vintx(int(N));
const size_t packetIndex = j / VSIZEX;
RayK<VSIZEX> ray = rayN.getRayByIndex(valid, i+j);
ray.tnear = select(valid, ray.tnear, zero);
ray.tfar = select(valid, ray.tfar, neg_inf);
rays[packetIndex] = ray;
rayPtrs[packetIndex] = &rays[packetIndex]; // rayPtrs might get reordered for occludedN
}
/* trace stream */
if (intersect)
scene->intersectors.intersectN(rayPtrs, size, context);
else
scene->intersectors.occludedN(rayPtrs, size, context);
/* convert from SOA to AOP */
for (size_t j = 0; j < size; j += VSIZEX)
{
const vintx vij = vintx(int(i+j)) + vintx(step);
const vboolx valid = vij < vintx(int(N));
const size_t packetIndex = j / VSIZEX;
rayN.setHitByIndex(valid, i+j, rays[packetIndex], intersect);
}
}
/* need to flush rays in octant ? */
if (unlikely(cur_octant == -1))
for (int i=0;i<8;i++)
if (rays_in_octant[i])
{
cur_octant = i;
break;
}
/* all rays traced ? */
if (unlikely(cur_octant == -1))
break;
Ray** rays = &octants[cur_octant][0];
const size_t numOctantRays = rays_in_octant[cur_octant];
/* special codepath for very small number of rays per octant */
if (numOctantRays == 1)
{
if (intersect) scene->intersect((RTCRay&)*rays[0],context);
else scene->occluded ((RTCRay&)*rays[0],context);
}
/* codepath for large number of rays per octant */
else
{
/* incoherent ray stream code path */
if (intersect) scene->intersectN((RTCRay**)rays,numOctantRays,context);
else scene->occludedN ((RTCRay**)rays,numOctantRays,context);
}
rays_in_octant[cur_octant] = 0;
}
else
{
/* fallback to packets */
for (size_t i = 0; i < N; i += VSIZEX)
{
const vintx vi = vintx(int(i)) + vintx(step);
vboolx valid = vi < vintx(int(N));
#endif
RayK<VSIZEX> ray = rayN.getRayByIndex(valid, i);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersectors.intersect(valid, ray, context);
else
scene->intersectors.occluded(valid, ray, context);
rayN.setHitByIndex(valid, i, ray, intersect);
}
}
}
__forceinline void RayStreamFilter::filterSOA(Scene* scene, char* rayData, size_t N, size_t numPackets, size_t stride, IntersectContext* context, bool intersect)
@@ -220,45 +178,40 @@ namespace embree
!rayDataAlignment &&
!offsetAlignment))
{
#if defined(__AVX__) && ENABLE_COHERENT_STREAM_PATH == 1
/* all valid accels need to have a intersectN/occludedN */
if (unlikely(isCoherent(context->user->flags) && !scene->isRobust() && scene->accels.validIsecN()))
if (unlikely(isCoherent(context->user->flags)))
{
static const size_t MAX_COHERENT_RAY_PACKETS = MAX_RAYS_PER_OCTANT / VSIZEX;
__aligned(64) RayK<VSIZEX>* rays_ptr[MAX_RAYS_PER_OCTANT / VSIZEX];
size_t numPacketsInOctant = 0;
__aligned(64) RayK<VSIZEX>* rayPtrs[MAX_INTERNAL_STREAM_SIZE / VSIZEX];
size_t packetIndex = 0;
for (size_t i = 0; i < numPackets; i++)
{
const size_t offset = i * stride;
RayK<VSIZEX>& ray = *(RayK<VSIZEX>*)(rayData + offset);
rays_ptr[numPacketsInOctant++] = &ray;
rayPtrs[packetIndex++] = &ray;
/* trace as stream */
if (unlikely(numPacketsInOctant == MAX_COHERENT_RAY_PACKETS))
if (unlikely(packetIndex == MAX_PACKET_STREAM_SIZE))
{
const size_t size = numPacketsInOctant*VSIZEX;
const size_t size = packetIndex*VSIZEX;
if (intersect)
scene->intersectN((void**)rays_ptr, size, context);
scene->intersectors.intersectN(rayPtrs, size, context);
else
scene->occludedN((void**)rays_ptr, size, context);
numPacketsInOctant = 0;
scene->intersectors.occludedN(rayPtrs, size, context);
packetIndex = 0;
}
}
/* flush remaining packets */
if (unlikely(numPacketsInOctant))
if (unlikely(packetIndex > 0))
{
const size_t size = numPacketsInOctant*VSIZEX;
const size_t size = packetIndex*VSIZEX;
if (intersect)
scene->intersectN((void**)rays_ptr, size, context);
scene->intersectors.intersectN(rayPtrs, size, context);
else
scene->occludedN((void**)rays_ptr, size, context);
scene->intersectors.occludedN(rayPtrs, size, context);
}
}
else
#endif
{
/* fallback to packets */
for (size_t i = 0; i < numPackets; i++)
@@ -268,37 +221,34 @@ namespace embree
const vboolx valid = ray.tnear <= ray.tfar;
if (intersect)
scene->intersect(valid, ray, context);
scene->intersectors.intersect(valid, ray, context);
else
scene->occluded(valid, ray, context);
scene->intersectors.occluded(valid, ray, context);
}
}
}
else
{
/* this is a very slow fallback path but it's extremely unlikely to be hit */
/* fallback to packets for arbitrary packet size and alignment */
for (size_t i = 0; i < numPackets; i++)
{
const size_t offset = i * stride;
RayPacketSOA rayN(rayData + offset, N);
RayK<VSIZEX> ray;
{
const size_t offsetN = i * stride;
RayPacketSOA rayN(rayData + offsetN, N);
for (size_t j = 0; j < N; j++)
for (size_t j = 0; j < N; j += VSIZEX)
{
/* invalidate all lanes */
ray.tnear = 0.0f;
ray.tfar = neg_inf;
const size_t offset = j * sizeof(float);
vboolx valid = (vintx(int(j)) + vintx(step)) < vintx(int(N));
/* extract single ray and copy data to first packet lane */
rayN.getRayByIndex(j, ray, 0);
const vboolx valid = ray.tnear <= ray.tfar;
RayK<VSIZEX> ray = rayN.getRayByOffset(valid, offset);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersect(valid, ray, context);
scene->intersectors.intersect(valid, ray, context);
else
scene->occluded(valid, ray, context);
scene->intersectors.occluded(valid, ray, context);
rayN.setHitByIndex(j, ray, 0, intersect);
rayN.setHitByOffset(valid, offset, ray, intersect);
}
}
}
@@ -309,70 +259,65 @@ namespace embree
RayStreamSOP& rayN = *(RayStreamSOP*)&_rayN;
/* use fast path for coherent ray mode */
#if defined(__AVX__) && ENABLE_COHERENT_STREAM_PATH == 1
/* all valid accels need to have a intersectN/occludedN */
if (unlikely(isCoherent(context->user->flags) && !scene->isRobust() && scene->accels.validIsecN()))
if (unlikely(isCoherent(context->user->flags)))
{
static const size_t MAX_COHERENT_RAY_PACKETS = MAX_RAYS_PER_OCTANT / VSIZEX;
__aligned(64) RayK<VSIZEX> rays[MAX_PACKET_STREAM_SIZE];
__aligned(64) RayK<VSIZEX>* rayPtrs[MAX_PACKET_STREAM_SIZE];
__aligned(64) RayK<VSIZEX> rays[MAX_COHERENT_RAY_PACKETS];
__aligned(64) RayK<VSIZEX>* rays_ptr[MAX_COHERENT_RAY_PACKETS];
for (size_t i = 0; i < N; i += MAX_RAYS_PER_OCTANT)
for (size_t i = 0; i < N; i += MAX_INTERNAL_STREAM_SIZE)
{
const size_t size = min(N - i, MAX_RAYS_PER_OCTANT);
const size_t size = min(N - i, MAX_INTERNAL_STREAM_SIZE);
/* convert from SOP to SOA */
for (size_t j = 0; j < size; j += VSIZEX)
{
const vintx vij = vintx(int(i+j)) + vintx(step);
const vboolx valid = vij < vintx(int(N));
const size_t offset = sizeof(float) * (i+j);
const size_t packet_index = j / VSIZEX;
const size_t offset = (i+j) * sizeof(float);
const size_t packetIndex = j / VSIZEX;
RayK<VSIZEX> ray = rayN.getRayByOffset(valid, offset);
ray.tnear = select(valid, ray.tnear, zero);
ray.tfar = select(valid, ray.tfar, neg_inf);
rays[packet_index] = ray;
rays_ptr[packet_index] = &rays[packet_index]; // rays_ptr might get reordered for occludedN
rays[packetIndex] = ray;
rayPtrs[packetIndex] = &rays[packetIndex]; // rayPtrs might get reordered for occludedN
}
/* trace stream */
if (intersect)
scene->intersectN((void**)rays_ptr, size, context);
scene->intersectors.intersectN(rayPtrs, size, context);
else
scene->occludedN((void**)rays_ptr, size, context);
scene->intersectors.occludedN(rayPtrs, size, context);
/* convert from SOA to SOP */
for (size_t j = 0; j < size; j += VSIZEX)
{
const vintx vij = vintx(int(i+j)) + vintx(step);
const vboolx valid = vij < vintx(int(N));
const size_t offset = sizeof(float) * (i+j);
const size_t packet_index = j / VSIZEX;
const size_t offset = (i+j) * sizeof(float);
const size_t packetIndex = j / VSIZEX;
rayN.setHitByOffset(valid, offset, rays[packet_index], intersect);
rayN.setHitByOffset(valid, offset, rays[packetIndex], intersect);
}
}
}
else
#endif
{
/* fallback to packets */
for (size_t i = 0; i < N; i += VSIZEX)
{
const vintx vi = vintx(int(i)) + vintx(step);
vboolx valid = vi < vintx(int(N));
const size_t offset = sizeof(float) * i;
const size_t offset = i * sizeof(float);
RayK<VSIZEX> ray = rayN.getRayByOffset(valid, offset);
valid &= ray.tnear <= ray.tfar;
if (intersect)
scene->intersect(valid, ray, context);
scene->intersectors.intersect(valid, ray, context);
else
scene->occluded(valid, ray, context);
scene->intersectors.occluded(valid, ray, context);
rayN.setHitByOffset(valid, offset, ray, intersect);
}
+1 -1
View File
@@ -106,7 +106,7 @@ namespace embree
int pos[4] = { pos0,pos1,pos2,pos3 };
const size_t mbd = BVH4::maxBuildDepth;
vbool4 valid = vint4(int(depth+1))+cdepth <= vint4(mbd); // only select swaps that fulfill depth constraints
valid &= vint4(c2) != vint4(step);
valid &= vint4(int(c2)) != vint4(step);
if (none(valid)) continue;
size_t c1 = select_min(valid,area0123);
float area = area0123[c1];
+198 -4
View File
@@ -30,6 +30,8 @@ namespace embree
/*! Helper functions for fast sorting using AVX512 instructions. */
#if defined(__AVX512F__)
/* KNL code path */
__forceinline static void isort_update(vfloat16 &dist, vllong8 &ptr, const vfloat16 &d, const vllong8 &p)
{
const vfloat16 dist_shift = align_shift_right<15>(dist,dist);
@@ -230,19 +232,196 @@ namespace embree
vuint16::storeu(stackPtr + 4,stackElementB1);
/* increase stack pointer */
stackPtr += hits-1;
}
/* SKX code path */
#if defined(__AVX512VL__)
template<int N>
__forceinline static void isort_update(vfloat<N> &dist, vint<N> &ptr, const vfloat<N> &d, const vint<N> &p)
{
const vfloat<N> dist_shift = align_shift_right<N-1>(dist,dist);
const vint<N> ptr_shift = align_shift_right<N-1>(ptr,ptr);
const vboolf<N> m_geq = d >= dist;
const vboolf<N> m_geq_shift = m_geq << 1;
dist = select(m_geq,d,dist);
ptr = select(m_geq,p,ptr);
dist = select(m_geq_shift,dist_shift,dist);
ptr = select(m_geq_shift,ptr_shift,ptr);
}
template<int N>
__forceinline static void isort_quick_update(vfloat<N> &dist, vint<N> &ptr, const vfloat<N> &d, const vint<N> &p)
{
dist = align_shift_right<N-1>(dist,permute(d,vint<N>(zero)));
ptr = align_shift_right<N-1>(ptr,permute(p,vint<N>(zero)));
}
template<int N, int Nx, int types, class NodeRef, class BaseNode>
static __forceinline void traverseClosestHitAVX512VL(NodeRef& cur,
size_t mask,
const vfloat<Nx>& tNear,
StackItemT<NodeRef>*& stackPtr,
StackItemT<NodeRef>* stackEnd)
{
assert(mask != 0);
const BaseNode* node = cur.baseNode(types);
vint<N> children( step );
children = vint<N>::compact((int)mask,children);
vfloat<N> distance = tNear;
distance = vfloat<N>::compact((int)mask,distance,tNear);
cur = node->child((unsigned int)toScalar(children));
cur.prefetch(types);
mask &= mask-1;
if (likely(mask == 0)) return;
/* 2 hits: order A0 B0 */
const vint<N> c0(children);
const vfloat<N> d0(distance);
children = align_shift_right<1>(children,children);
distance = align_shift_right<1>(distance,distance);
const vint<N> c1(children);
const vfloat<N> d1(distance);
cur = node->child((unsigned int)toScalar(children));
cur.prefetch(types);
/* a '<' keeps the order for equal distances, scenes like powerplant largely benefit from it */
const vboolf<N> m_dist = d0 < d1;
const vfloat<N> dist_A0 = select(m_dist, d0, d1);
const vfloat<N> dist_B0 = select(m_dist, d1, d0);
const vint<N> ptr_A0 = select(vboolf<N>(m_dist), c0, c1);
const vint<N> ptr_B0 = select(vboolf<N>(m_dist), c1, c0);
mask &= mask-1;
if (likely(mask == 0)) {
cur = node->child((unsigned int)toScalar(ptr_A0));
stackPtr[0].ptr = node->child((unsigned int)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 vint<N> c2(children);
const vfloat<N> d2(distance);
cur = node->child((unsigned int)toScalar(children));
cur.prefetch(types);
const vboolf<N> m_dist1 = dist_A0 <= d2;
const vfloat<N> dist_tmp_B1 = select(m_dist1, d2, dist_A0);
const vint<N> ptr_A1 = select(vboolf<N>(m_dist1), ptr_A0, c2);
const vint<N> ptr_tmp_B1 = select(vboolf<N>(m_dist1), c2, ptr_A0);
const vboolf<N> m_dist2 = dist_B0 <= dist_tmp_B1;
const vfloat<N> dist_B1 = select(m_dist2, dist_B0 , dist_tmp_B1);
const vfloat<N> dist_C1 = select(m_dist2, dist_tmp_B1, dist_B0);
const vint<N> ptr_B1 = select(vboolf<N>(m_dist2), ptr_B0, ptr_tmp_B1);
const vint<N> ptr_C1 = select(vboolf<N>(m_dist2), ptr_tmp_B1, ptr_B0);
mask &= mask-1;
if (likely(mask == 0)) {
cur = node->child((unsigned int)toScalar(ptr_A1));
stackPtr[0].ptr = node->child((unsigned int)toScalar(ptr_C1));
*(float*)&stackPtr[0].dist = toScalar(dist_C1);
stackPtr[1].ptr = node->child((unsigned int)toScalar(ptr_B1));
*(float*)&stackPtr[1].dist = toScalar(dist_B1);
stackPtr+=2;
return;
}
/* 4 hits: order A2 B2 C2 D2 */
const vfloat<N> dist_A1 = select(m_dist1, dist_A0, d2);
children = align_shift_right<1>(children,children);
distance = align_shift_right<1>(distance,distance);
const vint<N> c3(children);
const vfloat<N> d3(distance);
cur = node->child((unsigned int)toScalar(children));
cur.prefetch(types);
const vboolf<N> m_dist3 = dist_A1 <= d3;
const vfloat<N> dist_tmp_B2 = select(m_dist3, d3, dist_A1);
const vint<N> ptr_A2 = select(vboolf<N>(m_dist3), ptr_A1, c3);
const vint<N> ptr_tmp_B2 = select(vboolf<N>(m_dist3), c3, ptr_A1);
const vboolf<N> m_dist4 = dist_B1 <= dist_tmp_B2;
const vfloat<N> dist_B2 = select(m_dist4, dist_B1 , dist_tmp_B2);
const vfloat<N> dist_tmp_C2 = select(m_dist4, dist_tmp_B2, dist_B1);
const vint<N> ptr_B2 = select(vboolf<N>(m_dist4), ptr_B1, ptr_tmp_B2);
const vint<N> ptr_tmp_C2 = select(vboolf<N>(m_dist4), ptr_tmp_B2, ptr_B1);
const vboolf<N> m_dist5 = dist_C1 <= dist_tmp_C2;
const vfloat<N> dist_C2 = select(m_dist5, dist_C1 , dist_tmp_C2);
const vfloat<N> dist_D2 = select(m_dist5, dist_tmp_C2, dist_C1);
const vint<N> ptr_C2 = select(vboolf<N>(m_dist5), ptr_C1, ptr_tmp_C2);
const vint<N> ptr_D2 = select(vboolf<N>(m_dist5), ptr_tmp_C2, ptr_C1);
mask &= mask-1;
if (likely(mask == 0)) {
cur = node->child((unsigned int)toScalar(ptr_A2));
stackPtr[0].ptr = node->child((unsigned int)toScalar(ptr_D2));
*(float*)&stackPtr[0].dist = toScalar(dist_D2);
stackPtr[1].ptr = node->child((unsigned int)toScalar(ptr_C2));
*(float*)&stackPtr[1].dist = toScalar(dist_C2);
stackPtr[2].ptr = node->child((unsigned int)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 vfloat<N> dist_A2 = select(m_dist3, dist_A1, d3);
vfloat<N> dist(neg_inf);
vint<N> 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 = node->child((unsigned int)toScalar(children));
cur.prefetch(types);
const vfloat<N> new_dist(permute(distance,vint<N>(zero)));
const vint<N> new_ptr(permute(children,vint<N>(zero)));
mask &= mask-1;
isort_update(dist,ptr,new_dist,new_ptr);
} while(mask);
#if 0
for (size_t i=0;i<hits-1;i++)
{
stackPtr->ptr = toScalar(ptr);
stackPtr->ptr = node->child((unsigned int)toScalar(ptr));
*(float*)&stackPtr->dist = toScalar(dist);
dist = align_shift_right<1>(dist,dist);
ptr = align_shift_right<1>(ptr,ptr);
stackPtr++;
}
cur = toScalar(ptr);
#endif
cur = node->child((unsigned int)toScalar(ptr));
}
#endif
#endif
@@ -263,8 +442,16 @@ namespace embree
StackItemT<NodeRef>* stackEnd)
{
assert(mask != 0);
#if defined(__AVX512F__) && 1
#if defined(__AVX512ER__)
traverseClosestHitAVX512<4,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
#elif defined(__AVX512VL__)
traverseClosestHitAVX512VL<4,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
#else
static_assert(false);
#endif
#else
const BaseNode* node = cur.baseNode(types);
@@ -368,9 +555,16 @@ namespace embree
StackItemT<NodeRef>* stackEnd)
{
assert(mask != 0);
#if defined(__AVX512F__) && 1
#if defined(__AVX512ER__)
traverseClosestHitAVX512<8,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
#elif defined(__AVX512VL__)
traverseClosestHitAVX512VL<8,Nx,types,NodeRef,BaseNode>(cur,mask,tNear,stackPtr,stackEnd);
#else
static_assert(false);
#endif
#else
const BaseNode* node = cur.baseNode(types);
+384
View File
@@ -0,0 +1,384 @@
// ======================================================================== //
// Copyright 2009-2017 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. //
// ======================================================================== //
#pragma once
#include "bvh.h"
#include "../common/ray.h"
#include "../common/stack_item.h"
namespace embree
{
namespace isa
{
struct NearFarPreCompute
{
size_t nearX, nearY, nearZ;
size_t farX, farY, farZ;
__forceinline NearFarPreCompute() {}
__forceinline NearFarPreCompute(const Vec3fa& dir, size_t N)
{
const size_t M = sizeof(float)*N;
nearX = (dir.x < 0.0f) ? 1*M : 0*M;
nearY = (dir.y < 0.0f) ? 3*M : 2*M;
nearZ = (dir.z < 0.0f) ? 5*M : 4*M;
farX = nearX ^ M;
farY = nearY ^ M;
farZ = nearZ ^ M;
}
};
template<int K, bool robust>
struct Packet;
template<int K>
struct Packet<K,false>
{
Vec3vf<K> rdir;
Vec3vf<K> org_rdir;
vfloat<K> min_dist;
vfloat<K> max_dist;
__forceinline Packet () {}
__forceinline Packet (const Vec3vf<K>& org, const Vec3vf<K>& dir, const vfloat<K>& tnear, const vfloat<K>& tfar)
: rdir(rcp_safe(dir)), org_rdir(org*rdir), min_dist(tnear), max_dist(tfar) {}
template<int N, int Nx>
__forceinline size_t intersectRay(const typename BVHN<N>::AlignedNode* __restrict__ node, size_t rid, const NearFarPreCompute& nf) const
{
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
const vfloat<Nx> rminX = msub(bminX, vfloat<Nx>(rdir.x[rid]), vfloat<Nx>(org_rdir.x[rid]));
const vfloat<Nx> rminY = msub(bminY, vfloat<Nx>(rdir.y[rid]), vfloat<Nx>(org_rdir.y[rid]));
const vfloat<Nx> rminZ = msub(bminZ, vfloat<Nx>(rdir.z[rid]), vfloat<Nx>(org_rdir.z[rid]));
const vfloat<Nx> rmaxX = msub(bmaxX, vfloat<Nx>(rdir.x[rid]), vfloat<Nx>(org_rdir.x[rid]));
const vfloat<Nx> rmaxY = msub(bmaxY, vfloat<Nx>(rdir.y[rid]), vfloat<Nx>(org_rdir.y[rid]));
const vfloat<Nx> rmaxZ = msub(bmaxZ, vfloat<Nx>(rdir.z[rid]), vfloat<Nx>(org_rdir.z[rid]));
const vfloat<Nx> rmin = maxi(rminX, rminY, rminZ, vfloat<Nx>(min_dist[rid]));
const vfloat<Nx> rmax = mini(rmaxX, rmaxY, rmaxZ, vfloat<Nx>(max_dist[rid]));
const vbool<Nx> vmask_first_hit = rmin <= rmax;
return movemask(vmask_first_hit) & (((size_t)1 << N)-1);
}
template<int N>
__forceinline size_t intersect(const typename BVHN<N>::AlignedNode* __restrict__ node, size_t bid, const NearFarPreCompute& nf) const
{
char *ptr = (char*)&node->lower_x + bid*sizeof(float);
const vfloat<K> bminX = *(const float*)(ptr + nf.nearX);
const vfloat<K> bminY = *(const float*)(ptr + nf.nearY);
const vfloat<K> bminZ = *(const float*)(ptr + nf.nearZ);
const vfloat<K> bmaxX = *(const float*)(ptr + nf.farX);
const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
const vfloat<K> rminX = msub(bminX, rdir.x, org_rdir.x);
const vfloat<K> rminY = msub(bminY, rdir.y, org_rdir.y);
const vfloat<K> rminZ = msub(bminZ, rdir.z, org_rdir.z);
const vfloat<K> rmaxX = msub(bmaxX, rdir.x, org_rdir.x);
const vfloat<K> rmaxY = msub(bmaxY, rdir.y, org_rdir.y);
const vfloat<K> rmaxZ = msub(bmaxZ, rdir.z, org_rdir.z);
const vfloat<K> rmin = maxi(rminX, rminY, rminZ, min_dist);
const vfloat<K> rmax = mini(rmaxX, rmaxY, rmaxZ, max_dist);
const vbool<K> vmask_first_hit = rmin <= rmax;
return movemask(vmask_first_hit);
}
};
template<int K>
struct Packet<K,true>
{
Vec3vf<K> rdir;
Vec3vf<K> org;
vfloat<K> min_dist;
vfloat<K> max_dist;
__forceinline Packet () {}
__forceinline Packet (const Vec3vf<K>& org, const Vec3vf<K>& dir, const vfloat<K>& tnear, const vfloat<K>& tfar)
: rdir(rcp_safe(dir)), org(org), min_dist(tnear), max_dist(tfar) {}
template<int N, int Nx>
__forceinline size_t intersectRay(const typename BVHN<N>::AlignedNode* __restrict__ node, size_t rid, const NearFarPreCompute& nf) const
{
const vfloat<Nx> bminX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX));
const vfloat<Nx> bminY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY));
const vfloat<Nx> bminZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ));
const vfloat<Nx> bmaxX = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farX));
const vfloat<Nx> bmaxY = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farY));
const vfloat<Nx> bmaxZ = vfloat<Nx>(*(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ));
const vfloat<Nx> rminX = (bminX - vfloat<Nx>(org.x[rid])) * vfloat<Nx>(rdir.x[rid]);
const vfloat<Nx> rminY = (bminY - vfloat<Nx>(org.y[rid])) * vfloat<Nx>(rdir.y[rid]);
const vfloat<Nx> rminZ = (bminZ - vfloat<Nx>(org.z[rid])) * vfloat<Nx>(rdir.z[rid]);
const vfloat<Nx> rmaxX = (bmaxX - vfloat<Nx>(org.x[rid])) * vfloat<Nx>(rdir.x[rid]);
const vfloat<Nx> rmaxY = (bmaxY - vfloat<Nx>(org.y[rid])) * vfloat<Nx>(rdir.y[rid]);
const vfloat<Nx> rmaxZ = (bmaxZ - vfloat<Nx>(org.z[rid])) * vfloat<Nx>(rdir.z[rid]);
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<Nx> rmin = round_down*max(rminX, rminY, rminZ, vfloat<Nx>(min_dist[rid]));
const vfloat<Nx> rmax = round_up *min(rmaxX, rmaxY, rmaxZ, vfloat<Nx>(max_dist[rid]));
const vbool<Nx> vmask_first_hit = rmin <= rmax;
return movemask(vmask_first_hit) & (((size_t)1 << N)-1);
}
template<int N>
__forceinline size_t intersect(const typename BVHN<N>::AlignedNode* __restrict__ node, size_t bid, const NearFarPreCompute& nf) const
{
char *ptr = (char*)&node->lower_x + bid*sizeof(float);
const vfloat<K> bminX = *(const float*)(ptr + nf.nearX);
const vfloat<K> bminY = *(const float*)(ptr + nf.nearY);
const vfloat<K> bminZ = *(const float*)(ptr + nf.nearZ);
const vfloat<K> bmaxX = *(const float*)(ptr + nf.farX);
const vfloat<K> bmaxY = *(const float*)(ptr + nf.farY);
const vfloat<K> bmaxZ = *(const float*)(ptr + nf.farZ);
const vfloat<K> rminX = (bminX - org.x) * rdir.x;
const vfloat<K> rminY = (bminY - org.y) * rdir.y;
const vfloat<K> rminZ = (bminZ - org.z) * rdir.z;
const vfloat<K> rmaxX = (bmaxX - org.x) * rdir.x;
const vfloat<K> rmaxY = (bmaxY - org.y) * rdir.y;
const vfloat<K> rmaxZ = (bmaxZ - org.z) * 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<K> rmin = round_down*max(rminX, rminY, rminZ, vfloat<K>(min_dist));
const vfloat<K> rmax = round_up *min(rmaxX, rmaxY, rmaxZ, vfloat<K>(max_dist));
const vbool<K> vmask_first_hit = rmin <= rmax;
return movemask(vmask_first_hit);
}
};
/* Optimized frustum test. We calculate t=(p-org)/dir in ray/box
* intersection. We assume the rays are split by octant, thus
* dir intervals are either positive or negative in each
* dimension.
Case 1: dir.min >= 0 && dir.max >= 0:
t_min = (p_min - org_max) / dir_max = (p_min - org_max)*rdir_min = p_min*rdir_min - org_max*rdir_min
t_max = (p_max - org_min) / dir_min = (p_max - org_min)*rdir_max = p_max*rdir_max - org_min*rdir_max
Case 2: dir.min < 0 && dir.max < 0:
t_min = (p_max - org_min) / dir_min = (p_max - org_min)*rdir_max = p_max*rdir_max - org_min*rdir_max
t_max = (p_min - org_max) / dir_max = (p_min - org_max)*rdir_min = p_min*rdir_min - org_max*rdir_min
*/
template<int N, int Nx, int K, bool robust>
struct Frustum;
template<int N, int Nx, int K>
struct Frustum<N,Nx,K,false>
{
__forceinline Frustum() {}
__forceinline Frustum(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar) {
init(valid,org,rdir,ray_tnear,ray_tfar);
}
__forceinline void init(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar)
{
const Vec3fa reduced_min_org( reduce_min(select(valid,org.x,pos_inf)),
reduce_min(select(valid,org.y,pos_inf)),
reduce_min(select(valid,org.z,pos_inf)) );
const Vec3fa reduced_max_org( reduce_max(select(valid,org.x,neg_inf)),
reduce_max(select(valid,org.y,neg_inf)),
reduce_max(select(valid,org.z,neg_inf)) );
const Vec3fa reduced_min_rdir( reduce_min(select(valid,rdir.x,pos_inf)),
reduce_min(select(valid,rdir.y,pos_inf)),
reduce_min(select(valid,rdir.z,pos_inf)) );
const Vec3fa reduced_max_rdir( reduce_max(select(valid,rdir.x,neg_inf)),
reduce_max(select(valid,rdir.y,neg_inf)),
reduce_max(select(valid,rdir.z,neg_inf)) );
const float reduced_min_dist = reduce_min(select(valid,ray_tnear,vfloat<K>(pos_inf)));
const float reduced_max_dist = reduce_max(select(valid,ray_tfar ,vfloat<K>(neg_inf)));
init(reduced_min_org, reduced_max_org, reduced_min_rdir, reduced_max_rdir, reduced_min_dist, reduced_max_dist);
}
__forceinline void init(const Vec3fa& reduced_min_org,
const Vec3fa& reduced_max_org,
const Vec3fa& reduced_min_rdir,
const Vec3fa& reduced_max_rdir,
const float reduced_min_dist,
const float reduced_max_dist)
{
const Vec3ba pos_rdir = ge_mask(reduced_min_rdir, Vec3fa(zero));
min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
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);
min_dist = reduced_min_dist;
max_dist = reduced_max_dist;
nf = NearFarPreCompute(min_rdir,N);
}
__forceinline size_t intersect(const typename BVHN<N>::AlignedNode* __restrict__ node, vfloat<Nx>& dist) const
{
const vfloat<Nx> bminX = *(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX);
const vfloat<Nx> bminY = *(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY);
const vfloat<Nx> bminZ = *(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ);
const vfloat<Nx> bmaxX = *(const vfloat<N>*)((const char*)&node->lower_x + nf.farX);
const vfloat<Nx> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + nf.farY);
const vfloat<Nx> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ);
const vfloat<Nx> fminX = msub(bminX, vfloat<Nx>(min_rdir.x), vfloat<Nx>(min_org_rdir.x));
const vfloat<Nx> fminY = msub(bminY, vfloat<Nx>(min_rdir.y), vfloat<Nx>(min_org_rdir.y));
const vfloat<Nx> fminZ = msub(bminZ, vfloat<Nx>(min_rdir.z), vfloat<Nx>(min_org_rdir.z));
const vfloat<Nx> fmaxX = msub(bmaxX, vfloat<Nx>(max_rdir.x), vfloat<Nx>(max_org_rdir.x));
const vfloat<Nx> fmaxY = msub(bmaxY, vfloat<Nx>(max_rdir.y), vfloat<Nx>(max_org_rdir.y));
const vfloat<Nx> fmaxZ = msub(bmaxZ, vfloat<Nx>(max_rdir.z), vfloat<Nx>(max_org_rdir.z));
const vfloat<Nx> fmin = maxi(fminX, fminY, fminZ, vfloat<Nx>(min_dist));
dist = fmin;
const vfloat<Nx> fmax = mini(fmaxX, fmaxY, fmaxZ, vfloat<Nx>(max_dist));
const vbool<Nx> vmask_node_hit = fmin <= fmax;
size_t m_node = movemask(vmask_node_hit) & (((size_t)1 << N)-1);
return m_node;
}
__forceinline void updateMaxDist(const vfloat<K>& ray_tfar) {
max_dist = reduce_max(ray_tfar);
}
NearFarPreCompute nf;
Vec3fa min_rdir;
Vec3fa max_rdir;
Vec3fa min_org_rdir;
Vec3fa max_org_rdir;
float min_dist;
float max_dist;
};
template<int N, int Nx, int K>
struct Frustum<N,Nx,K,true >
{
__forceinline Frustum() {}
__forceinline Frustum(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar) {
init(valid,org,rdir,ray_tnear,ray_tfar);
}
__forceinline void init(const vbool<K>& valid, const Vec3vf<K>& org, const Vec3vf<K>& rdir, const vfloat<K>& ray_tnear, const vfloat<K>& ray_tfar)
{
const Vec3fa reduced_min_org( reduce_min(select(valid,org.x,pos_inf)),
reduce_min(select(valid,org.y,pos_inf)),
reduce_min(select(valid,org.z,pos_inf)) );
const Vec3fa reduced_max_org( reduce_max(select(valid,org.x,neg_inf)),
reduce_max(select(valid,org.y,neg_inf)),
reduce_max(select(valid,org.z,neg_inf)) );
const Vec3fa reduced_min_rdir( reduce_min(select(valid,rdir.x,pos_inf)),
reduce_min(select(valid,rdir.y,pos_inf)),
reduce_min(select(valid,rdir.z,pos_inf)) );
const Vec3fa reduced_max_rdir( reduce_max(select(valid,rdir.x,neg_inf)),
reduce_max(select(valid,rdir.y,neg_inf)),
reduce_max(select(valid,rdir.z,neg_inf)) );
const float reduced_min_dist = reduce_min(select(valid,ray_tnear,vfloat<K>(pos_inf)));
const float reduced_max_dist = reduce_max(select(valid,ray_tfar ,vfloat<K>(neg_inf)));
init(reduced_min_org, reduced_max_org, reduced_min_rdir, reduced_max_rdir, reduced_min_dist, reduced_max_dist);
}
__forceinline void init(const Vec3fa& reduced_min_org,
const Vec3fa& reduced_max_org,
const Vec3fa& reduced_min_rdir,
const Vec3fa& reduced_max_rdir,
const float reduced_min_dist,
const float reduced_max_dist)
{
const Vec3ba pos_rdir = ge_mask(reduced_min_rdir, Vec3fa(zero));
min_rdir = select(pos_rdir, reduced_min_rdir, reduced_max_rdir);
max_rdir = select(pos_rdir, reduced_max_rdir, reduced_min_rdir);
min_org = select(pos_rdir, reduced_max_org, reduced_min_org);
max_org = select(pos_rdir, reduced_min_org, reduced_max_org);
min_dist = reduced_min_dist;
max_dist = reduced_max_dist;
nf = NearFarPreCompute(min_rdir,N);
}
__forceinline size_t intersect(const typename BVHN<N>::AlignedNode* __restrict__ node, vfloat<Nx>& dist) const
{
const vfloat<Nx> bminX = *(const vfloat<N>*)((const char*)&node->lower_x + nf.nearX);
const vfloat<Nx> bminY = *(const vfloat<N>*)((const char*)&node->lower_x + nf.nearY);
const vfloat<Nx> bminZ = *(const vfloat<N>*)((const char*)&node->lower_x + nf.nearZ);
const vfloat<Nx> bmaxX = *(const vfloat<N>*)((const char*)&node->lower_x + nf.farX);
const vfloat<Nx> bmaxY = *(const vfloat<N>*)((const char*)&node->lower_x + nf.farY);
const vfloat<Nx> bmaxZ = *(const vfloat<N>*)((const char*)&node->lower_x + nf.farZ);
const vfloat<Nx> fminX = (bminX - vfloat<Nx>(min_org.x)) * vfloat<Nx>(min_rdir.x);
const vfloat<Nx> fminY = (bminY - vfloat<Nx>(min_org.y)) * vfloat<Nx>(min_rdir.y);
const vfloat<Nx> fminZ = (bminZ - vfloat<Nx>(min_org.z)) * vfloat<Nx>(min_rdir.z);
const vfloat<Nx> fmaxX = (bmaxX - vfloat<Nx>(max_org.x)) * vfloat<Nx>(max_rdir.x);
const vfloat<Nx> fmaxY = (bmaxY - vfloat<Nx>(max_org.y)) * vfloat<Nx>(max_rdir.y);
const vfloat<Nx> fmaxZ = (bmaxZ - vfloat<Nx>(max_org.z)) * vfloat<Nx>(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<Nx> fmin = max(fminX, fminY, fminZ, vfloat<Nx>(min_dist));
dist = fmin;
const vfloat<Nx> fmax = min(fmaxX, fmaxY, fmaxZ, vfloat<Nx>(max_dist));
const vbool<Nx> 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;
}
__forceinline void updateMaxDist(const vfloat<K>& ray_tfar) {
max_dist = reduce_max(ray_tfar);
}
NearFarPreCompute nf;
Vec3fa min_rdir;
Vec3fa max_rdir;
Vec3fa min_org;
Vec3fa max_org;
float min_dist;
float max_dist;
};
}
}
+127 -137
View File
@@ -61,62 +61,64 @@ namespace embree
ALIGNED_CLASS;
public:
struct Intersectors;
/*! Type of intersect function pointer for single rays. */
typedef void (*IntersectFunc)(void* ptr, /*!< pointer to user data */
typedef void (*IntersectFunc)(Intersectors* This, /*!< this pointer to accel */
RTCRay& ray, /*!< ray to intersect */
IntersectContext* context);
/*! Type of intersect function pointer for ray packets of size 4. */
typedef void (*IntersectFunc4)(const void* valid, /*!< pointer to valid mask */
void* ptr, /*!< pointer to user data */
Intersectors* This, /*!< this pointer to accel */
RTCRay4& ray, /*!< ray packet to intersect */
IntersectContext* context);
/*! Type of intersect function pointer for ray packets of size 8. */
typedef void (*IntersectFunc8)(const void* valid, /*!< pointer to valid mask */
void* ptr, /*!< pointer to user data */
Intersectors* This, /*!< this pointer to accel */
RTCRay8& ray, /*!< ray packet to intersect */
IntersectContext* context);
/*! Type of intersect function pointer for ray packets of size 16. */
typedef void (*IntersectFunc16)(const void* valid, /*!< pointer to valid mask */
void* ptr, /*!< pointer to user data */
typedef void (*IntersectFunc16)(const void* valid, /*!< pointer to valid mask */
Intersectors* This, /*!< this pointer to accel */
RTCRay16& ray, /*!< ray packet to intersect */
IntersectContext* context);
/*! Type of intersect function pointer for ray packets of size N. */
typedef void (*IntersectFuncN)(void* ptr, /*!< pointer to user data */
void** ray, /*!< ray stream to intersect */
typedef void (*IntersectFuncN)(Intersectors* This, /*!< this pointer to accel */
RayK<VSIZEX>** ray, /*!< ray stream to intersect */
const size_t N, /*!< number of rays in stream */
IntersectContext* context /*!< layout flags */);
/*! Type of occlusion function pointer for single rays. */
typedef void (*OccludedFunc) (void* ptr, /*!< pointer to user data */
typedef void (*OccludedFunc) (Intersectors* This, /*!< this pointer to accel */
RTCRay& ray, /*!< ray to test occlusion */
IntersectContext* context);
/*! Type of occlusion function pointer for ray packets of size 4. */
typedef void (*OccludedFunc4) (const void* valid, /*! pointer to valid mask */
void* ptr, /*!< pointer to user data */
Intersectors* This, /*!< this pointer to accel */
RTCRay4& ray, /*!< Ray packet to test occlusion. */
IntersectContext* context);
/*! Type of occlusion function pointer for ray packets of size 8. */
typedef void (*OccludedFunc8) (const void* valid, /*! pointer to valid mask */
void* ptr, /*!< pointer to user data */
Intersectors* This, /*!< this pointer to accel */
RTCRay8& ray, /*!< Ray packet to test occlusion. */
IntersectContext* context);
/*! Type of occlusion function pointer for ray packets of size 16. */
typedef void (*OccludedFunc16) (const void* valid, /*! pointer to valid mask */
void* ptr, /*!< pointer to user data */
Intersectors* This,/*!< this pointer to accel */
RTCRay16& ray, /*!< Ray packet to test occlusion. */
IntersectContext* context);
/*! Type of intersect function pointer for ray packets of size N. */
typedef void (*OccludedFuncN)(void* ptr, /*!< pointer to user data */
void** ray, /*!< ray stream to intersect */
typedef void (*OccludedFuncN)(Intersectors* This, /*!< this pointer to accel */
RayK<VSIZEX>** ray, /*!< ray stream to intersect */
const size_t N, /*!< number of rays in stream */
IntersectContext* context /*!< layout flags */);
typedef void (*ErrorFunc) ();
@@ -258,6 +260,118 @@ namespace embree
}
}
/*! Intersects a single ray with the scene. */
__forceinline void intersect (RTCRay& ray, IntersectContext* context) {
assert(intersector1.intersect);
intersector1.intersect(this,ray,context);
}
/*! Intersects a packet of 4 rays with the scene. */
__forceinline void intersect4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
assert(intersector4.intersect);
intersector4.intersect(valid,this,ray,context);
}
/*! Intersects a packet of 8 rays with the scene. */
__forceinline void intersect8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
assert(intersector8.intersect);
intersector8.intersect(valid,this,ray,context);
}
/*! Intersects a packet of 16 rays with the scene. */
__forceinline void intersect16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
assert(intersector16.intersect);
intersector16.intersect(valid,this,ray,context);
}
/*! Intersects a packet of N rays in SOA layout with the scene. */
__forceinline void intersectN (RayK<VSIZEX>** rayN, const size_t N, IntersectContext* context)
{
assert(intersectorN.intersect);
intersectorN.intersect(this,rayN,N,context);
}
#if defined(__SSE__)
__forceinline void intersect(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
const vint<4> mask = valid.mask32();
intersect4(&mask,(RTCRay4&)ray,context);
}
#endif
#if defined(__AVX__)
__forceinline void intersect(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
const vint<8> mask = valid.mask32();
intersect8(&mask,(RTCRay8&)ray,context);
}
#endif
#if defined(__AVX512F__)
__forceinline void intersect(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
const vint<16> mask = valid.mask32();
intersect16(&mask,(RTCRay16&)ray,context);
}
#endif
/*! Tests if single ray is occluded by the scene. */
__forceinline void occluded (RTCRay& ray, IntersectContext* context) {
assert(intersector1.occluded);
intersector1.occluded(this,ray,context);
}
/*! Tests if a packet of 4 rays is occluded by the scene. */
__forceinline void occluded4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
assert(intersector4.occluded);
intersector4.occluded(valid,this,ray,context);
}
/*! Tests if a packet of 8 rays is occluded by the scene. */
__forceinline void occluded8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
assert(intersector8.occluded);
intersector8.occluded(valid,this,ray,context);
}
/*! Tests if a packet of 16 rays is occluded by the scene. */
__forceinline void occluded16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
assert(intersector16.occluded);
intersector16.occluded(valid,this,ray,context);
}
/*! Tests if a packet of N rays in SOA layout is occluded by the scene. */
__forceinline void occludedN (RayK<VSIZEX>** rayN, const size_t N, IntersectContext* context)
{
//assert(intersectorN.occluded);
if (intersectorN.occluded)
intersectorN.occluded(this,rayN,N,context);
else
{
const size_t numPackets = (N+VSIZEX-1)/VSIZEX;
for (size_t i=0; i<numPackets; i++)
{
RayK<VSIZEX> &ray = *rayN[i];
vbool<VSIZEX> valid = ray.tnear <= ray.tfar;
occluded(valid,ray,context);
}
}
}
#if defined(__SSE__)
__forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
const vint<4> mask = valid.mask32();
occluded4(&mask,(RTCRay4&)ray,context);
}
#endif
#if defined(__AVX__)
__forceinline void occluded(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
const vint<8> mask = valid.mask32();
occluded8(&mask,(RTCRay8&)ray,context);
}
#endif
#if defined(__AVX512F__)
__forceinline void occluded(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
const vint<16> mask = valid.mask32();
occluded16(&mask,(RTCRay16&)ray,context);
}
#endif
public:
AccelData* ptr;
Intersector1 intersector1;
@@ -294,130 +408,6 @@ namespace embree
/*! build acceleration structure */
virtual void build () = 0;
/*! Intersects a single ray with the scene. */
__forceinline void intersect (RTCRay& ray, IntersectContext* context) {
assert(intersectors.intersector1.intersect);
intersectors.intersector1.intersect(intersectors.ptr,ray,context);
}
/*! Intersects a packet of 4 rays with the scene. */
__forceinline void intersect4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
assert(intersectors.intersector4.intersect);
intersectors.intersector4.intersect(valid,intersectors.ptr,ray,context);
}
/*! Intersects a packet of 8 rays with the scene. */
__forceinline void intersect8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
assert(intersectors.intersector8.intersect);
intersectors.intersector8.intersect(valid,intersectors.ptr,ray,context);
}
/*! Intersects a packet of 16 rays with the scene. */
__forceinline void intersect16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
assert(intersectors.intersector16.intersect);
intersectors.intersector16.intersect(valid,intersectors.ptr,ray,context);
}
/*! Intersects a packet of N rays in SOA layout with the scene. */
__forceinline void intersectN (void **rayN, const size_t N, IntersectContext* context)
{
//assert(intersectors.intersectorN.intersect);
if (intersectors.intersectorN.intersect)
intersectors.intersectorN.intersect(intersectors.ptr,rayN,N,context);
else
{
const size_t numPackets = (N+VSIZEX-1)/VSIZEX;
for (size_t i=0; i<numPackets; i++)
{
RayK<VSIZEX> &ray = *(RayK<VSIZEX>*)rayN[i];
vbool<VSIZEX> valid = ray.tnear <= ray.tfar;
intersect(valid,ray,context);
}
}
}
#if defined(__SSE__)
__forceinline void intersect(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
const vint<4> mask = valid.mask32();
intersect4(&mask,(RTCRay4&)ray,context);
}
#endif
#if defined(__AVX__)
__forceinline void intersect(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
const vint<8> mask = valid.mask32();
intersect8(&mask,(RTCRay8&)ray,context);
}
#endif
#if defined(__AVX512F__)
__forceinline void intersect(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
const vint<16> mask = valid.mask32();
intersect16(&mask,(RTCRay16&)ray,context);
}
#endif
/*! Tests if single ray is occluded by the scene. */
__forceinline void occluded (RTCRay& ray, IntersectContext* context) {
assert(intersectors.intersector1.occluded);
intersectors.intersector1.occluded(intersectors.ptr,ray,context);
}
/*! Tests if a packet of 4 rays is occluded by the scene. */
__forceinline void occluded4 (const void* valid, RTCRay4& ray, IntersectContext* context) {
assert(intersectors.intersector4.occluded);
intersectors.intersector4.occluded(valid,intersectors.ptr,ray,context);
}
/*! Tests if a packet of 8 rays is occluded by the scene. */
__forceinline void occluded8 (const void* valid, RTCRay8& ray, IntersectContext* context) {
assert(intersectors.intersector8.occluded);
intersectors.intersector8.occluded(valid,intersectors.ptr,ray,context);
}
/*! Tests if a packet of 16 rays is occluded by the scene. */
__forceinline void occluded16 (const void* valid, RTCRay16& ray, IntersectContext* context) {
assert(intersectors.intersector16.occluded);
intersectors.intersector16.occluded(valid,intersectors.ptr,ray,context);
}
/*! Tests if a packet of N rays in SOA layout is occluded by the scene. */
__forceinline void occludedN (void **rayN, const size_t N, IntersectContext* context)
{
//assert(intersectors.intersectorN.occluded);
if (intersectors.intersectorN.occluded)
intersectors.intersectorN.occluded(intersectors.ptr,rayN,N,context);
else
{
const size_t numPackets = (N+VSIZEX-1)/VSIZEX;
for (size_t i=0; i<numPackets; i++)
{
RayK<VSIZEX> &ray = *(RayK<VSIZEX>*)rayN[i];
vbool<VSIZEX> valid = ray.tnear <= ray.tfar;
occluded(valid,ray,context);
}
}
}
#if defined(__SSE__)
__forceinline void occluded(const vbool4& valid, RayK<4>& ray, IntersectContext* context) {
const vint<4> mask = valid.mask32();
occluded4(&mask,(RTCRay4&)ray,context);
}
#endif
#if defined(__AVX__)
__forceinline void occluded(const vbool8& valid, RayK<8>& ray, IntersectContext* context) {
const vint<8> mask = valid.mask32();
occluded8(&mask,(RTCRay8&)ray,context);
}
#endif
#if defined(__AVX512F__)
__forceinline void occluded(const vbool16& valid, RayK<16>& ray, IntersectContext* context) {
const vint<16> mask = valid.mask32();
occluded16(&mask,(RTCRay16&)ray,context);
}
#endif
public:
Intersectors intersectors;
};
+31 -33
View File
@@ -22,7 +22,7 @@
namespace embree
{
AccelN::AccelN ()
: Accel(AccelData::TY_ACCELN), accels(nullptr), validAccels(nullptr), validIntersectorN(false) {}
: Accel(AccelData::TY_ACCELN), accels(nullptr), validAccels(nullptr) {}
AccelN::~AccelN()
{
@@ -39,55 +39,55 @@ namespace embree
accels.push_back(accel);
}
void AccelN::intersect (void* ptr, RTCRay& ray, IntersectContext* context)
void AccelN::intersect (Accel::Intersectors* This_in, RTCRay& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++)
This->validAccels[i]->intersect(ray,context);
This->validAccels[i]->intersectors.intersect(ray,context);
}
void AccelN::intersect4 (const void* valid, void* ptr, RTCRay4& ray, IntersectContext* context)
void AccelN::intersect4 (const void* valid, Accel::Intersectors* This_in, RTCRay4& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++)
This->validAccels[i]->intersect4(valid,ray,context);
This->validAccels[i]->intersectors.intersect4(valid,ray,context);
}
void AccelN::intersect8 (const void* valid, void* ptr, RTCRay8& ray, IntersectContext* context)
void AccelN::intersect8 (const void* valid, Accel::Intersectors* This_in, RTCRay8& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++)
This->validAccels[i]->intersect8(valid,ray,context);
This->validAccels[i]->intersectors.intersect8(valid,ray,context);
}
void AccelN::intersect16 (const void* valid, void* ptr, RTCRay16& ray, IntersectContext* context)
void AccelN::intersect16 (const void* valid, Accel::Intersectors* This_in, RTCRay16& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++)
This->validAccels[i]->intersect16(valid,ray,context);
This->validAccels[i]->intersectors.intersect16(valid,ray,context);
}
void AccelN::intersectN (void* ptr, void** ray, const size_t N, IntersectContext* context)
void AccelN::intersectN (Accel::Intersectors* This_in, RayK<VSIZEX>** ray, const size_t N, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++)
This->validAccels[i]->intersectN(ray,N,context);
This->validAccels[i]->intersectors.intersectN(ray,N,context);
}
void AccelN::occluded (void* ptr, RTCRay& ray, IntersectContext* context)
void AccelN::occluded (Accel::Intersectors* This_in, RTCRay& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++) {
This->validAccels[i]->occluded(ray,context);
This->validAccels[i]->intersectors.occluded(ray,context);
if (ray.geomID == 0) break;
}
}
void AccelN::occluded4 (const void* valid, void* ptr, RTCRay4& ray, IntersectContext* context)
void AccelN::occluded4 (const void* valid, Accel::Intersectors* This_in, RTCRay4& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++) {
This->validAccels[i]->occluded4(valid,ray,context);
This->validAccels[i]->intersectors.occluded4(valid,ray,context);
#if defined(__SSE2__)
vbool4 valid0 = ((vbool4*)valid)[0];
vbool4 hit0 = ((vint4*)ray.geomID)[0] != vint4(0);
@@ -96,11 +96,11 @@ namespace embree
}
}
void AccelN::occluded8 (const void* valid, void* ptr, RTCRay8& ray, IntersectContext* context)
void AccelN::occluded8 (const void* valid, Accel::Intersectors* This_in, RTCRay8& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++) {
This->validAccels[i]->occluded8(valid,ray,context);
This->validAccels[i]->intersectors.occluded8(valid,ray,context);
#if defined(__SSE2__) // FIXME: use higher ISA
vbool4 valid0 = ((vbool4*)valid)[0];
vbool4 hit0 = ((vint4*)ray.geomID)[0] != vint4(0);
@@ -111,11 +111,11 @@ namespace embree
}
}
void AccelN::occluded16 (const void* valid, void* ptr, RTCRay16& ray, IntersectContext* context)
void AccelN::occluded16 (const void* valid, Accel::Intersectors* This_in, RTCRay16& ray, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
for (size_t i=0; i<This->validAccels.size(); i++) {
This->validAccels[i]->occluded16(valid,ray,context);
This->validAccels[i]->intersectors.occluded16(valid,ray,context);
#if defined(__SSE2__) // FIXME: use higher ISA
vbool4 valid0 = ((vbool4*)valid)[0];
vbool4 hit0 = ((vint4*)ray.geomID)[0] != vint4(0);
@@ -130,12 +130,12 @@ namespace embree
}
}
void AccelN::occludedN (void* ptr, void** ray, const size_t N, IntersectContext* context)
void AccelN::occludedN (Accel::Intersectors* This_in, RayK<VSIZEX>** ray, const size_t N, IntersectContext* context)
{
AccelN* This = (AccelN*)ptr;
AccelN* This = (AccelN*)This_in->ptr;
size_t M = N;
for (size_t i=0; i<This->validAccels.size(); i++)
This->validAccels[i]->occludedN(ray,M,context);
This->validAccels[i]->intersectors.occludedN(ray,M,context);
}
void AccelN::print(size_t ident)
@@ -163,11 +163,9 @@ namespace embree
/* create list of non-empty acceleration structures */
validAccels.clear();
validIntersectorN = true;
for (size_t i=0; i<accels.size(); i++) {
if (accels[i]->bounds.empty()) continue;
validAccels.push_back(accels[i]);
if (!accels[i]->intersectors.intersectorN) validIntersectorN = false;
}
if (validAccels.size() == 1) {
+10 -12
View File
@@ -31,18 +31,18 @@ namespace embree
void add(Accel* accel);
public:
static void intersect (void* ptr, RTCRay& ray, IntersectContext* context);
static void intersect4 (const void* valid, void* ptr, RTCRay4& ray, IntersectContext* context);
static void intersect8 (const void* valid, void* ptr, RTCRay8& ray, IntersectContext* context);
static void intersect16 (const void* valid, void* ptr, RTCRay16& ray, IntersectContext* context);
static void intersectN (void* ptr, void** ray, const size_t N, IntersectContext* context);
static void intersect (Accel::Intersectors* This, RTCRay& ray, IntersectContext* context);
static void intersect4 (const void* valid, Accel::Intersectors* This, RTCRay4& ray, IntersectContext* context);
static void intersect8 (const void* valid, Accel::Intersectors* This, RTCRay8& ray, IntersectContext* context);
static void intersect16 (const void* valid, Accel::Intersectors* This, RTCRay16& ray, IntersectContext* context);
static void intersectN (Accel::Intersectors* This, RayK<VSIZEX>** ray, const size_t N, IntersectContext* context);
public:
static void occluded (void* ptr, RTCRay& ray, IntersectContext* context);
static void occluded4 (const void* valid, void* ptr, RTCRay4& ray, IntersectContext* context);
static void occluded8 (const void* valid, void* ptr, RTCRay8& ray, IntersectContext* context);
static void occluded16 (const void* valid, void* ptr, RTCRay16& ray, IntersectContext* context);
static void occludedN (void* ptr, void** ray, const size_t N, IntersectContext* context);
static void occluded (Accel::Intersectors* This, RTCRay& ray, IntersectContext* context);
static void occluded4 (const void* valid, Accel::Intersectors* This, RTCRay4& ray, IntersectContext* context);
static void occluded8 (const void* valid, Accel::Intersectors* This, RTCRay8& ray, IntersectContext* context);
static void occluded16 (const void* valid, Accel::Intersectors* This, RTCRay16& ray, IntersectContext* context);
static void occludedN (Accel::Intersectors* This, RayK<VSIZEX>** ray, const size_t N, IntersectContext* context);
public:
void print(size_t ident);
@@ -51,11 +51,9 @@ namespace embree
void select(bool filter4, bool filter8, bool filter16, bool filterN);
void deleteGeometry(size_t geomID);
void clear ();
__forceinline bool validIsecN() { return validIntersectorN; }
public:
darray_t<Accel*,16> accels;
darray_t<Accel*,16> validAccels;
bool validIntersectorN;
};
}
+1 -1
View File
@@ -101,7 +101,7 @@ namespace embree
bvh4_factory = make_unique(new BVH4Factory(enabled_builder_cpu_features, enabled_cpu_features));
#if defined(EMBREE_TARGET_AVX)
#if defined(EMBREE_TARGET_SIMD8)
bvh8_factory = make_unique(new BVH8Factory(enabled_builder_cpu_features, enabled_cpu_features));
#endif
+1 -1
View File
@@ -88,7 +88,7 @@ namespace embree
std::unique_ptr<InstanceFactory> instance_factory;
std::unique_ptr<BVH4Factory> bvh4_factory;
#if defined(EMBREE_TARGET_AVX)
#if defined(EMBREE_TARGET_SIMD8)
std::unique_ptr<BVH8Factory> bvh8_factory;
#endif
+10 -2
View File
@@ -16,6 +16,9 @@
#pragma once
#include "../../common/sys/platform.h"
#include "../../common/sys/sysinfo.h"
namespace embree
{
#define DEFINE_SYMBOL2(type,name) \
@@ -69,12 +72,17 @@ namespace embree
#define SELECT_SYMBOL_SSE42(features,intersector)
#endif
#if defined(EMBREE_TARGET_AVX)
#if defined(EMBREE_TARGET_AVX) || defined(__AVX__)
#if !defined(EMBREE_TARGET_SIMD8)
#define EMBREE_TARGET_SIMD8
#endif
#define SELECT_SYMBOL_AVX(features,intersector) \
#if defined(__AVX__) // if default ISA is >= AVX we treat AVX target as default target
#define SELECT_SYMBOL_AVX(features,intersector) \
if ((features & ISA) == ISA) intersector = isa::intersector;
#else
#define SELECT_SYMBOL_AVX(features,intersector) \
if ((features & AVX) == AVX) intersector = avx::intersector;
#endif
#else
#define SELECT_SYMBOL_AVX(features,intersector)
#endif
+117 -34
View File
@@ -18,10 +18,14 @@
#include "default.h"
#define MAX_INTERNAL_STREAM_SIZE 64
namespace embree
{
#if defined(__X86_64__) && 0
static const size_t MAX_INTERNAL_STREAM_SIZE = 64;
#else
static const size_t MAX_INTERNAL_STREAM_SIZE = 32;
#endif
/* Ray structure for K rays */
template<int K>
struct RayK
@@ -364,35 +368,35 @@ namespace embree
struct RayPacketSOA
{
__forceinline RayPacketSOA(void* rays, size_t K)
: ptr((char*)rays), K(K) {}
__forceinline RayPacketSOA(void* rays, size_t N)
: ptr((char*)rays), N(N) {}
/* ray data access functions */
__forceinline float* orgx(size_t offset) { return (float*)&ptr[0*4*K+offset]; } //!< x coordinate of ray origin
__forceinline float* orgy(size_t offset) { return (float*)&ptr[1*4*K+offset]; } //!< y coordinate of ray origin
__forceinline float* orgz(size_t offset) { return (float*)&ptr[2*4*K+offset]; }; //!< z coordinate of ray origin
__forceinline float* orgx(size_t offset) { return (float*)&ptr[0*4*N+offset]; } //!< x coordinate of ray origin
__forceinline float* orgy(size_t offset) { return (float*)&ptr[1*4*N+offset]; } //!< y coordinate of ray origin
__forceinline float* orgz(size_t offset) { return (float*)&ptr[2*4*N+offset]; }; //!< z coordinate of ray origin
__forceinline float* dirx(size_t offset) { return (float*)&ptr[3*4*K+offset]; }; //!< x coordinate of ray direction
__forceinline float* diry(size_t offset) { return (float*)&ptr[4*4*K+offset]; }; //!< y coordinate of ray direction
__forceinline float* dirz(size_t offset) { return (float*)&ptr[5*4*K+offset]; }; //!< z coordinate of ray direction
__forceinline float* dirx(size_t offset) { return (float*)&ptr[3*4*N+offset]; }; //!< x coordinate of ray direction
__forceinline float* diry(size_t offset) { return (float*)&ptr[4*4*N+offset]; }; //!< y coordinate of ray direction
__forceinline float* dirz(size_t offset) { return (float*)&ptr[5*4*N+offset]; }; //!< z coordinate of ray direction
__forceinline float* tnear(size_t offset) { return (float*)&ptr[6*4*K+offset]; }; //!< Start of ray segment
__forceinline float* tfar (size_t offset) { return (float*)&ptr[7*4*K+offset]; }; //!< End of ray segment (set to hit distance)
__forceinline float* tnear(size_t offset) { return (float*)&ptr[6*4*N+offset]; }; //!< Start of ray segment
__forceinline float* tfar (size_t offset) { return (float*)&ptr[7*4*N+offset]; }; //!< End of ray segment (set to hit distance)
__forceinline float* time(size_t offset) { return (float*)&ptr[8*4*K+offset]; }; //!< Time of this ray for motion blur
__forceinline int* mask(size_t offset) { return (int*) &ptr[9*4*K+offset]; }; //!< Used to mask out objects during traversal (optional)
__forceinline float* time(size_t offset) { return (float*)&ptr[8*4*N+offset]; }; //!< Time of this ray for motion blur
__forceinline int* mask(size_t offset) { return (int*) &ptr[9*4*N+offset]; }; //!< Used to mask out objects during traversal (optional)
/* hit data access functions */
__forceinline float* Ngx(size_t offset) { return (float*)&ptr[10*4*K+offset]; }; //!< x coordinate of geometry normal
__forceinline float* Ngy(size_t offset) { return (float*)&ptr[11*4*K+offset]; }; //!< y coordinate of geometry normal
__forceinline float* Ngz(size_t offset) { return (float*)&ptr[12*4*K+offset]; }; //!< z coordinate of geometry normal
__forceinline float* Ngx(size_t offset) { return (float*)&ptr[10*4*N+offset]; }; //!< x coordinate of geometry normal
__forceinline float* Ngy(size_t offset) { return (float*)&ptr[11*4*N+offset]; }; //!< y coordinate of geometry normal
__forceinline float* Ngz(size_t offset) { return (float*)&ptr[12*4*N+offset]; }; //!< z coordinate of geometry normal
__forceinline float* u(size_t offset) { return (float*)&ptr[13*4*K+offset]; }; //!< Barycentric u coordinate of hit
__forceinline float* v(size_t offset) { return (float*)&ptr[14*4*K+offset]; }; //!< Barycentric v coordinate of hit
__forceinline float* u(size_t offset) { return (float*)&ptr[13*4*N+offset]; }; //!< Barycentric u coordinate of hit
__forceinline float* v(size_t offset) { return (float*)&ptr[14*4*N+offset]; }; //!< Barycentric v coordinate of hit
__forceinline int* geomID(size_t offset) { return (int*)&ptr[15*4*K+offset]; }; //!< geometry ID
__forceinline int* primID(size_t offset) { return (int*)&ptr[16*4*K+offset]; }; //!< primitive ID
__forceinline int* instID(size_t offset) { return (int*)&ptr[17*4*K+offset]; }; //!< instance ID
__forceinline int* geomID(size_t offset) { return (int*)&ptr[15*4*N+offset]; }; //!< geometry ID
__forceinline int* primID(size_t offset) { return (int*)&ptr[16*4*N+offset]; }; //!< primitive ID
__forceinline int* instID(size_t offset) { return (int*)&ptr[17*4*N+offset]; }; //!< instance ID
__forceinline void setRayByIndex(size_t index, const Ray& ray, int* valid)
@@ -467,8 +471,45 @@ namespace embree
ray.tnear = vfloat<K>::loadu(tnear(offset));
ray.tfar = vfloat<K>::loadu(tfar(offset));
ray.time = vfloat<K>::loadu(time(offset));
ray.mask = vint<K> ::loadu(mask(offset));
ray.instID= vint<K> ::loadu(instID(offset));
ray.mask = vint<K>::loadu(mask(offset));
ray.instID = vint<K>::loadu(instID(offset));
ray.geomID = RTC_INVALID_GEOMETRY_ID;
return ray;
}
template<int K>
__forceinline RayK<K> getRayByOffset(const vbool<K>& valid, size_t offset)
{
RayK<K> ray;
ray.org.x = vfloat<K>::loadu(valid, orgx(offset));
ray.org.y = vfloat<K>::loadu(valid, orgy(offset));
ray.org.z = vfloat<K>::loadu(valid, orgz(offset));
ray.dir.x = vfloat<K>::loadu(valid, dirx(offset));
ray.dir.y = vfloat<K>::loadu(valid, diry(offset));
ray.dir.z = vfloat<K>::loadu(valid, dirz(offset));
ray.tnear = vfloat<K>::loadu(valid, tnear(offset));
ray.tfar = vfloat<K>::loadu(valid, tfar(offset));
ray.time = vfloat<K>::loadu(valid, time(offset));
ray.mask = vint<K>::loadu(valid, mask(offset));
#if !defined(__AVX__)
/* SSE: some ray members must be loaded with scalar instructions to ensure that we don't cause memory faults,
because the SSE masked loads always access the entire vector */
if (unlikely(!all(valid)))
{
ray.instID = zero;
for (size_t k = 0; k < K; k++)
{
if (likely(valid[k]))
ray.instID[k] = instID(offset)[k];
}
}
else
#endif
{
ray.instID = vint<K>::loadu(valid, instID(offset));
}
ray.geomID = RTC_INVALID_GEOMETRY_ID;
return ray;
}
@@ -539,17 +580,43 @@ namespace embree
if (likely(any(valid)))
{
vint<K>::storeu(valid, geomID(offset), ray.geomID);
#if !defined(__AVX__)
/* SSE: some ray members must be stored with scalar instructions to ensure that we don't cause memory faults,
because the SSE masked stores always access the entire vector */
if (unlikely(!all(valid_i)))
{
for (size_t k = 0; k < K; k++)
{
if (likely(valid[k]))
{
geomID(offset)[k] = ray.geomID[k];
if (intersect)
{
primID(offset)[k] = ray.primID[k];
instID(offset)[k] = ray.instID[k];
}
}
}
}
else
#endif
{
vint<K>::storeu(valid, geomID(offset), ray.geomID);
if (intersect)
{
vint<K>::storeu(valid, primID(offset), ray.primID);
vint<K>::storeu(valid, instID(offset), ray.instID);
}
}
if (intersect)
{
vfloat<K>::storeu(valid, tfar(offset), ray.tfar);
vfloat<K>::storeu(valid, u(offset), ray.u);
vfloat<K>::storeu(valid, v(offset), ray.v);
vint<K> ::storeu(valid, primID(offset), ray.primID);
vfloat<K>::storeu(valid, Ngx(offset), ray.Ng.x);
vfloat<K>::storeu(valid, Ngy(offset), ray.Ng.y);
vfloat<K>::storeu(valid, Ngz(offset), ray.Ng.z);
vint<K> ::storeu(valid, instID(offset), ray.instID);
vfloat<K>::storeu(valid, u(offset), ray.u);
vfloat<K>::storeu(valid, v(offset), ray.v);
}
}
}
@@ -571,7 +638,7 @@ namespace embree
}
char* __restrict__ ptr;
size_t K;
size_t N;
};
template<size_t MAX_K>
@@ -780,8 +847,15 @@ namespace embree
ray.time = vfloat<K>::template gather<1>(valid, &ptr->time, offset);
ray.mask = vint<K>::template gather<1>(valid, &ptr->mask, offset);
ray.instID = vint<K>::template gather<1>(valid, (int*)&ptr->instID, offset);
ray.geomID = RTC_INVALID_GEOMETRY_ID;
#else
ray.org = zero;
ray.dir = zero;
ray.tnear = zero;
ray.tfar = zero;
ray.time = zero;
ray.mask = zero;
ray.instID = zero;
for (size_t k = 0; k < K; k++)
{
if (likely(valid[k]))
@@ -799,11 +873,12 @@ namespace embree
ray.time[k] = ray_k->time;
ray.mask[k] = ray_k->mask;
ray.instID[k] = ray_k->instID;
ray.geomID[k] = RTC_INVALID_GEOMETRY_ID;
}
}
#endif
ray.geomID = RTC_INVALID_GEOMETRY_ID;
return ray;
}
@@ -899,7 +974,6 @@ namespace embree
__forceinline Ray8 RayStreamAOS::getRayByOffset(const vint8& offset)
{
Ray8 ray;
/* gather: instID */
ray.instID = vint8::gather<1>((int*)&ptr->instID, offset);
@@ -1014,6 +1088,14 @@ namespace embree
RayK<K> ray;
ray.org = zero;
ray.dir = zero;
ray.tnear = zero;
ray.tfar = zero;
ray.time = zero;
ray.mask = zero;
ray.instID = zero;
for (size_t k = 0; k < K; k++)
{
if (likely(valid[k]))
@@ -1031,10 +1113,11 @@ namespace embree
ray.time[k] = ray_k->time;
ray.mask[k] = ray_k->mask;
ray.instID[k] = ray_k->instID;
ray.geomID[k] = RTC_INVALID_GEOMETRY_ID;
}
}
ray.geomID = RTC_INVALID_GEOMETRY_ID;
return ray;
}
+22 -22
View File
@@ -346,7 +346,7 @@ namespace embree
#endif
STAT3(normal.travs,1,1,1);
IntersectContext context(scene,nullptr);
scene->intersect(ray,&context);
scene->intersectors.intersect(ray,&context);
#if defined(DEBUG)
((Ray&)ray).verifyHit();
#endif
@@ -365,7 +365,7 @@ namespace embree
#endif
STAT3(normal.travs,1,1,1);
IntersectContext context(scene,user_context);
scene->intersect(ray,&context);
scene->intersectors.intersect(ray,&context);
#if defined(DEBUG)
((Ray&)ray).verifyHit();
#endif
@@ -388,7 +388,7 @@ namespace embree
STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
STAT3(normal.travs,cnt,cnt,cnt);
IntersectContext context(scene,nullptr);
scene->intersect4(valid,ray,&context);
scene->intersectors.intersect4(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcIntersect4 not supported");
#endif
@@ -411,7 +411,7 @@ namespace embree
STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
STAT3(normal.travs,cnt,cnt,cnt);
IntersectContext context(scene,user_context);
scene->intersect4(valid,ray,&context);
scene->intersectors.intersect4(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcIntersect4Ex not supported");
#endif
@@ -434,7 +434,7 @@ namespace embree
STAT(size_t cnt=0; for (size_t i=0; i<8; i++) cnt += ((int*)valid)[i] == -1;);
STAT3(normal.travs,cnt,cnt,cnt);
IntersectContext context(scene,nullptr);
scene->intersect8(valid,ray,&context);
scene->intersectors.intersect8(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcIntersect8 not supported");
#endif
@@ -458,7 +458,7 @@ namespace embree
STAT3(normal.travs,cnt,cnt,cnt);
IntersectContext context(scene,user_context);
scene->intersect8(valid,ray,&context);
scene->intersectors.intersect8(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcIntersect8Ex not supported");
#endif
@@ -482,7 +482,7 @@ namespace embree
STAT3(normal.travs,cnt,cnt,cnt);
IntersectContext context(scene,nullptr);
scene->intersect16(valid,ray,&context);
scene->intersectors.intersect16(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcIntersect16 not supported");
#endif
@@ -506,7 +506,7 @@ namespace embree
STAT3(normal.travs,cnt,cnt,cnt);
IntersectContext context(scene,user_context);
scene->intersect16(valid,ray,&context);
scene->intersectors.intersect16(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcIntersect16Ex not supported");
#endif
@@ -531,7 +531,7 @@ namespace embree
/* fast codepath for single rays */
if (likely(M == 1)) {
if (likely(rays->tnear <= rays->tfar))
scene->intersect(*rays,&context);
scene->intersectors.intersect(*rays,&context);
}
/* codepath for streams */
@@ -562,7 +562,7 @@ namespace embree
/* fast codepath for single rays */
if (likely(M == 1)) {
if (likely(rays[0]->tnear <= rays[0]->tfar))
scene->intersect(*rays[0],&context);
scene->intersectors.intersect(*rays[0],&context);
}
/* codepath for streams */
@@ -596,7 +596,7 @@ namespace embree
/* fast code path for streams of size 1 */
if (likely(M == 1)) {
if (likely(((RTCRay*)rays)->tnear <= ((RTCRay*)rays)->tfar))
scene->intersect(*(RTCRay*)rays,&context);
scene->intersectors.intersect(*(RTCRay*)rays,&context);
}
/* normal codepath for single ray streams */
else {
@@ -663,7 +663,7 @@ namespace embree
if (((size_t)&ray) & 0x0F ) throw_RTCError(RTC_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
#endif
IntersectContext context(scene,nullptr);
scene->occluded(ray,&context);
scene->intersectors.occluded(ray,&context);
RTCORE_CATCH_END2(scene);
}
@@ -679,7 +679,7 @@ namespace embree
if (((size_t)&ray) & 0x0F ) throw_RTCError(RTC_INVALID_ARGUMENT, "ray not aligned to 16 bytes");
#endif
IntersectContext context(scene,user_context);
scene->occluded(ray,&context);
scene->intersectors.occluded(ray,&context);
RTCORE_CATCH_END2(scene);
}
@@ -699,7 +699,7 @@ namespace embree
STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
STAT3(shadow.travs,cnt,cnt,cnt);
IntersectContext context(scene,nullptr);
scene->occluded4(valid,ray,&context);
scene->intersectors.occluded4(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcOccluded4 not supported");
#endif
@@ -722,7 +722,7 @@ namespace embree
STAT(size_t cnt=0; for (size_t i=0; i<4; i++) cnt += ((int*)valid)[i] == -1;);
STAT3(shadow.travs,cnt,cnt,cnt);
IntersectContext context(scene,user_context);
scene->occluded4(valid,ray,&context);
scene->intersectors.occluded4(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcOccluded4Ex not supported");
#endif
@@ -745,7 +745,7 @@ namespace embree
STAT(size_t cnt=0; for (size_t i=0; i<8; i++) cnt += ((int*)valid)[i] == -1;);
STAT3(shadow.travs,cnt,cnt,cnt);
IntersectContext context(scene,nullptr);
scene->occluded8(valid,ray,&context);
scene->intersectors.occluded8(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcOccluded8 not supported");
#endif
@@ -769,7 +769,7 @@ namespace embree
STAT3(shadow.travs,cnt,cnt,cnt);
IntersectContext context(scene,user_context);
scene->occluded8(valid,ray,&context);
scene->intersectors.occluded8(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcOccluded8Ex not supported");
#endif
@@ -793,7 +793,7 @@ namespace embree
STAT3(shadow.travs,cnt,cnt,cnt);
IntersectContext context(scene,nullptr);
scene->occluded16(valid,ray,&context);
scene->intersectors.occluded16(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcOccluded16 not supported");
#endif
@@ -817,7 +817,7 @@ namespace embree
STAT3(shadow.travs,cnt,cnt,cnt);
IntersectContext context(scene,user_context);
scene->occluded16(valid,ray,&context);
scene->intersectors.occluded16(valid,ray,&context);
#else
throw_RTCError(RTC_INVALID_OPERATION,"rtcOccluded16Ex not supported");
#endif
@@ -842,7 +842,7 @@ namespace embree
/* fast codepath for streams of size 1 */
if (likely(M == 1)) {
if (likely(rays->tnear <= rays->tfar))
scene->occluded (*rays,&context);
scene->intersectors.occluded (*rays,&context);
}
/* codepath for normal streams */
else {
@@ -872,7 +872,7 @@ namespace embree
/* fast codepath for streams of size 1 */
if (likely(M == 1)) {
if (likely(rays[0]->tnear <= rays[0]->tfar))
scene->occluded (*rays[0],&context);
scene->intersectors.occluded (*rays[0],&context);
}
/* codepath for normal streams */
else {
@@ -906,7 +906,7 @@ namespace embree
/* fast path for streams of size 1 */
if (likely(M == 1)) {
if (likely(((RTCRay*)rays)->tnear <= ((RTCRay*)rays)->tfar))
scene->occluded (*(RTCRay*)rays,&context);
scene->intersectors.occluded (*(RTCRay*)rays,&context);
}
/* codepath for normal ray streams */
else {
+2 -2
View File
@@ -161,8 +161,8 @@ namespace embree
rtcIntersectNp(scene,context,rays,N);
}
extern "C" void ispcOccluded1 (RTCScene scene, RTCRay& ray) {
rtcOccluded(scene,ray);
extern "C" void ispcOccluded1 (RTCScene scene, const RTCIntersectContext* context, RTCRay& ray) {
rtcOccluded1Ex(scene,context,ray);
}
extern "C" void ispcOccluded4 (const void* valid, RTCScene scene, const RTCIntersectContext* context, RTCRay4& ray) {
+3 -3
View File
@@ -130,7 +130,7 @@ extern "C" void ispcDeleteGeometry (RTCScene scene, uniform unsigned int geomID)
extern "C" void ispcSetBoundsFunction (RTCScene scene, uniform unsigned int geomID, void* uniform bounds);
extern "C" void ispcSetBoundsFunction2 (RTCScene scene, uniform unsigned int geomID, void* uniform bounds, void* uniform userPtr);
extern "C" void ispcSetBoundsFunction3 (RTCScene scene, uniform unsigned int geomID, void* uniform bounds, void* uniform userPtr);
extern "C" void ispcSetTessellationRate (RTCScene hscene, uniform unsigned geomID, uniform float tessellationRate);
extern "C" void ispcSetTessellationRate (RTCScene hscene, uniform unsigned int geomID, uniform float tessellationRate);
extern "C" void ispcSetUserData (RTCScene scene, uniform unsigned int geomID, void* uniform ptr);
extern "C" void* uniform ispcGetUserData (RTCScene scene, uniform unsigned int geomID);
@@ -540,7 +540,7 @@ void rtcSetSubdivisionMode(RTCScene scene, uniform unsigned int geomID, uniform
ispcSetSubdivisionMode(scene,geomID,topologyID,mode);
}
void rtcSetIndexBuffer(RTCScene scene, uniform unsigned geomID, uniform RTCBufferType vertexBuffer, uniform RTCBufferType indexBuffer) {
void rtcSetIndexBuffer(RTCScene scene, uniform unsigned int geomID, uniform RTCBufferType vertexBuffer, uniform RTCBufferType indexBuffer) {
ispcSetIndexBuffer(scene,geomID,vertexBuffer,indexBuffer);
}
@@ -580,7 +580,7 @@ void rtcDeleteGeometry (RTCScene scene, uniform unsigned int geomID) {
ispcDeleteGeometry(scene,geomID);
}
void rtcSetTessellationRate (RTCScene hscene, uniform unsigned geomID, uniform float tessellationRate) {
void rtcSetTessellationRate (RTCScene hscene, uniform unsigned int geomID, uniform float tessellationRate) {
ispcSetTessellationRate(hscene,geomID,tessellationRate);
}
+26 -26
View File
@@ -108,7 +108,7 @@ namespace embree
int ty = __bsf(get(i)->type);
assert(ty<Geometry::NUM_TYPES);
int timesegments = get(i)->numTimeSegments();
assert(timesegments < max_time_steps);
assert((unsigned int)timesegments < max_time_steps);
statistics[ty][timesegments] += get(i)->size();
}
@@ -152,7 +152,7 @@ namespace embree
int mode = 2*(int)isCompact() + 1*(int)isRobust();
switch (mode) {
case /*0b00*/ 0:
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
{
if (isHighQuality())
@@ -171,7 +171,7 @@ namespace embree
break;
case /*0b01*/ 1:
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
accels.add(device->bvh8_factory->BVH8Triangle4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
else
@@ -185,7 +185,7 @@ namespace embree
}
else /* dynamic */
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
{
int mode = 2*(int)isCompact() + 1*(int)isRobust();
@@ -214,7 +214,7 @@ namespace embree
else if (device->tri_accel == "bvh4.triangle4i") accels.add(device->bvh4_factory->BVH4Triangle4i(this));
else if (device->tri_accel == "qbvh4.triangle4i") accels.add(device->bvh4_factory->BVH4QuantizedTriangle4i(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->tri_accel == "bvh8.triangle4") accels.add(device->bvh8_factory->BVH8Triangle4 (this));
else if (device->tri_accel == "bvh8.triangle4v") accels.add(device->bvh8_factory->BVH8Triangle4v(this));
else if (device->tri_accel == "bvh8.triangle4i") accels.add(device->bvh8_factory->BVH8Triangle4i(this));
@@ -232,7 +232,7 @@ namespace embree
{
int mode = 2*(int)isCompact() + 1*(int)isRobust();
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX2)) // BVH8 reduces performance on AVX only-machines
{
switch (mode) {
@@ -255,7 +255,7 @@ namespace embree
}
else if (device->tri_accel_mb == "bvh4.triangle4imb") accels.add(device->bvh4_factory->BVH4Triangle4iMB(this));
else if (device->tri_accel_mb == "bvh4.triangle4vmb") accels.add(device->bvh4_factory->BVH4Triangle4vMB(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->tri_accel_mb == "bvh8.triangle4imb") accels.add(device->bvh8_factory->BVH8Triangle4iMB(this));
else if (device->tri_accel_mb == "bvh8.triangle4vmb") accels.add(device->bvh8_factory->BVH8Triangle4vMB(this));
#endif
@@ -274,7 +274,7 @@ namespace embree
int mode = 2*(int)isCompact() + 1*(int)isRobust();
switch (mode) {
case /*0b00*/ 0:
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
{
if (isHighQuality())
@@ -293,7 +293,7 @@ namespace embree
break;
case /*0b01*/ 1:
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
accels.add(device->bvh8_factory->BVH8Quad4v(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
else
@@ -307,7 +307,7 @@ namespace embree
}
else /* dynamic */
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
{
int mode = 2*(int)isCompact() + 1*(int)isRobust();
@@ -335,7 +335,7 @@ namespace embree
else if (device->quad_accel == "bvh4.quad4i") accels.add(device->bvh4_factory->BVH4Quad4i(this));
else if (device->quad_accel == "qbvh4.quad4i") accels.add(device->bvh4_factory->BVH4QuantizedQuad4i(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->quad_accel == "bvh8.quad4v") accels.add(device->bvh8_factory->BVH8Quad4v(this));
else if (device->quad_accel == "bvh8.quad4i") accels.add(device->bvh8_factory->BVH8Quad4i(this));
else if (device->quad_accel == "qbvh8.quad4i") accels.add(device->bvh8_factory->BVH8QuantizedQuad4i(this));
@@ -352,7 +352,7 @@ namespace embree
int mode = 2*(int)isCompact() + 1*(int)isRobust();
switch (mode) {
case /*0b00*/ 0:
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
accels.add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::FAST));
else
@@ -361,7 +361,7 @@ namespace embree
break;
case /*0b01*/ 1:
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX))
accels.add(device->bvh8_factory->BVH8Quad4iMB(this,BVHFactory::BuildVariant::STATIC,BVHFactory::IntersectVariant::ROBUST));
else
@@ -374,7 +374,7 @@ namespace embree
}
}
else if (device->quad_accel_mb == "bvh4.quad4imb") accels.add(device->bvh4_factory->BVH4Quad4iMB(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->quad_accel_mb == "bvh8.quad4imb") accels.add(device->bvh8_factory->BVH8Quad4iMB(this));
#endif
else throw_RTCError(RTC_INVALID_ARGUMENT,"unknown quad motion blur acceleration structure "+device->quad_accel_mb);
@@ -389,7 +389,7 @@ namespace embree
int mode = 2*(int)isCompact() + 1*(int)isRobust();
if (isStatic())
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX2)) // only enable on HSW machines, for SNB this codepath is slower
{
switch (mode) {
@@ -424,7 +424,7 @@ namespace embree
else if (device->hair_accel == "bvh4.bezier1i" ) accels.add(device->bvh4_factory->BVH4Bezier1i(this));
else if (device->hair_accel == "bvh4obb.bezier1v" ) accels.add(device->bvh4_factory->BVH4OBBBezier1v(this));
else if (device->hair_accel == "bvh4obb.bezier1i" ) accels.add(device->bvh4_factory->BVH4OBBBezier1i(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->hair_accel == "bvh8obb.bezier1v" ) accels.add(device->bvh8_factory->BVH8OBBBezier1v(this));
else if (device->hair_accel == "bvh8obb.bezier1i" ) accels.add(device->bvh8_factory->BVH8OBBBezier1i(this));
#endif
@@ -437,7 +437,7 @@ namespace embree
#if defined(EMBREE_GEOMETRY_HAIR)
if (device->hair_accel_mb == "default")
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX2) && !isCompact()) // only enable on HSW machines, on SNB this codepath is slower
{
accels.add(device->bvh8_factory->BVH8OBBBezier1iMB(this));
@@ -449,7 +449,7 @@ namespace embree
}
}
else if (device->hair_accel_mb == "bvh4.bezier1imb") accels.add(device->bvh4_factory->BVH4OBBBezier1iMB(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->hair_accel_mb == "bvh8.bezier1imb") accels.add(device->bvh8_factory->BVH8OBBBezier1iMB(this));
#endif
else throw_RTCError(RTC_INVALID_ARGUMENT,"unknown motion blur hair acceleration structure "+device->hair_accel_mb);
@@ -463,7 +463,7 @@ namespace embree
{
if (isStatic())
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX) && !isCompact())
accels.add(device->bvh8_factory->BVH8Line4i(this));
else
@@ -476,7 +476,7 @@ namespace embree
}
}
else if (device->line_accel == "bvh4.line4i") accels.add(device->bvh4_factory->BVH4Line4i(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->line_accel == "bvh8.line4i") accels.add(device->bvh8_factory->BVH8Line4i(this));
#endif
else throw_RTCError(RTC_INVALID_ARGUMENT,"unknown line segment acceleration structure "+device->line_accel);
@@ -488,7 +488,7 @@ namespace embree
#if defined(EMBREE_GEOMETRY_LINES)
if (device->line_accel_mb == "default")
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX) && !isCompact())
accels.add(device->bvh8_factory->BVH8Line4iMB(this));
else
@@ -496,7 +496,7 @@ namespace embree
accels.add(device->bvh4_factory->BVH4Line4iMB(this));
}
else if (device->line_accel_mb == "bvh4.line4imb") accels.add(device->bvh4_factory->BVH4Line4iMB(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->line_accel_mb == "bvh8.line4imb") accels.add(device->bvh8_factory->BVH8Line4iMB(this));
#endif
else throw_RTCError(RTC_INVALID_ARGUMENT,"unknown motion blur line segment acceleration structure "+device->line_accel_mb);
@@ -542,7 +542,7 @@ namespace embree
#if defined(EMBREE_GEOMETRY_USER)
if (device->object_accel == "default")
{
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX) && !isCompact())
{
//if (isStatic()) {
@@ -562,7 +562,7 @@ namespace embree
}
}
else if (device->object_accel == "bvh4.object") accels.add(device->bvh4_factory->BVH4UserGeometry(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->object_accel == "bvh8.object") accels.add(device->bvh8_factory->BVH8UserGeometry(this));
#endif
else throw_RTCError(RTC_INVALID_ARGUMENT,"unknown user geometry accel "+device->object_accel);
@@ -573,7 +573,7 @@ namespace embree
{
#if defined(EMBREE_GEOMETRY_USER)
if (device->object_accel_mb == "default" ) {
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
if (device->hasISA(AVX) && !isCompact())
accels.add(device->bvh8_factory->BVH8UserGeometryMB(this));
else
@@ -581,7 +581,7 @@ namespace embree
accels.add(device->bvh4_factory->BVH4UserGeometryMB(this));
}
else if (device->object_accel_mb == "bvh4.object") accels.add(device->bvh4_factory->BVH4UserGeometryMB(this));
#if defined (EMBREE_TARGET_AVX)
#if defined (EMBREE_TARGET_SIMD8)
else if (device->object_accel_mb == "bvh8.object") accels.add(device->bvh8_factory->BVH8UserGeometryMB(this));
#endif
else throw_RTCError(RTC_INVALID_ARGUMENT,"unknown user geometry mblur accel "+device->object_accel_mb);
+1 -1
View File
@@ -185,7 +185,7 @@ namespace embree
{
const size_t ofs = i*sizeof(float);
const size_t segment = segments[primID];
const vboolx valid = vintx((int)i)+vintx(step) < vintx(numFloats);
const vboolx valid = vintx((int)i)+vintx(step) < vintx(int(numFloats));
const vfloatx p0 = vfloatx::loadu(valid,(float*)&src[(segment+0)*stride+ofs]);
const vfloatx p1 = vfloatx::loadu(valid,(float*)&src[(segment+1)*stride+ofs]);
if (P ) vfloatx::storeu(valid,P+i,lerp(p0,p1,u));
+1 -1
View File
@@ -200,7 +200,7 @@ namespace embree
for (size_t i=0; i<numFloats; i+=VSIZEX)
{
const vboolx valid = vintx((int)i)+vintx(step) < vintx(numFloats);
const vboolx valid = vintx((int)i)+vintx(step) < vintx(int(numFloats));
const size_t ofs = i*sizeof(float);
const Quad& tri = quad(primID);
const vfloatx p0 = vfloatx::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]);
+1 -1
View File
@@ -873,7 +873,7 @@ namespace embree
for (size_t i=0; i<numUVs; i+=4)
{
vbool4 valid1 = vint4(i)+vint4(step) < vint4(numUVs);
vbool4 valid1 = vint4(int(i))+vint4(step) < vint4(int(numUVs));
if (valid) valid1 &= vint4::loadu(&valid[i]) == vint4(-1);
if (none(valid1)) continue;
+1 -1
View File
@@ -207,7 +207,7 @@ namespace embree
size_t ofs = i*sizeof(float);
const float w = 1.0f-u-v;
const Triangle& tri = triangle(primID);
const vboolx valid = vintx((int)i)+vintx(step) < vintx(numFloats);
const vboolx valid = vintx((int)i)+vintx(step) < vintx(int(numFloats));
const vfloatx p0 = vfloatx::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]);
const vfloatx p1 = vfloatx::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]);
const vfloatx p2 = vfloatx::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]);
+10 -2
View File
@@ -22,7 +22,7 @@ namespace embree
{
/*! An item on the stack holds the node ID and distance of that node. */
template<typename T>
struct __aligned(16) StackItemT
struct __aligned(16) StackItemT
{
/*! assert that the xchg function works */
static_assert(sizeof(T) <= 12, "sizeof(T) <= 12 failed");
@@ -79,7 +79,15 @@ namespace embree
}
public:
T ptr;
T ptr;
unsigned dist;
};
/*! An item on the stack holds the node ID and active ray mask. */
template<typename T>
struct __aligned(16) StackItemMaskT
{
T ptr;
unsigned mask;
};
}
+6 -6
View File
@@ -30,12 +30,12 @@ namespace embree
{
/* the generate loops need padded arrays, thus first store into these temporary arrays */
unsigned temp_size = width*height+VSIZEX;
dynamic_large_stack_array(float,local_grid_u,temp_size,64*64*sizeof(float));
dynamic_large_stack_array(float,local_grid_v,temp_size,64*64*sizeof(float));
dynamic_large_stack_array(float,local_grid_x,temp_size,64*64*sizeof(float));
dynamic_large_stack_array(float,local_grid_y,temp_size,64*64*sizeof(float));
dynamic_large_stack_array(float,local_grid_z,temp_size,64*64*sizeof(float));
dynamic_large_stack_array(int,local_grid_uv,temp_size,64*64*sizeof(int));
dynamic_large_stack_array(float,local_grid_u,temp_size,32*32*sizeof(float));
dynamic_large_stack_array(float,local_grid_v,temp_size,32*32*sizeof(float));
dynamic_large_stack_array(float,local_grid_x,temp_size,32*32*sizeof(float));
dynamic_large_stack_array(float,local_grid_y,temp_size,32*32*sizeof(float));
dynamic_large_stack_array(float,local_grid_z,temp_size,32*32*sizeof(float));
dynamic_large_stack_array(int,local_grid_uv,temp_size,32*32*sizeof(int));
/* first create the grids for each time step */
for (size_t t=0; t<time_steps; t++)
+8 -8
View File
@@ -52,7 +52,7 @@ namespace embree
ray.geomID = RTC_INVALID_GEOMETRY_ID;
ray.instID = instance->geomID;
IntersectContext context(instance->object,user_context);
instance->object->intersect((RTCRay&)ray,&context);
instance->object->intersectors.intersect((RTCRay&)ray,&context);
ray.org = ray_org;
ray.dir = ray_dir;
if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {
@@ -71,7 +71,7 @@ namespace embree
ray.dir = xfmVector(world2local,ray_dir);
ray.instID = instance->geomID;
IntersectContext context(instance->object,user_context);
instance->object->occluded((RTCRay&)ray,&context);
instance->object->intersectors.occluded((RTCRay&)ray,&context);
ray.org = ray_org;
ray.dir = ray_dir;
}
@@ -82,16 +82,16 @@ namespace embree
__forceinline void occludedObject(vint<K>* valid, Scene* object, IntersectContext* context, RayK<K>& ray);
#if defined (__SSE__)
template<> __forceinline void intersectObject<4>(vint4* valid, Scene* object, IntersectContext* context, Ray4& ray) { object->intersect4(valid,(RTCRay4&)ray,context); }
template<> __forceinline void occludedObject <4>(vint4* valid, Scene* object, IntersectContext* context, Ray4& ray) { object->occluded4 (valid,(RTCRay4&)ray,context); }
template<> __forceinline void intersectObject<4>(vint4* valid, Scene* object, IntersectContext* context, Ray4& ray) { object->intersectors.intersect4(valid,(RTCRay4&)ray,context); }
template<> __forceinline void occludedObject <4>(vint4* valid, Scene* object, IntersectContext* context, Ray4& ray) { object->intersectors.occluded4 (valid,(RTCRay4&)ray,context); }
#endif
#if defined (__AVX__)
template<> __forceinline void intersectObject<8>(vint8* valid, Scene* object, IntersectContext* context, Ray8& ray) { object->intersect8(valid,(RTCRay8&)ray,context); }
template<> __forceinline void occludedObject <8>(vint8* valid, Scene* object, IntersectContext* context, Ray8& ray) { object->occluded8 (valid,(RTCRay8&)ray,context); }
template<> __forceinline void intersectObject<8>(vint8* valid, Scene* object, IntersectContext* context, Ray8& ray) { object->intersectors.intersect8(valid,(RTCRay8&)ray,context); }
template<> __forceinline void occludedObject <8>(vint8* valid, Scene* object, IntersectContext* context, Ray8& ray) { object->intersectors.occluded8 (valid,(RTCRay8&)ray,context); }
#endif
#if defined (__AVX512F__)
template<> __forceinline void intersectObject<16>(vint16* valid, Scene* object, IntersectContext* context, Ray16& ray) { object->intersect16(valid,(RTCRay16&)ray,context); }
template<> __forceinline void occludedObject <16>(vint16* valid, Scene* object, IntersectContext* context, Ray16& ray) { object->occluded16 (valid,(RTCRay16&)ray,context); }
template<> __forceinline void intersectObject<16>(vint16* valid, Scene* object, IntersectContext* context, Ray16& ray) { object->intersectors.intersect16(valid,(RTCRay16&)ray,context); }
template<> __forceinline void occludedObject <16>(vint16* valid, Scene* object, IntersectContext* context, Ray16& ray) { object->intersectors.occluded16 (valid,(RTCRay16&)ray,context); }
#endif
template<int N>
+10 -4
View File
@@ -29,8 +29,6 @@ namespace embree
typedef typename Intersector::Primitive Primitive;
typedef typename Intersector::Precalculations Precalculations;
static const bool validIntersectorK = false; // FIXME: why do we need this
static __forceinline void intersect(Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive* prim, size_t num, size_t& lazy_node)
{
for (size_t i=0; i<num; i++)
@@ -105,8 +103,6 @@ namespace embree
{
typedef typename IntersectorK::Primitive PrimitiveK;
typedef typename IntersectorK::Precalculations PrecalculationsK;
static const bool validIntersectorK = true;
static __forceinline void intersectK(const vbool<K>& valid, /* PrecalculationsK& pre, */ RayK<K>& ray, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
{
@@ -128,6 +124,16 @@ namespace embree
return !valid0;
}
static __forceinline bool occluded(RayK<K>& ray, size_t k, IntersectContext* context, const PrimitiveK* prim, size_t num, size_t& lazy_node)
{
PrecalculationsK pre(vbool<K>(true),ray); // FIXME: might cause trouble
for (size_t i=0; i<num; i++) {
if (IntersectorK::occluded(pre,ray,k,context,prim[i]))
return true;
}
return false;
}
};
}
}
+1
View File
@@ -214,6 +214,7 @@ namespace embree
const unsigned l = (unsigned) floor(0.5f*uv.x); const float u = 2.0f*frac(0.5f*uv.x)-0.5f;
const unsigned h = (unsigned) floor(0.5f*uv.y); const float v = 2.0f*frac(0.5f*uv.y)-0.5f;
const unsigned i = 4*h+l; assert(i<N);
if (i >= N) return;
#if PATCH_USE_GREGORY == 2
BezierCurve borders[2]; patch.getLimitBorder(borders,i);
+8 -8
View File
@@ -323,14 +323,14 @@ namespace embree
const unsigned x1s = stitch(x1,fine_x,coarse_x);
const unsigned M = x1s-x0s+1;
dynamic_large_stack_array(float,px,M,64*sizeof(float));
dynamic_large_stack_array(float,py,M,64*sizeof(float));
dynamic_large_stack_array(float,pz,M,64*sizeof(float));
dynamic_large_stack_array(float,u,M,64*sizeof(float));
dynamic_large_stack_array(float,v,M,64*sizeof(float));
dynamic_large_stack_array(float,nx,M,64*sizeof(float));
dynamic_large_stack_array(float,ny,M,64*sizeof(float));
dynamic_large_stack_array(float,nz,M,64*sizeof(float));
dynamic_large_stack_array(float,px,M,32*sizeof(float));
dynamic_large_stack_array(float,py,M,32*sizeof(float));
dynamic_large_stack_array(float,pz,M,32*sizeof(float));
dynamic_large_stack_array(float,u,M,32*sizeof(float));
dynamic_large_stack_array(float,v,M,32*sizeof(float));
dynamic_large_stack_array(float,nx,M,32*sizeof(float));
dynamic_large_stack_array(float,ny,M,32*sizeof(float));
dynamic_large_stack_array(float,nz,M,32*sizeof(float));
const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
Eval(patch,subPatch, x0s,x1s, bottom,bottom, coarse_x+1,2, px,py,pz,u,v,
has_Nxyz ? (float*)nx :nullptr, has_Nxyz ? (float*)ny : nullptr , has_Nxyz ? (float*)nz : nullptr, 4097,1);
+3 -3
View File
@@ -95,9 +95,9 @@ namespace embree
{
const bool displ = geom->displFunc || geom->displFunc2;
const unsigned N = displ ? M : 0;
dynamic_large_stack_array(float,grid_Ng_x,N,64*64*sizeof(float));
dynamic_large_stack_array(float,grid_Ng_y,N,64*64*sizeof(float));
dynamic_large_stack_array(float,grid_Ng_z,N,64*64*sizeof(float));
dynamic_large_stack_array(float,grid_Ng_x,N,32*32*sizeof(float));
dynamic_large_stack_array(float,grid_Ng_y,N,32*32*sizeof(float));
dynamic_large_stack_array(float,grid_Ng_z,N,32*32*sizeof(float));
if (geom->patch_eval_trees.size())
{
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -42,7 +42,7 @@ def render(name,modelname,model):
command += ' -c ' + model
for arg in args:
command += ' ' + arg
command += ' -rtcore verbose=2 -benchmark 4 16 > ' + logFile
command += ' -rtcore verbose=2 -benchmark 8 32 > ' + logFile
os.system(command)
def renderLoop():
+1 -1
View File
@@ -94,7 +94,7 @@ outImageFileJpg = name + ".jpg"
diffImageFileTga= name + ".diff.tga"
diffImageFileJpg= name + ".diff.jpg"
executable = executable + " -rtcore verbose=2"
executable = executable + " -rtcore verbose=0"
if (model != "" and model != "default"):
executable = executable + " -c " + modeldir + dash + model
+2 -2
View File
@@ -3,7 +3,7 @@ make clean > /dev/null
kwinject -w -o buildspec.txt make -j 8 > /dev/null
#kwcheck create -b buildspec.txt --url http://localhost:8080/embree
#kwcheck run
kwbuildproject --force --url http://localhost:8080/embree buildspec.txt --tables-directory mytables
kwadmin --url http://localhost:8080 load embree mytables
kwbuildproject --force --url http://10.123.110.111:80/embree buildspec.txt --tables-directory mytables
kwadmin --url http://10.123.110.111:80 load embree mytables
#kwcheck list -F detailed
#kwcheck list -F detailed > klocwork.log
+1
View File
@@ -57,6 +57,7 @@ cmake \
# set release settings
cmake \
-D EMBREE_STACK_PROTECTOR=ON\
-D EMBREE_MAX_ISA=NONE \
-D EMBREE_ISA_SSE2=ON \
-D EMBREE_ISA_SSE42=ON \
+1
View File
@@ -19,6 +19,7 @@ cmake \
# set release settings
cmake \
-D EMBREE_STACK_PROTECTOR=ON\
-D EMBREE_MAX_ISA=AVX2 \
-D EMBREE_TUTORIALS_IMAGE_MAGICK=OFF \
-D EMBREE_TUTORIALS_LIBJPEG=OFF \
+1
View File
@@ -12,6 +12,7 @@ REM set release settings
cmake -L ^
-G "Visual Studio 12 2013" ^
-T "Intel C++ Compiler 16.0" ^
-D EMBREE_STACK_PROTECTOR=ON ^
-D EMBREE_MAX_ISA=AVX512SKX ^
-D EMBREE_TUTORIALS_IMAGE_MAGICK=OFF ^
-D EMBREE_TUTORIALS_LIBJPEG=OFF ^
+117
View File
@@ -0,0 +1,117 @@
message("CTEST_BUILD_OPTIONS = ${CTEST_BUILD_OPTIONS}")
# project and repository to clone from
SET(CTEST_PROJECT_NAME "Embree")
SET(TEST_REPOSITORY "https://github.com/embree/embree.git")
SET(TEST_ROOT_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}/..")
STRING(REPLACE ":/" ":\\" TEST_ROOT_DIRECTORY1 "${TEST_ROOT_DIRECTORY}") # cygwin git has issues with c:/dir paths
#SET(TEST_MODELS_DIRECTORY ${TEST_ROOT_DIRECTORY}/dependencies/embree-models)
SET(TEST_MODELS_DIRECTORY $ENV{HOME}/embree-models)
MESSAGE("TEST_MODELS_DIRECTORY = ${TEST_MODELS_DIRECTORY}")
# set source and build directory
set(CTEST_SOURCE_DIRECTORY "${TEST_ROOT_DIRECTORY1}")
message("CTEST_SOURCE_DIRECTORY = ${CTEST_SOURCE_DIRECTORY}")
set(CTEST_BINARY_DIRECTORY "${TEST_ROOT_DIRECTORY1}/build")
# update external model repository
FIND_PROGRAM(CTEST_GIT_COMMAND NAMES git)
# macro that updates the test models
MACRO(update_test_models)
IF(NOT EXISTS "${TEST_MODELS_DIRECTORY}")
MESSAGE("cloning test models ...")
EXECUTE_PROCESS(
COMMAND ${CTEST_GIT_COMMAND} "clone" "git@git.sdvis.org:embree-models.git" embree-models
WORKING_DIRECTORY $ENV{HOME}
)
ELSE()
MESSAGE("updating test models ...")
EXECUTE_PROCESS(
COMMAND ${CTEST_GIT_COMMAND} "fetch"
WORKING_DIRECTORY ${TEST_MODELS_DIRECTORY}
)
ENDIF()
IF (NOT TEST_MODELS_HASH)
MESSAGE(FATAL_ERROR "no TEST_MODELS_HASH set")
ENDIF()
MESSAGE("checking out test models: ${TEST_MODELS_HASH}")
EXECUTE_PROCESS(
COMMAND ${CTEST_GIT_COMMAND} "checkout" ${TEST_MODELS_HASH}
WORKING_DIRECTORY ${TEST_MODELS_DIRECTORY}
)
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()
# 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}")
# set site based on this machine's hostname
SITE_NAME(HOSTNAME)
set(CTEST_SITE "${HOSTNAME}")
# 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 "${TEST_NAME}-${osname}-${cpu}")
set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
IF (WIN32)
set(CTEST_BUILD_COMMAND "${CMAKE_COMMAND} --build . --config ${CTEST_CONFIGURATION_TYPE}")
ELSE()
set(CTEST_BUILD_COMMAND "make -j ${numProcessors}")
ENDIF()
###################
# execute the test
###################
# requires CMake 2.8 or higher for git!!!
#set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}")
set(CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION}")
set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} ${CTEST_BUILD_OPTIONS}")
set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} ..")
# start the test
ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY})
ctest_start("Continuous")
#ctest_update (RETURN_VALUE count)
update_test_models()
ctest_configure()
ctest_build()
IF (NOT CTEST_SKIP_TESTING)
ctest_test()
ENDIF()
ctest_submit()
+514
View File
@@ -0,0 +1,514 @@
#!/usr/bin/python
import sys
import os
import ctypes
import time
import datetime
import json
import socket
import subprocess
g_cdash = ""
g_config = {}
g_mode = "Experimental"
g_intensive = False
g_debugMode = False
g_singleConfig = ""
def escape(str):
str = str.replace("\\",r"\\")
str = str.replace("\"",r"\"")
str = str.replace(":","\:")
return str
# 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)
# fast testing
def createConfigsLight(branch,build,host):
configs = []
if host == "tcg-vis-ci-win1":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"V140", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
if host == "tcg-vis-ci-win2":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"V120", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
if host == "tcg-vis-mac-mini":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC16", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
if host == "tcg-vis-ci-ubuntu1604" or host == "tcg-vis-ubuntu1404":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"AVX2" , "tasking":"TBB", "intensive":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":"AVX512KNL", "tasking":"TBB", "intensive":"OFF" })
if host == "k7":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":"AVX512KNL", "tasking":"TBB", "intensive":"OFF" })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4","isa":"AVX512KNL", "tasking":"TBB", "intensive":"OFF" })
if host == "swr-ivb-lnx-01":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":"AVX2", "tasking":"TBB", "klocwork":"ON"})
if host == "skylake-b0":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":"AVX512SKX", "tasking":"TBB", "intensive":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4","isa":"AVX512SKX", "tasking":"TBB", "intensive":"OFF"})
if host == "test":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"SSE2" , "tasking":"TBB", "intensive":"OFF"})
return configs
# intensive testing
def createConfigsIntensive(branch,build,host):
configs = []
if host == "tcg-vis-ci-win1":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC18","isa":"AVX512SKX", "tasking":"TBB", "intensive":"ON"})
for platform in ["x64", "win32"]:
if platform == "win32": intensive = "OFF" # runs only small win32 tests for win32 platform
else: intensive = "ON"
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"V140", "isa":"AVX2", "tasking":"TBB", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"V140", "isa":"AVX2", "tasking":"INT", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"V140", "isa":"AVX2", "tasking":"PPL", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"CLANG","isa":"AVX2", "tasking":"TBB", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"ICC16","isa":"AVX2", "tasking":"TBB", "intensive":intensive})
elif host == "tcg-vis-ci-win2":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":"AVX512SKX" , "tasking":"TBB", "intensive":"OFF", "sde":"skx"})
for platform in ["x64", "win32"]:
if platform == "win32": intensive = "OFF" # runs only small win32 tests for win32 platform
else: intensive = "ON"
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"V120", "isa":"SSE2", "tasking":"TBB", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"V120", "isa":"AVX", "tasking":"INT", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"V141", "isa":"AVX2", "tasking":"TBB", "intensive":intensive})
configs.append({"branch":branch, "platform":platform, "build":build, "compiler":"ICC17", "isa":"AVX2", "tasking":"TBB", "intensive":intensive})
elif host == "k7":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC16" , "isa":"AVX512KNL", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17" , "isa":"AVX512KNL", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4" , "isa":"AVX512KNL", "tasking":"TBB", "intensive":"ON"})
elif host == "skylake-b0":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17" , "isa":"AVX512SKX", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4" , "isa":"AVX512SKX", "tasking":"TBB", "intensive":"ON"})
elif host == "tcg-vis-ci-ubuntu1604" or host == "tcg-vis-ubuntu1404":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"SSE2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX" , "tasking":"INT", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"SSE2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"AVX" , "tasking":"INT", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"AVX2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC16" , "isa":"SSE2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC15" , "isa":"AVX" , "tasking":"INT", "intensive":"ON"})
if build == "RelWithDebInfo":
configs.append({"branch":branch, "platform":"x64", "build":"RelWithDebInfo", "compiler":"ICC18" , "isa":"AVX512SKX", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":"RelWithDebInfo", "compiler":"ICC17" , "isa":"AVX512KNL", "tasking":"TBB", "intensive":"ON", "memcheck":"ON"})
# configs.append({"branch":branch, "platform":"x64", "build":"Release", "compiler":"ICC17" , "isa":"AVX2", "tasking":"TBB", "intensive":"ON", "benchmark":"ON"})
else:
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17" , "isa":"AVX2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "ISPC_SUPPORT":"OFF", "test":False})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "STATIC_LIB":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "TUTORIALS":"OFF", "test":False})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "BACKFACE_CULLING":"ON", "test":False})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "IGNORE_INVALID_RAYS":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "INTERSECTION_FILTER":"OFF", "test":False})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "RAY_MASK":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "RAY_PACKETS":"OFF"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "STAT_COUNTERS":"ON", "test":False})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["SSE2"], "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["SSE42"], "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["AVX"] , "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["AVX2"] , "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["AVX512KNL"], "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["AVX512SKX"], "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG4", "isa":["AVX2","AVX512SKX"] , "tasking":"TBB", "test":False })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "test":False,
"TRIS":"ON", "QUADS":"OFF", "LINES":"OFF", "HAIR":"OFF", "SUBDIV":"OFF", "USERGEOM":"OFF" })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "test":False,
"TRIS":"OFF", "QUADS":"ON", "LINES":"OFF", "HAIR":"OFF", "SUBDIV":"OFF", "USERGEOM":"OFF" })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "test":False,
"TRIS":"OFF", "QUADS":"OFF", "LINES":"ON", "HAIR":"OFF", "SUBDIV":"OFF", "USERGEOM":"OFF" })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "test":False,
"TRIS":"OFF", "QUADS":"OFF", "LINES":"OFF", "HAIR":"ON", "SUBDIV":"OFF", "USERGEOM":"OFF" })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "test":False,
"TRIS":"OFF", "QUADS":"OFF", "LINES":"OFF", "HAIR":"OFF", "SUBDIV":"ON", "USERGEOM":"OFF" })
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "test":False,
"TRIS":"OFF", "QUADS":"OFF", "LINES":"OFF", "HAIR":"OFF", "SUBDIV":"OFF", "USERGEOM":"ON" })
elif host == "tcg-vis-mac-mini":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"SSE2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX" , "tasking":"INT", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG", "isa":"AVX2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"SSE2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"AVX" , "tasking":"INT", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"GCC" , "isa":"AVX2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC16" , "isa":"SSE2", "tasking":"TBB", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC15" , "isa":"AVX" , "tasking":"INT", "intensive":"ON"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"CLANG" , "isa":"AVX2" , "tasking":"TBB", "STATIC_LIB":"ON"})
# configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17" , "isa":"AVX2", "tasking":"TBB", "intensive":"ON"})
return configs
# intensive testing
def createConfigsPackage(branch,build,host):
configs = []
isa_windows = ["SSE2","SSE42","AVX","AVX2","AVX512SKX"]
isa_linux = ["SSE2","SSE42","AVX","AVX2","AVX512KNL","AVX512SKX"]
isa_macosx = ["SSE2","SSE42","AVX","AVX2"]
if host == "tcg-vis-ci-win1":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":isa_windows, "tasking":"TBB", "intensive":"ON", "package":"ZIP"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":isa_windows, "tasking":"TBB", "intensive":"ON", "package":"RPM"})
elif host == "swr-ivb-lnx-01":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":isa_linux, "tasking":"TBB", "intensive":"ON", "package":"ZIP"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC17", "isa":isa_linux, "tasking":"TBB", "intensive":"ON", "package":"RPM"})
elif host == "tcg-vis-mac-mini":
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC16", "isa":isa_macosx, "tasking":"TBB", "intensive":"ON", "package":"ZIP"})
configs.append({"branch":branch, "platform":"x64", "build":build, "compiler":"ICC16", "isa":isa_macosx, "tasking":"TBB", "intensive":"ON", "package":"RPM"})
return configs
def string_of_isa(isa):
if type(isa) == str: return isa;
else: return "ISAS-" + ("-".join(isa))
def createTest(config,OS):
platform = config["platform"]
build = config["build"]
compiler = config["compiler"]
isa = config["isa"]
tasking = config["tasking"]
if "intensive" in config: intensive = config["intensive"]
else : intensive = "OFF"
if "memcheck" in config: memcheck = config["memcheck"]
else : memcheck = "OFF"
if "benchmark" in config: benchmark = config["benchmark"]
else : benchmark = "OFF"
if "sde" in config: sde = config["sde"]
else : sde = "OFF"
if "test" in config: skip_testing = not config["test"]
else : skip_testing = False
if tasking == "INT": tasking = "INTERNAL"
if tasking == "PPL": tasking = "PPL"
name = "gitlab-"+platform+"-"+build+"-"+compiler+"-"+string_of_isa(isa)+"-"+tasking
if "package" in config:
c.append("-D EMBREE_STACK_PROTECTOR=ON")
if config["package"] == "ZIP": name = name + "-package-zip"
else : name = name + "-package-installer"
if "klocwork" in config: name = name + "-klocwork"
ispc_ext = "-vs2013"
c = [] # CMake configuration
e = [] # shell environment
if "package" in config and OS == 'linux': # we need up to date cmake for RPMs to work properly
e.append("module load cmake")
c.append("-D CMAKE_BUILD_TYPE="+build+"")
if OS == "windows":
ext = ""
if platform == "x64":
ext = " Win64"
if (compiler == "V141"):
c.append("-G \"Visual Studio 15 2017"+ext+"\"")
c.append("-T \"V141\"")
ispc_ext = "-vs2015"
elif (compiler == "V140"):
c.append("-G \"Visual Studio 14 2015"+ext+"\"")
c.append("-T \"V140\"")
ispc_ext = "-vs2015"
elif (compiler == "V120"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"V120\"")
elif (compiler == "V110"):
c.append("-G \"Visual Studio 11 2012"+ext+"\"")
c.append("-T \"V110\"")
elif (compiler == "ICC"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"Intel C++ Compiler 17.0\"")
elif (compiler == "ICC18"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"Intel C++ Compiler 18.0\"")
elif (compiler == "ICC17"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"Intel C++ Compiler 17.0\"")
elif (compiler == "ICC16"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"Intel C++ Compiler 16.0\"")
elif (compiler == "ICC15"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"Intel C++ Compiler XE 15.0\"")
elif (compiler == "CLANG"):
c.append("-G \"Visual Studio 12 2013"+ext+"\"")
c.append("-T \"LLVM-vs2013\"")
else:
raise ValueError('unknown compiler: ' + compiler + '')
else:
if (compiler == "ICC18"):
c.append("-D CMAKE_CXX_COMPILER=icpc -D CMAKE_C_COMPILER=icc")
e.append("module load intel/2018")
elif (compiler == "ICC17"):
c.append("-D CMAKE_CXX_COMPILER=icpc -D CMAKE_C_COMPILER=icc")
e.append("module load intel/2017")
elif (compiler == "ICC16"):
c.append("-D CMAKE_CXX_COMPILER=icpc -D CMAKE_C_COMPILER=icc")
e.append("module load intel/2016")
elif (compiler == "ICC15"):
c.append("-D CMAKE_CXX_COMPILER=icpc -D CMAKE_C_COMPILER=icc")
e.append("module load intel/2015")
elif (compiler == "ICC"):
c.append("-D CMAKE_CXX_COMPILER=icpc -D CMAKE_C_COMPILER=icc")
e.append("module load intel")
elif (compiler == "GCC"):
c.append("-D CMAKE_CXX_COMPILER=g++ -D CMAKE_C_COMPILER=gcc")
elif (compiler == "CLANG4"):
c.append("-D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang")
e.append("module load clang/4")
elif (compiler == "CLANG3.9"):
c.append("-D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang")
e.append("module load clang/3.9")
elif (compiler == "CLANG3.8"):
c.append("-D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang")
e.append("module load clang/3.8")
elif (compiler == "CLANG"):
c.append("-D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang")
else:
raise ValueError('unknown compiler: ' + compiler + '')
if type(isa) == str:
c.append("-D EMBREE_MAX_ISA="+isa+"")
else:
c.append("-D EMBREE_MAX_ISA=NONE")
if "SSE2" in isa: c.append("-D EMBREE_ISA_SSE2=ON")
else : c.append("-D EMBREE_ISA_SSE2=OFF")
if "SSE42" in isa: c.append("-D EMBREE_ISA_SSE42=ON")
else : c.append("-D EMBREE_ISA_SSE42=OFF")
if "AVX" in isa: c.append("-D EMBREE_ISA_AVX=ON")
else : c.append("-D EMBREE_ISA_AVX=OFF")
if "AVX2" in isa: c.append("-D EMBREE_ISA_AVX2=ON")
else : c.append("-D EMBREE_ISA_AVX2=OFF")
if "AVX512KNL" in isa: c.append("-D EMBREE_ISA_AVX512KNL=ON")
else : c.append("-D EMBREE_ISA_AVX512KNL=OFF")
if "AVX512SKX" in isa: c.append("-D EMBREE_ISA_AVX512SKX=ON")
else : c.append("-D EMBREE_ISA_AVX512SKX=OFF")
c.append("-D EMBREE_TASKING_SYSTEM="+tasking+"")
c.append("-D EMBREE_TESTING_MEMCHECK="+memcheck+"")
c.append("-D EMBREE_TESTING_INTENSIVE="+intensive+"")
c.append("-D EMBREE_TESTING_SDE="+sde+"")
ispc_enabled = True
if "ISPC_SUPPORT" in config:
c.append("-D EMBREE_ISPC_SUPPORT="+config["ISPC_SUPPORT"])
if config["ISPC_SUPPORT"] == "OFF": name += "-noispc"
ispc_enabled = False
if "STATIC_LIB" in config:
c.append("-D EMBREE_STATIC_LIB="+config["STATIC_LIB"])
if config["STATIC_LIB"] == "ON": name += "-static"
if "TUTORIALS" in config:
c.append("-D EMBREE_TUTORIALS="+config["TUTORIALS"])
if config["TUTORIALS"] == "OFF": name += "-notutorials"
if "BACKFACE_CULLING" in config:
c.append("-D EMBREE_BACKFACE_CULLING="+config["BACKFACE_CULLING"])
if config["BACKFACE_CULLING"] == "ON": name += "-backfaceculling"
if "IGNORE_INVALID_RAYS" in config:
c.append("-D EMBREE_IGNORE_INVALID_RAYS="+config["IGNORE_INVALID_RAYS"])
if config["IGNORE_INVALID_RAYS"] == "ON": name += "-noinvalid"
if "INTERSECTION_FILTER" in config:
c.append("-D EMBREE_INTERSECTION_FILTER="+config["INTERSECTION_FILTER"])
if config["INTERSECTION_FILTER"] == "OFF": name += "-nofilter"
if "RAY_MASK" in config:
c.append("-D EMBREE_RAY_MASK="+config["RAY_MASK"])
if config["RAY_MASK"] == "ON": name += "-raymask"
if "RAY_PACKETS" in config:
c.append("-D EMBREE_RAY_PACKETS="+config["RAY_PACKETS"])
if config["RAY_PACKETS"] == "OFF": name += "-nopackets"
if "STAT_COUNTERS" in config:
c.append("-D EMBREE_STAT_COUNTERS="+config["STAT_COUNTERS"])
if config["STAT_COUNTERS"] == "ON": name += "-stats"
if "TRIS" in config:
c.append("-D EMBREE_GEOMETRY_TRIANGLES="+config["TRIS"])
if config["TRIS"] == "ON": name += "-tris"
if "QUADS" in config:
c.append("-D EMBREE_GEOMETRY_QUADS="+config["QUADS"])
if config["QUADS"] == "ON": name += "-quads"
if "LINES" in config:
c.append("-D EMBREE_GEOMETRY_LINES="+config["LINES"])
if config["LINES"] == "ON": name += "-lines"
if "HAIR" in config:
c.append("-D EMBREE_GEOMETRY_HAIR="+config["HAIR"])
if config["HAIR"] == "ON": name += "-hair"
if "SUBDIV" in config:
c.append("-D EMBREE_GEOMETRY_SUBDIV="+config["SUBDIV"])
if config["SUBDIV"] == "ON": name += "-subdiv"
if "USERGEOM" in config:
c.append("-D EMBREE_GEOMETRY_USER="+config["USERGEOM"])
if config["USERGEOM"] == "ON": name += "-usergeom"
if OS == "linux":
if ispc_enabled: c.append("-D EMBREE_ISPC_EXECUTABLE=/NAS/packages/apps/ispc/1.9.1/ispc")
if tasking == "TBB": c.append("-D EMBREE_TBB_ROOT=/NAS/packages/apps/tbb/tbb-2017-linux")
elif OS == "macosx":
{}
#if ispc_enabled: c.append("-D EMBREE_ISPC_EXECUTABLE="+os.getcwd()+"/dependencies/ispc-v1.9.1-osx/ispc")
#if tasking == "TBB": c.append("-D EMBREE_TBB_ROOT="+os.getcwd()+dash+"dependencies"+dash+"tbb-2017-osx")
elif OS == "windows":
#if ispc_enabled:
#c.append("-D EMBREE_ISPC_EXECUTABLE="+os.getcwd()+dash+"dependencies"+dash+"ispc-v1.9.1-windows"+ispc_ext+dash+"ispc.exe")
if tasking == "TBB":
#tbb_path = os.getcwd()+dash+"dependencies"+dash+"tbb-2017-windows"
#c.append("-D EMBREE_TBB_ROOT="+tbb_path)
if platform == "x64":
e.append("set PATH="+tbb_path+"\\bin\\intel64\\vc12;%PATH%")
else:
e.append("set PATH="+tbb_path+"\\bin\\ia32\\vc12;%PATH%")
else:
sys.stderr.write("unknown operating system "+OS)
sys.exit(1)
if "klocwork" in config:
c.append("-D EMBREE_TESTING_KLOCWORK="+config["klocwork"])
if "package" in config:
c.append("-D EMBREE_TESTING_PACKAGE=ON")
c.append("-D EMBREE_TUTORIALS_IMAGE_MAGICK=OFF")
c.append("-D EMBREE_TUTORIALS_LIBJPEG=OFF")
c.append("-D EMBREE_TUTORIALS_LIBPNG=OFF")
c.append("-D EMBREE_TUTORIALS_OPENEXR=OFF")
if OS == "linux" and config["package"] == "ZIP":
c.append("-D EMBREE_ZIP_MODE=ON")
c.append("-D CMAKE_SKIP_INSTALL_RPATH=ON")
c.append("-D CMAKE_INSTALL_INCLUDEDIR=include")
c.append("-D CMAKE_INSTALL_LIBDIR=lib")
c.append("-D CMAKE_INSTALL_DOCDIR=doc")
c.append("-D CMAKE_INSTALL_BINDIR=bin")
elif OS == "linux" and config["package"] == "RPM":
c.append("-D EMBREE_ZIP_MODE=OFF")
c.append("-D CMAKE_SKIP_INSTALL_RPATH=OFF")
c.append("-D CMAKE_INSTALL_PREFIX=/usr")
c.append("-D EMBREE_TBB_ROOT=/usr")
elif OS == "macosx" and config["package"] == "ZIP":
c.append("-D EMBREE_ZIP_MODE=ON")
c.append("-D CMAKE_SKIP_INSTALL_RPATH=ON")
c.append("-D CMAKE_MACOSX_RPATH=ON")
c.append("-D CMAKE_INSTALL_INCLUDEDIR=include")
c.append("-D CMAKE_INSTALL_LIBDIR=lib")
c.append("-D CMAKE_INSTALL_DOCDIR=doc")
c.append("-D CMAKE_INSTALL_BINDIR=bin")
elif OS == "macosx" and config["package"] == "RPM":
c.append("-D EMBREE_ZIP_MODE=OFF")
c.append("-D CMAKE_SKIP_INSTALL_RPATH=OFF")
c.append("-D CMAKE_INSTALL_PREFIX=/opt/local")
c.append("-D CMAKE_INSTALL_INCLUDEDIR=include")
c.append("-D CMAKE_INSTALL_LIBDIR=lib")
c.append("-D CMAKE_INSTALL_DOCDIR=../../Applications/Embree2/doc")
c.append("-D CMAKE_INSTALL_BINDIR=../../Applications/Embree2/bin")
c.append("-D EMBREE_TBB_ROOT=/opt/local")
elif OS == "windows" and config["package"] == "ZIP":
c.append("-D EMBREE_ZIP_MODE=ON")
c.append("-D CMAKE_INSTALL_INCLUDEDIR=include")
c.append("-D CMAKE_INSTALL_LIBDIR=lib")
c.append("-D CMAKE_INSTALL_DATAROOTDIR=")
c.append("-D CMAKE_INSTALL_DOCDIR=doc")
c.append("-D CMAKE_INSTALL_BINDIR=bin")
elif OS == "windows" and config["package"] == "RPM":
c.append("-D EMBREE_ZIP_MODE=OFF")
c.append("-D CMAKE_INSTALL_INCLUDEDIR=include")
c.append("-D CMAKE_INSTALL_LIBDIR=lib")
c.append("-D CMAKE_INSTALL_DATAROOTDIR=")
c.append("-D CMAKE_INSTALL_DOCDIR=doc")
c.append("-D CMAKE_INSTALL_BINDIR=bin")
else:
sys.stderr.write("unknown package mode: "+OS+":"+config["package"])
sys.exit(1)
return [name,build,skip_testing,benchmark,c,e]
# runs all tests for specified host machine
def runConfig(cfg):
[name,build,skip_testing,benchmark,conf,env] = createTest(cfg,OS)
ctest = ""
ctest += "ctest -VV -S scripts/test.cmake"
if g_cdash != "": ctest += " -D CTEST_DROP_SITE="+g_cdash
ctest += " -D TEST_NAME=\""+name+"\""
if skip_testing: ctest += " -D CTEST_SKIP_TESTING=ON"
else : ctest += " -D CTEST_SKIP_TESTING=OFF"
ctest += " -D CTEST_CONFIGURATION_TYPE=\""+build+"\""
ctest += " -D CTEST_BUILD_OPTIONS=\"" + escape(" ".join(conf))+"\""
if g_debugMode:
print(name)
for e in env: print(' '+e)
print(' '+ctest+'\n')
else:
cmd = ""
for e in env: cmd += e + " && "
cmd += ctest+"\n"
subprocess.check_call(cmd, shell=True)
#if OS == "windows":
# subprocess.Popen(cmd, shell=True).communicate()
#else: # we have to use a login shell to make "module load xxx" work
# cmd = "export http_proxy= && export https_proxy= && " + cmd # cdash submission fails when proxy servers set
# subprocess.Popen(['bash', '-l'], stdin=subprocess.PIPE).communicate(input=cmd.encode("utf-8"))
def parseCommandLine(argv):
global g_cdash
global g_config
global g_mode
global g_intensive
global g_debugMode
if len(argv) == 0:
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]
parseCommandLine(argv[2:len(argv)])
elif len(argv)>=1 and argv[0] == "--intensive":
g_intensive = True
parseCommandLine(argv[1:len(argv)])
elif len(argv)>=1 and argv[0] == "--debug":
g_debugMode = True
parseCommandLine(argv[1:len(argv)])
elif len(argv)>=1 and argv[0] == "--help":
printUsage()
return;
elif ':' in argv[0]:
p = argv[0].split(":")
g_config[p[0]] = p[1]
parseCommandLine(argv[1:len(argv)])
else:
sys.stderr.write("unknown command line option: "+argv[0])
sys.exit(1)
parseCommandLine(sys.argv[1:len(sys.argv)])
runConfig(g_config)
+4 -6
View File
@@ -238,7 +238,7 @@ namespace embree
if (features & FEATURE_STREAM)
{
/* register parsing of stream mode */
registerOption("mode", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("mode", [] (Ref<ParseStream> cin, const FileName& path) {
std::string mode = cin->getString();
if (mode == "normal") g_mode = MODE_NORMAL;
else if (mode == "stream") g_mode = MODE_STREAM;
@@ -744,8 +744,9 @@ namespace embree
{
/* update camera */
camera.move(moveDelta.x*speed, moveDelta.y*speed, moveDelta.z*speed);
ISPCCamera ispccamera = camera.getISPCCamera(width,height,true);
if (print_camera)
std::cout << camera.str() << std::endl;
/* render image using ISPC */
initRayStats();
@@ -819,10 +820,7 @@ namespace embree
stream << dt1*1000.0f << " ms, ";
stream << width << "x" << height << " pixels";
std::cout << stream.str() << std::endl;
}
if (print_camera)
std::cout << camera.str() << std::endl;
}
}
void TutorialApplication::reshapeFunc(int width, int height)
+2 -2
View File
@@ -287,12 +287,12 @@ float Noise(float x, float y, float z)
Tutorial()
: TutorialApplication("hair_geometry",FEATURE_RTCORE)
{
registerOption("ambientlight", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("ambientlight", [] (Ref<ParseStream> cin, const FileName& path) {
g_ambient_intensity = cin->getVec3fa();
}, "--ambientlight r g b: adds an ambient light with intensity rgb");
registerOptionAlias("ambientlight","ambient");
registerOption("directionallight", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("directionallight", [] (Ref<ParseStream> cin, const FileName& path) {
g_dirlight_direction = normalize(cin->getVec3fa());
g_dirlight_intensity = cin->getVec3fa();
}, "--directionallight x y z r g b: adds a directional light with direction xyz and intensity rgb");
@@ -77,7 +77,7 @@ void convertHairSet(ISPCHairSet* hair, RTCScene scene_out)
}
rtcSetBuffer(scene_out,geomID,RTC_INDEX_BUFFER,hair->hairs,0,sizeof(ISPCHair));
rtcSetOcclusionFilterFunction(scene_out,geomID,filterDispatch);
rtcSetTessellationRate(scene_out,geomID,hair->tessellation_rate);
rtcSetTessellationRate(scene_out,geomID,(float)hair->tessellation_rate);
}
RTCScene convertScene(ISPCScene* scene_in)
@@ -29,16 +29,16 @@ namespace embree
Tutorial()
: TutorialApplication("motion_blur_geometry",FEATURE_RTCORE)
{
registerOption("time", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("time", [] (Ref<ParseStream> cin, const FileName& path) {
g_time = cin->getFloat();
}, "--time <float>: time to render image at");
registerOption("time-steps", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("time-steps", [] (Ref<ParseStream> cin, const FileName& path) {
g_num_time_steps = cin->getInt();
if (g_num_time_steps < 2) throw std::runtime_error("at least 2 time steps have to be used");
}, "--time-steps <int>: number of time steps to use");
registerOption("time-steps2", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("time-steps2", [] (Ref<ParseStream> cin, const FileName& path) {
g_num_time_steps2 = cin->getInt();
if (g_num_time_steps2 < 2) throw std::runtime_error("at least 2 time steps have to be used");
}, "--time-steps2 <int>: number of time steps to use");
+2
View File
@@ -17,3 +17,5 @@
INCLUDE(tutorial)
ADD_TUTORIAL(pathtracer)
ADD_EMBREE_MODELS_TEST(pathtracer pathtracer pathtracer)
ADD_EMBREE_MODELS_TEST(pathtracer_coherent pathtracer pathtracer --coherent)
ADD_EMBREE_MODELS_TEST(pathtracer_incoherent pathtracer pathtracer --incoherent)
+2 -2
View File
@@ -28,11 +28,11 @@ namespace embree
Tutorial()
: SceneLoadingTutorialApplication("pathtracer",FEATURE_RTCORE)
{
registerOption("spp", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("spp", [] (Ref<ParseStream> cin, const FileName& path) {
g_spp = cin->getInt();
}, "--spp: sets number of samples per pixel");
registerOption("accumulate", [this] (Ref<ParseStream> cin, const FileName& path) {
registerOption("accumulate", [] (Ref<ParseStream> cin, const FileName& path) {
g_accumulate = cin->getInt();
}, "--accumulate <bool>: accumulate samples (on by default)");
}
+2 -1
View File
@@ -1461,6 +1461,7 @@ Vec3fa renderPixelFunction(float x, float y, RandomSampler& sampler, const ISPCC
c = c * Material__sample(material_array,materialID,numMaterials,brdf,Lw, wo, dg, wi1, medium, RandomSampler_get2D(sampler));
/* iterate over lights */
context.flags = g_iflags_incoherent;
for (size_t i=0; i<g_ispc_scene->numLights; i++)
{
const Light* l = g_ispc_scene->lights[i];
@@ -1501,7 +1502,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats&
float fy = y + RandomSampler_get1D(sampler);
L = L + renderPixelFunction(fx,fy,sampler,camera,stats);
}
L = L/g_spp;
L = L/(float)g_spp;
return L;
}
@@ -1459,6 +1459,7 @@ Vec3f renderPixelFunction(float x, float y, RandomSampler& sampler, const unifor
c = c * Material__sample(material_array,materialID,numMaterials,brdf,Lw, wo, dg, wi1, medium, RandomSampler_get2D(sampler));
/* iterate over lights */
context.flags = g_iflags_incoherent;
for (uniform size_t i=0; i<g_ispc_scene->numLights; i++)
{
const uniform Light* uniform l = g_ispc_scene->lights[i];
+42 -39
View File
@@ -664,7 +664,7 @@ namespace embree
}
template<int N>
inline void IntersectWithNMMode(IntersectVariant ivariant, RTCScene scene, RTCIntersectContext* context, RTCRay* rays, size_t Nrays)
__noinline void IntersectWithNMMode(IntersectVariant ivariant, RTCScene scene, RTCIntersectContext* context, RTCRay* rays, size_t Nrays)
{
assert(Nrays<1024);
const size_t alignment = size_t(rays) % 64;
@@ -693,8 +693,45 @@ namespace embree
for (size_t j=0; j<L; j++) rays[i+j] = getRay(ray,N,j);
}
}
__noinline void IntersectWithNpMode(IntersectVariant ivariant, RTCScene scene, RTCIntersectContext* context, RTCRay* rays, size_t N)
{
assert(N < 1024);
const size_t alignment = size_t(rays) % 64;
__aligned(64) char data[1024 * sizeof(RTCRay) + 64];
RTCRayN* ray = (RTCRayN*)&data[alignment];
for (size_t j = 0; j < N; j++) setRay(ray, N, j, rays[j]);
inline void IntersectWithModeInternal(IntersectMode mode, IntersectVariant ivariant, RTCScene scene, RTCRay* rays, size_t N)
RTCRayNp rayp;
rayp.orgx = &RTCRayN_org_x(ray, N, 0);
rayp.orgy = &RTCRayN_org_y(ray, N, 0);
rayp.orgz = &RTCRayN_org_z(ray, N, 0);
rayp.dirx = &RTCRayN_dir_x(ray, N, 0);
rayp.diry = &RTCRayN_dir_y(ray, N, 0);
rayp.dirz = &RTCRayN_dir_z(ray, N, 0);
rayp.tnear = &RTCRayN_tnear(ray, N, 0);
rayp.tfar = &RTCRayN_tfar(ray, N, 0);
rayp.time = &RTCRayN_time(ray, N, 0);
rayp.mask = &RTCRayN_mask(ray, N, 0);
rayp.instID = &RTCRayN_instID(ray, N, 0);
rayp.geomID = &RTCRayN_geomID(ray, N, 0);
rayp.primID = &RTCRayN_primID(ray, N, 0);
rayp.u = &RTCRayN_u(ray, N, 0);
rayp.v = &RTCRayN_v(ray, N, 0);
rayp.Ngx = &RTCRayN_Ng_x(ray, N, 0);
rayp.Ngy = &RTCRayN_Ng_y(ray, N, 0);
rayp.Ngz = &RTCRayN_Ng_z(ray, N, 0);
switch (ivariant & VARIANT_INTERSECT_OCCLUDED_MASK) {
case VARIANT_INTERSECT: rtcIntersectNp(scene, context, rayp, N); break;
case VARIANT_OCCLUDED: rtcOccludedNp(scene, context, rayp, N); break;
default: assert(false);
}
for (size_t j = 0; j < N; j++) rays[j] = getRay(ray, N, j);
}
__noinline void IntersectWithModeInternal(IntersectMode mode, IntersectVariant ivariant, RTCScene scene, RTCRay* rays, size_t N)
{
RTCIntersectContext context;
context.flags = ((ivariant & VARIANT_COHERENT_INCOHERENT_MASK) == VARIANT_COHERENT) ? RTC_INTERSECT_COHERENT : RTC_INTERSECT_INCOHERENT;
@@ -812,48 +849,14 @@ namespace embree
IntersectWithNMMode<16>(ivariant,scene,&context,rays,N);
break;
}
case MODE_INTERSECTNp:
{
assert(N<1024);
const size_t alignment = size_t(rays) % 64;
__aligned(64) char data[1024*sizeof(RTCRay)+64];
RTCRayN* ray = (RTCRayN*) &data[alignment];
for (size_t j=0; j<N; j++) setRay(ray,N,j,rays[j]);
RTCRayNp rayp;
rayp.orgx = &RTCRayN_org_x(ray,N,0);
rayp.orgy = &RTCRayN_org_y(ray,N,0);
rayp.orgz = &RTCRayN_org_z(ray,N,0);
rayp.dirx = &RTCRayN_dir_x(ray,N,0);
rayp.diry = &RTCRayN_dir_y(ray,N,0);
rayp.dirz = &RTCRayN_dir_z(ray,N,0);
rayp.tnear = &RTCRayN_tnear(ray,N,0);
rayp.tfar = &RTCRayN_tfar(ray,N,0);
rayp.time = &RTCRayN_time(ray,N,0);
rayp.mask = &RTCRayN_mask(ray,N,0);
rayp.instID = &RTCRayN_instID(ray,N,0);
rayp.geomID = &RTCRayN_geomID(ray,N,0);
rayp.primID = &RTCRayN_primID(ray,N,0);
rayp.u = &RTCRayN_u(ray,N,0);
rayp.v = &RTCRayN_v(ray,N,0);
rayp.Ngx = &RTCRayN_Ng_x(ray,N,0);
rayp.Ngy = &RTCRayN_Ng_y(ray,N,0);
rayp.Ngz = &RTCRayN_Ng_z(ray,N,0);
switch (ivariant & VARIANT_INTERSECT_OCCLUDED_MASK) {
case VARIANT_INTERSECT: rtcIntersectNp(scene,&context,rayp,N); break;
case VARIANT_OCCLUDED : rtcOccludedNp(scene,&context,rayp,N); break;
default: assert(false);
}
for (size_t j=0; j<N; j++) rays[j] = getRay(ray,N,j);
case MODE_INTERSECTNp: {
IntersectWithNpMode(ivariant, scene, &context, rays, N);
break;
}
}
}
inline void IntersectWithMode(IntersectMode mode, IntersectVariant ivariant, RTCScene scene, RTCRay* rays, size_t N)
void IntersectWithMode(IntersectMode mode, IntersectVariant ivariant, RTCScene scene, RTCRay* rays, size_t N)
{
/* verify occluded result against intersect */
if ((ivariant & VARIANT_INTERSECT_OCCLUDED) == VARIANT_INTERSECT_OCCLUDED)
+4 -2
View File
@@ -16,8 +16,10 @@
INCLUDE(tutorial)
ADD_TUTORIAL(viewer)
ADD_EMBREE_MODELS_TEST(viewer viewer viewer)
ADD_EMBREE_MODELS_TEST(viewer_quad viewer viewer -convert-triangles-to-quads)
ADD_EMBREE_MODELS_TEST(viewer_coherent viewer viewer --coherent)
ADD_EMBREE_MODELS_TEST(viewer_incoherent viewer viewer --incoherent)
ADD_EMBREE_MODELS_TEST(viewer_quad_coherent viewer viewer -convert-triangles-to-quads)
ADD_EMBREE_MODELS_TEST(viewer_quad_incoherent viewer viewer -convert-triangles-to-quads --incoherent)
ADD_EMBREE_SUBDIV_MODELS_TEST(viewer viewer viewer viewer)
IF (EMBREE_TESTING_INTENSIVE)
+1 -1
View File
@@ -268,7 +268,7 @@ Vec3fa renderPixelStandard(float x, float y, const ISPCCamera& camera, RayStats&
/* intersect ray with scene */
RTCIntersectContext context;
context.flags = RTC_INTERSECT_COHERENT;
context.flags = g_iflags_coherent;
rtcIntersect1Ex(g_scene,&context,ray);
RayStats_addRay(stats);
+1 -1
View File
@@ -258,7 +258,7 @@ Vec3f renderPixelStandard(float x, float y, const uniform ISPCCamera& camera, un
/* intersect ray with scene */
uniform RTCIntersectContext context;
context.flags = RTC_INTERSECT_COHERENT;
context.flags = g_iflags_coherent;
rtcIntersectEx(g_scene,&context,ray);
RayStats_addRay(stats);
@@ -26,7 +26,7 @@ namespace embree {
//#define rtcOccluded rtcIntersect
//#define rtcOccluded1M rtcIntersect1M
#define SIMPLE_SHADING 1
#define SIMPLE_SHADING 0
extern "C" ISPCScene* g_ispc_scene;
@@ -163,7 +163,7 @@ void renderTileStandard(int taskIndex,
rtcIntersect1M(g_scene,&context,rays,N,sizeof(RTCRay));
#elif USE_INTERFACE == 1
for (size_t i=0; i<N; i++)
rtcIntersect(g_scene,rays[i]);
rtcIntersect1Ex(g_scene,&context,rays[i]);
#else
for (size_t i=0; i<N; i++)
rtcIntersect1M(g_scene,&context,&rays[i],1,sizeof(RTCRay));
@@ -24,7 +24,7 @@
//#define rtcOccluded rtcIntersect
//#define rtcOccludedVM rtcIntersectVM
#define SIMPLE_SHADING 1
#define SIMPLE_SHADING 0
extern uniform ISPCScene* uniform g_ispc_scene;
@@ -167,7 +167,6 @@ void renderTileStandard(uniform int taskIndex,
rtcIntersectVM(g_scene,&context,&rays[i],1,sizeof(RTCRay));
#endif
#if 1
/* shade stream of rays */
N = 0;
foreach_tiled (y = y0 ... y1, x = x0 ... x1)
@@ -191,7 +190,6 @@ void renderTileStandard(uniform int taskIndex,
unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f));
pixels[y*width+x] = (b << 16) + (g << 8) + r;
}
#endif
}
/* task that renders a single screen tile */