Compare commits
358
Commits
release
...
sycl_stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c539c3e9b | ||
|
|
db6e680325 | ||
|
|
c8288045ea | ||
|
|
a2f51f16bf | ||
|
|
22ca07cb3f | ||
|
|
77fed4d218 | ||
|
|
43bfb0966a | ||
|
|
a804fcd873 | ||
|
|
2b5581a581 | ||
|
|
78ef8476ca | ||
|
|
1a3c3ef2bb | ||
|
|
1c591829bb | ||
|
|
b051d35e4d | ||
|
|
501d81964a | ||
|
|
0a25869c0d | ||
|
|
15d50637e9 | ||
|
|
a17eb57780 | ||
|
|
d204039384 | ||
|
|
e839fb310f | ||
|
|
c8900a5a4c | ||
|
|
f525bf88fc | ||
|
|
8a5acfceb3 | ||
|
|
25ecb8b35c | ||
|
|
3966b99862 | ||
|
|
f86ac79968 | ||
|
|
255ad42fea | ||
|
|
e05d2c0b9d | ||
|
|
5f52ff3583 | ||
|
|
22e64801ce | ||
|
|
26b929734e | ||
|
|
86f6ec6433 | ||
|
|
4ea282f0c8 | ||
|
|
c232392335 | ||
|
|
6360dcba5c | ||
|
|
163636399e | ||
|
|
725f0e6259 | ||
|
|
d3a2a5e872 | ||
|
|
3da1dc0bad | ||
|
|
e9e3387dda | ||
|
|
ca8af6f7e9 | ||
|
|
45a1667211 | ||
|
|
a64ea4c043 | ||
|
|
08ac6ce20f | ||
|
|
b473755889 | ||
|
|
f3a1200841 | ||
|
|
7621a6bea1 | ||
|
|
6994e405cc | ||
|
|
c48ce76adc | ||
|
|
6a7daed2bb | ||
|
|
fd5ea59117 | ||
|
|
f28f7eb4f5 | ||
|
|
84f61f9c71 | ||
|
|
0f884c9342 | ||
|
|
d4d32c392a | ||
|
|
826eb9aef2 | ||
|
|
fbab9d87a4 | ||
|
|
e978963b89 | ||
|
|
a0e4508a00 | ||
|
|
86dcc2a40b | ||
|
|
9de5bacd81 | ||
|
|
8f1db409e6 | ||
|
|
a4baf0db09 | ||
|
|
5d9fb4937e | ||
|
|
34919811b6 | ||
|
|
f6e3b5a1ca | ||
|
|
46c89c537f | ||
|
|
8da10d31ee | ||
|
|
a814f62039 | ||
|
|
195f28336c | ||
|
|
9b413172b7 | ||
|
|
c22b17f5d1 | ||
|
|
fb430f58a0 | ||
|
|
b2337f7c1e | ||
|
|
e6a0bb88aa | ||
|
|
d55eb12d0e | ||
|
|
abe4c5a200 | ||
|
|
f03eeb9fa4 | ||
|
|
9197ab0095 | ||
|
|
3e45b6b1e2 | ||
|
|
8569234919 | ||
|
|
bdd40710b7 | ||
|
|
80f54b3a4d | ||
|
|
7e0798f329 | ||
|
|
0dbbe1986e | ||
|
|
183c7e00df | ||
|
|
696d09d41f | ||
|
|
e899659072 | ||
|
|
81e6aea43b | ||
|
|
75fdff2daf | ||
|
|
1ac4e0e7d0 | ||
|
|
f02ffaf2a3 | ||
|
|
efe4bbf708 | ||
|
|
e53bd68813 | ||
|
|
aff1b8a892 | ||
|
|
d4555d6a93 | ||
|
|
a7ed267a88 | ||
|
|
e25ebea61d | ||
|
|
c6c56e8faf | ||
|
|
1cdc1da6e1 | ||
|
|
d3b86a6ce0 | ||
|
|
654960f178 | ||
|
|
c0416b600c | ||
|
|
af0458922f | ||
|
|
1047a791a9 | ||
|
|
e2ee296b51 | ||
|
|
bcb4d3ec41 | ||
|
|
5fcd9ede79 | ||
|
|
6616c827ff | ||
|
|
644c81fdeb | ||
|
|
48090a347e | ||
|
|
791b07a297 | ||
|
|
eafceb14d7 | ||
|
|
26c77304c8 | ||
|
|
7741c659bc | ||
|
|
6a217105ff | ||
|
|
09f938aa79 | ||
|
|
8cff1df627 | ||
|
|
2fcc39aaec | ||
|
|
8fc8c7d745 | ||
|
|
02745407c1 | ||
|
|
5af7ce6b1c | ||
|
|
5710b2b993 | ||
|
|
f46e3e88a7 | ||
|
|
767ac7bb0a | ||
|
|
dfc03fe694 | ||
|
|
723bcd004a | ||
|
|
38b62acdd6 | ||
|
|
4ffcd740f5 | ||
|
|
383e254a94 | ||
|
|
ed98afda4a | ||
|
|
cf3abbec82 | ||
|
|
1db62bfe5b | ||
|
|
e877c78acc | ||
|
|
657a1f9751 | ||
|
|
44363d2bff | ||
|
|
9a46b465be | ||
|
|
8edf29d179 | ||
|
|
5c0b258b91 | ||
|
|
f33716072e | ||
|
|
16e295ca29 | ||
|
|
cd176187d7 | ||
|
|
db47037198 | ||
|
|
b4d10fc0fe | ||
|
|
de15d9cb6b | ||
|
|
e9bcc59877 | ||
|
|
661d3631c0 | ||
|
|
14af2c3e00 | ||
|
|
f2ef01c6a8 | ||
|
|
4e2760f76e | ||
|
|
6d3ff20b84 | ||
|
|
3a545c34e9 | ||
|
|
e10f199e55 | ||
|
|
65dddf452c | ||
|
|
bdbbb6a844 | ||
|
|
ebfc9116f4 | ||
|
|
71449762ed | ||
|
|
e062cbf14d | ||
|
|
1d79f7dfac | ||
|
|
37715726a0 | ||
|
|
d8d16b46e5 | ||
|
|
ce9e70be73 | ||
|
|
c248db1c75 | ||
|
|
23a3d91246 | ||
|
|
c22fedde2f | ||
|
|
b1ce99a1bf | ||
|
|
cf4601cbf5 | ||
|
|
1c01ef0541 | ||
|
|
ec67b001ac | ||
|
|
8340afdc48 | ||
|
|
0ba7904e10 | ||
|
|
83d03f5ff4 | ||
|
|
120572f140 | ||
|
|
2a9d7686fc | ||
|
|
19a669d294 | ||
|
|
2d41acb4db | ||
|
|
bf9e2f1791 | ||
|
|
425b572b6f | ||
|
|
58f305e645 | ||
|
|
c705db5f14 | ||
|
|
2ff35d4ef8 | ||
|
|
615110d256 | ||
|
|
e729819e3e | ||
|
|
23c82d464d | ||
|
|
ee8aa70fc6 | ||
|
|
bc9622b7dd | ||
|
|
0292f7c00c | ||
|
|
b70f70d24a | ||
|
|
584d55c7bf | ||
|
|
64b0c34769 | ||
|
|
57860ac6f5 | ||
|
|
d7e2c1cb3b | ||
|
|
6ac028e83c | ||
|
|
daeb2f0768 | ||
|
|
94f68bc100 | ||
|
|
ea57db0e49 | ||
|
|
0049d4d100 | ||
|
|
fadf381751 | ||
|
|
f9210cb471 | ||
|
|
84be1637c7 | ||
|
|
eeb3748819 | ||
|
|
f96ebc5fb3 | ||
|
|
2c18e8eb9f | ||
|
|
981a9390e5 | ||
|
|
919280b8fc | ||
|
|
ae73fa051e | ||
|
|
d7b663f1ac | ||
|
|
be717ff6c6 | ||
|
|
9a43f88e5c | ||
|
|
e52d56ff8c | ||
|
|
f85322566e | ||
|
|
faa8303382 | ||
|
|
a7ebec62ee | ||
|
|
f8861be1ce | ||
|
|
e32f0b7f24 | ||
|
|
976b13711c | ||
|
|
423b0b6d65 | ||
|
|
72eeeed34d | ||
|
|
218a004f7d | ||
|
|
24c4619d67 | ||
|
|
a431274108 | ||
|
|
a487f021a8 | ||
|
|
16d33a3268 | ||
|
|
f999c79ddf | ||
|
|
8476f5fe74 | ||
|
|
ef0f6ba977 | ||
|
|
21dd453dec | ||
|
|
6d8d752a83 | ||
|
|
4fb35c1144 | ||
|
|
9496d741e1 | ||
|
|
bcb54b9099 | ||
|
|
c95b346fc4 | ||
|
|
b9c84040f1 | ||
|
|
deccb6eb63 | ||
|
|
283514078f | ||
|
|
94db952ef6 | ||
|
|
4fe317bb52 | ||
|
|
f695109205 | ||
|
|
fe601f8509 | ||
|
|
c1df3629e0 | ||
|
|
1f430a9c3b | ||
|
|
e83ea3039e | ||
|
|
5a160bfdd5 | ||
|
|
428cefec6c | ||
|
|
308a67442e | ||
|
|
891a352967 | ||
|
|
7a4494efe0 | ||
|
|
1810141d97 | ||
|
|
d3701fdd36 | ||
|
|
3c22966cec | ||
|
|
aabee86bc3 | ||
|
|
d7882d4b81 | ||
|
|
3e4fa9613c | ||
|
|
31f5b20de8 | ||
|
|
71d3c6409d | ||
|
|
801220ed5d | ||
|
|
ea5133fe9d | ||
|
|
c5bb4b2e40 | ||
|
|
130b455be0 | ||
|
|
f2934a9f5d | ||
|
|
2a73d3f97d | ||
|
|
21492a112c | ||
|
|
ee76baca76 | ||
|
|
cf430a3ac4 | ||
|
|
1b7116b333 | ||
|
|
67f3f1d33f | ||
|
|
96ee4d5917 | ||
|
|
11d99d6722 | ||
|
|
6f7e3ecca4 | ||
|
|
ab1d6a7b49 | ||
|
|
c35c788a09 | ||
|
|
445810a1e7 | ||
|
|
92701d1e8c | ||
|
|
30a4760fa7 | ||
|
|
7f9c24005a | ||
|
|
74d838c981 | ||
|
|
d90b52f0bb | ||
|
|
5481b9fa16 | ||
|
|
ab711bb34a | ||
|
|
38c1b8f701 | ||
|
|
11c29c8561 | ||
|
|
26870da323 | ||
|
|
cd55a49d63 | ||
|
|
7907538a53 | ||
|
|
b44d736167 | ||
|
|
daf4450820 | ||
|
|
2a5ae73d01 | ||
|
|
e99200ca6e | ||
|
|
957475814f | ||
|
|
2cf4d08bad | ||
|
|
a9e03a598f | ||
|
|
ea33e05bea | ||
|
|
50ba2ab635 | ||
|
|
7b522de25b | ||
|
|
1eec731b10 | ||
|
|
a9a3a60efe | ||
|
|
41414000d4 | ||
|
|
a435db84ca | ||
|
|
96363fbdcf | ||
|
|
8b6e6ac862 | ||
|
|
2a77b9b624 | ||
|
|
38f801411a | ||
|
|
d57f7b7905 | ||
|
|
da2ffd6368 | ||
|
|
cebcc1d216 | ||
|
|
d8053e29ab | ||
|
|
d54d4fb03c | ||
|
|
1eae987941 | ||
|
|
6bc8231cfe | ||
|
|
91b80b2c0b | ||
|
|
cd4be2844f | ||
|
|
000acc1358 | ||
|
|
99677bb22d | ||
|
|
49b98b168f | ||
|
|
9a0f9a610e | ||
|
|
1157bb3384 | ||
|
|
ef28a21b63 | ||
|
|
ffe7d21945 | ||
|
|
c83f601508 | ||
|
|
3ea6f3ef8f | ||
|
|
9800fe45d8 | ||
|
|
d08cb07fcf | ||
|
|
f17d7c627a | ||
|
|
2fd16c26bb | ||
|
|
15c81b8218 | ||
|
|
058e9ce72a | ||
|
|
55f0680d3b | ||
|
|
e0dc1ee8fe | ||
|
|
fbca0fc7cc | ||
|
|
57b56531f3 | ||
|
|
7fa9f08b7b | ||
|
|
1b636a88ba | ||
|
|
7e80b37265 | ||
|
|
7abf88af73 | ||
|
|
9e2a8dcab4 | ||
|
|
5414ab5fcc | ||
|
|
8a5d3b6500 | ||
|
|
bfc0798962 | ||
|
|
b62ad99982 | ||
|
|
ab550c2381 | ||
|
|
b74e6d6ab0 | ||
|
|
3a85df53c6 | ||
|
|
350f214d95 | ||
|
|
48dced1260 | ||
|
|
f141ed5fae | ||
|
|
574ac598b1 | ||
|
|
023ee677d6 | ||
|
|
16753a99d1 | ||
|
|
d0fa655775 | ||
|
|
78eb9c2693 | ||
|
|
32a7efcecd | ||
|
|
b1b145c253 | ||
|
|
c21d7a5e7c | ||
|
|
b259057f2a | ||
|
|
8edf00e43a | ||
|
|
b190878fb0 | ||
|
|
c9bad6a566 | ||
|
|
5201912a41 | ||
|
|
684a3316ab |
+16
-2
@@ -97,7 +97,7 @@ INCLUDE(test)
|
||||
|
||||
GET_PROPERTY(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
|
||||
IF(SHARED_LIBS_SUPPORTED)
|
||||
OPTION(EMBREE_STATIC_LIB "Build Embree as a static library.")
|
||||
OPTION(EMBREE_STATIC_LIB "Build Embree as a static library." ON)
|
||||
MARK_AS_ADVANCED(CLEAR EMBREE_STATIC_LIB)
|
||||
ELSE()
|
||||
SET(EMBREE_STATIC_LIB ON CACHE BOOL "Build Embree as a static library." FORCE)
|
||||
@@ -127,6 +127,8 @@ MARK_AS_ADVANCED(EMBREE_INSTALL_DEPENDENCIES)
|
||||
OPTION(EMBREE_STAT_COUNTERS "Enables statistic counters.")
|
||||
OPTION(EMBREE_STACK_PROTECTOR "When enabled Embree compiles with stack protection against return address overrides." OFF)
|
||||
|
||||
OPTION(EMBREE_DPCPP_SUPPORT "Enables DPC++ support." ON)
|
||||
|
||||
OPTION(EMBREE_RAY_MASK "Enables ray mask support.")
|
||||
OPTION(EMBREE_BACKFACE_CULLING "Enables backface culling.")
|
||||
OPTION(EMBREE_FILTER_FUNCTION "Enables filter functions." ON)
|
||||
@@ -178,6 +180,14 @@ ENDIF()
|
||||
|
||||
SET(CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo")
|
||||
|
||||
# Validate build type
|
||||
IF (CMAKE_BUILD_TYPE)
|
||||
string(FIND "${CONFIGURATION_TYPES}" "${CMAKE_BUILD_TYPE}" MATCHED_CONFIG)
|
||||
IF (${MATCHED_CONFIG} EQUAL -1)
|
||||
message(FATAL_ERROR "CMAKE_BUILD_TYPE (${CMAKE_BUILD_TYPE}) allows only the following values: ${CONFIGURATION_TYPES}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF (WIN32)
|
||||
IF (NOT DEFAULT_CMAKE_CONFIGURATION_TYPES_SET)
|
||||
SET(CMAKE_CONFIGURATION_TYPES "${CONFIGURATION_TYPES}" CACHE STRING "List of generated configurations." FORCE)
|
||||
@@ -227,7 +237,8 @@ ENDIF (WIN32)
|
||||
IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
|
||||
SET(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.")
|
||||
ELSE()
|
||||
SET(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.")
|
||||
# SET(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.")
|
||||
SET(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.")
|
||||
ENDIF()
|
||||
SET_PROPERTY(CACHE EMBREE_MAX_ISA PROPERTY STRINGS NONE SSE2 SSE4.2 AVX AVX2 AVX512KNL AVX512SKX DEFAULT)
|
||||
|
||||
@@ -494,6 +505,9 @@ IF (EMBREE_TUTORIALS)
|
||||
ADD_SUBDIRECTORY(tutorials)
|
||||
ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY(tutorials/sycl_test)
|
||||
|
||||
|
||||
##############################################################
|
||||
# Uninstall
|
||||
##############################################################
|
||||
|
||||
@@ -100,6 +100,9 @@ ELSE()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") # disables strict aliasing rules
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable auto vectorizer
|
||||
|
||||
|
||||
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
|
||||
ENDIF()
|
||||
@@ -109,10 +112,19 @@ ELSE()
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
IF (EMBREE_ADDRESS_SANITIZER)
|
||||
IF (EMBREE_ADDRESS_SANITIZER)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
||||
ENDIF()
|
||||
|
||||
IF (EMBREE_DPCPP_SUPPORT)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-mismatched-tags -Wno-pessimizing-move -Wno-reorder -Wno-unneeded-internal-declaration -Wno-delete-non-abstract-non-virtual-dtor -Wno-dangling-field -Wno-unknown-pragmas -fsycl -fsycl-unnamed-lambda -Xclang -fsycl-allow-func-ptr") # disable DPC++ warnings
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEMBREE_DPCPP_SUPPORT") # enable DPC++ code in Embree
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lOpenCL -lsycl") # link against DPC++ libs
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lOpenCL -lsycl") # we do not need an executable stack
|
||||
|
||||
ENDIF(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode
|
||||
@@ -139,11 +151,15 @@ ELSE()
|
||||
IF (NOT EMBREE_ADDRESS_SANITIZER) # for address sanitizer this causes link errors
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
IF (EMBREE_DPCPP_SUPPORT)
|
||||
ELSE (EMBREE_DPCPP_SUPPORT)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
ENDIF (EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
|
||||
ENDIF()
|
||||
ENDIF(APPLE)
|
||||
|
||||
|
||||
ENDIF()
|
||||
|
||||
@@ -26,6 +26,16 @@ MACRO (ADD_TUTORIAL TUTORIAL_NAME)
|
||||
SIGN_TARGET(${TUTORIAL_NAME})
|
||||
ENDMACRO ()
|
||||
|
||||
MACRO (ADD_TUTORIAL_SYCL TUTORIAL_NAME)
|
||||
ADD_EXECUTABLE(${TUTORIAL_NAME}_sycl ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_sycl.cpp ${ARGN})
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_sycl embree image tutorial noise ${ADDITIONAL_LIBRARIES} -foffload-static-lib=../../libembree${EMBREE_VERSION_MAJOR}.a)
|
||||
TARGET_COMPILE_DEFINITIONS(${TUTORIAL_NAME}_sycl PUBLIC EMBREE_SYCL_TUTORIAL)
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_sycl PROPERTY FOLDER tutorials/sycl)
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_sycl APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}")
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME}_sycl DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
|
||||
SIGN_TARGET(${TUTORIAL_NAME}_sycl)
|
||||
ENDMACRO ()
|
||||
|
||||
MACRO (ADD_TUTORIAL_ISPC TUTORIAL_NAME)
|
||||
IF (EMBREE_ISPC_SUPPORT)
|
||||
ADD_EMBREE_ISPC_EXECUTABLE(${TUTORIAL_NAME}_ispc ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.ispc ${ARGN})
|
||||
|
||||
@@ -41,9 +41,13 @@ namespace embree
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline AffineSpaceT ( ) { }
|
||||
#if !defined(__SYCL_DEVICE_ONLY__) // FIXME: workaround for SYCL bug
|
||||
__forceinline AffineSpaceT ( const AffineSpaceT& other ) { l = other.l; p = other.p; }
|
||||
#endif
|
||||
__forceinline AffineSpaceT ( const L & other ) { l = other ; p = VectorT(zero); }
|
||||
#if !defined(__SYCL_DEVICE_ONLY__) // FIXME: workaround for SYCL bug
|
||||
__forceinline AffineSpaceT& operator=( const AffineSpaceT& other ) { l = other.l; p = other.p; return *this; }
|
||||
#endif
|
||||
|
||||
__forceinline AffineSpaceT( const VectorT& vx, const VectorT& vy, const VectorT& vz, const VectorT& p ) : l(vx,vy,vz), p(p) {}
|
||||
__forceinline AffineSpaceT( const L& l, const VectorT& p ) : l(l), p(p) {}
|
||||
@@ -192,7 +196,7 @@ namespace embree
|
||||
if (D) *D = sqrtf(D_x);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
__forceinline void AffineSpace3fa_store_unaligned(const AffineSpace3fa &source, AffineSpace3fa* ptr)
|
||||
{
|
||||
Vec3fa::storeu(&ptr->l.vx, source.l.vx);
|
||||
@@ -211,8 +215,6 @@ namespace embree
|
||||
return space;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef VectorT
|
||||
#undef ScalarT
|
||||
}
|
||||
|
||||
@@ -32,8 +32,11 @@ namespace embree
|
||||
|
||||
/*! default matrix constructor */
|
||||
__forceinline LinearSpace3 ( ) {}
|
||||
|
||||
#if !defined(__SYCL_DEVICE_ONLY__) // FIXME: workaround for SYCL bug
|
||||
__forceinline LinearSpace3 ( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; }
|
||||
__forceinline LinearSpace3& operator=( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; return *this; }
|
||||
#endif
|
||||
|
||||
template<typename L1> __forceinline LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
|
||||
|
||||
@@ -103,17 +106,20 @@ namespace embree
|
||||
Vector vx,vy,vz;
|
||||
};
|
||||
|
||||
#if !defined(EMBREE_SYCL_SIMD_LIBRARY) || !defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
/*! compute transposed matrix */
|
||||
template<> __forceinline const LinearSpace3<Vec3fa> LinearSpace3<Vec3fa>::transposed() const {
|
||||
vfloat4 rx,ry,rz; transpose((vfloat4&)vx,(vfloat4&)vy,(vfloat4&)vz,vfloat4(zero),rx,ry,rz);
|
||||
return LinearSpace3<Vec3fa>(Vec3fa(rx),Vec3fa(ry),Vec3fa(rz));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
__forceinline const LinearSpace3<T> transposed(const LinearSpace3<T>& xfm) {
|
||||
return xfm.transposed();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -192,7 +198,7 @@ namespace embree
|
||||
lerp(l0.vy,l1.vy,t),
|
||||
lerp(l0.vz,l1.vz,t));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#include "constants.h"
|
||||
#include <cmath>
|
||||
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#include "math_sycl.h"
|
||||
|
||||
#else
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
#include <immintrin.h>
|
||||
@@ -359,3 +365,5 @@ namespace embree
|
||||
return x | (y << 1) | (z << 2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../sys/platform.h"
|
||||
#include "../sys/intrinsics.h"
|
||||
#include "constants.h"
|
||||
#include <cmath>
|
||||
|
||||
#include "../../kernels/gpu/common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
__forceinline bool isvalid ( const float& v ) {
|
||||
return (v > -FLT_LARGE) & (v < +FLT_LARGE);
|
||||
}
|
||||
|
||||
__forceinline int cast_f2i(float f) {
|
||||
return __builtin_bit_cast(int,f);
|
||||
}
|
||||
|
||||
__forceinline float cast_i2f(int i) {
|
||||
return __builtin_bit_cast(float,i);
|
||||
}
|
||||
|
||||
//__forceinline bool finite ( const float x ) { return _finite(x) != 0; }
|
||||
//__forceinline float sign ( const float x ) { return x<0?-1.0f:1.0f; }
|
||||
__forceinline float sqr ( const float x ) { return x*x; }
|
||||
|
||||
__forceinline float rcp ( const float x ) {
|
||||
return cl::sycl::native::recip(x);
|
||||
}
|
||||
|
||||
//__forceinline float signmsk ( const float x ) {
|
||||
// return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
|
||||
//}
|
||||
//__forceinline float xorf( const float x, const float y ) {
|
||||
// return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y)));
|
||||
//}
|
||||
//__forceinline float andf( const float x, const unsigned y ) {
|
||||
// return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y))));
|
||||
//}
|
||||
|
||||
__forceinline float rsqrt( const float x ) {
|
||||
return cl::sycl::rsqrt(x);
|
||||
}
|
||||
|
||||
//__forceinline float nextafter(float x, float y) { if ((x<y) == (x>0)) return x*(1.1f+float(ulp)); else return x*(0.9f-float(ulp)); }
|
||||
//__forceinline double nextafter(double x, double y) { return _nextafter(x, y); }
|
||||
//__forceinline int roundf(float f) { return (int)(f + 0.5f); }
|
||||
|
||||
__forceinline float abs ( const float x ) { return cl::sycl::fabs(x); }
|
||||
__forceinline float acos ( const float x ) { return cl::sycl::acos(x); }
|
||||
__forceinline float asin ( const float x ) { return cl::sycl::asin(x); }
|
||||
__forceinline float atan ( const float x ) { return cl::sycl::atan(x); }
|
||||
__forceinline float atan2( const float y, const float x ) { return cl::sycl::atan2(y, x); }
|
||||
__forceinline float cos ( const float x ) { return cl::sycl::cos(x); }
|
||||
__forceinline float cosh ( const float x ) { return cl::sycl::cosh(x); }
|
||||
__forceinline float exp ( const float x ) { return cl::sycl::exp(x); }
|
||||
__forceinline float fmod ( const float x, const float y ) { return cl::sycl::fmod(x, y); }
|
||||
__forceinline float log ( const float x ) { return cl::sycl::log(x); }
|
||||
__forceinline float log10( const float x ) { return cl::sycl::log10(x); }
|
||||
__forceinline float pow ( const float x, const float y ) { return cl::sycl::pow(x, y); }
|
||||
__forceinline float sin ( const float x ) { return cl::sycl::sin(x); }
|
||||
__forceinline float sinh ( const float x ) { return cl::sycl::sinh(x); }
|
||||
__forceinline float sqrt ( const float x ) { return cl::sycl::sqrt(x); }
|
||||
__forceinline float tan ( const float x ) { return cl::sycl::tan(x); }
|
||||
__forceinline float tanh ( const float x ) { return cl::sycl::tanh(x); }
|
||||
__forceinline float floor( const float x ) { return cl::sycl::floor(x); }
|
||||
__forceinline float ceil ( const float x ) { return cl::sycl::ceil(x); }
|
||||
__forceinline float frac ( const float x ) { return x-floor(x); }
|
||||
|
||||
//__forceinline double abs ( const double x ) { return ::fabs(x); }
|
||||
//__forceinline double sign ( const double x ) { return x<0?-1.0:1.0; }
|
||||
//__forceinline double acos ( const double x ) { return ::acos (x); }
|
||||
//__forceinline double asin ( const double x ) { return ::asin (x); }
|
||||
//__forceinline double atan ( const double x ) { return ::atan (x); }
|
||||
//__forceinline double atan2( const double y, const double x ) { return ::atan2(y, x); }
|
||||
//__forceinline double cos ( const double x ) { return ::cos (x); }
|
||||
//__forceinline double cosh ( const double x ) { return ::cosh (x); }
|
||||
//__forceinline double exp ( const double x ) { return ::exp (x); }
|
||||
//__forceinline double fmod ( const double x, const double y ) { return ::fmod (x, y); }
|
||||
//__forceinline double log ( const double x ) { return ::log (x); }
|
||||
//__forceinline double log10( const double x ) { return ::log10(x); }
|
||||
//__forceinline double pow ( const double x, const double y ) { return ::pow (x, y); }
|
||||
//__forceinline double rcp ( const double x ) { return 1.0/x; }
|
||||
//__forceinline double rsqrt( const double x ) { return 1.0/::sqrt(x); }
|
||||
//__forceinline double sin ( const double x ) { return ::sin (x); }
|
||||
//__forceinline double sinh ( const double x ) { return ::sinh (x); }
|
||||
//__forceinline double sqr ( const double x ) { return x*x; }
|
||||
//__forceinline double sqrt ( const double x ) { return ::sqrt (x); }
|
||||
//__forceinline double tan ( const double x ) { return ::tan (x); }
|
||||
//__forceinline double tanh ( const double x ) { return ::tanh (x); }
|
||||
//__forceinline double floor( const double x ) { return ::floor (x); }
|
||||
//__forceinline double ceil ( const double x ) { return ::ceil (x); }
|
||||
|
||||
/*
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline float mini(float a, float b) {
|
||||
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
|
||||
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
|
||||
const __m128i ci = _mm_min_epi32(ai,bi);
|
||||
return _mm_cvtss_f32(_mm_castsi128_ps(ci));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline float maxi(float a, float b) {
|
||||
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
|
||||
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
|
||||
const __m128i ci = _mm_max_epi32(ai,bi);
|
||||
return _mm_cvtss_f32(_mm_castsi128_ps(ci));
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
__forceinline T twice(const T& a) { return a+a; }
|
||||
|
||||
__forceinline int min(int a, int b) { return cl::sycl::min(a,b); }
|
||||
__forceinline unsigned min(unsigned a, unsigned b) { return cl::sycl::min(a,b); }
|
||||
__forceinline int64_t min(int64_t a, int64_t b) { return cl::sycl::min(a,b); }
|
||||
__forceinline float min(float a, float b) { return cl::sycl::fmin(a,b); }
|
||||
__forceinline double min(double a, double b) { return cl::sycl::fmin(a,b); }
|
||||
#if defined(__X86_64__)
|
||||
__forceinline size_t min(size_t a, size_t b) { return cl::sycl::min(a,b); }
|
||||
#endif
|
||||
|
||||
template<typename T> __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); }
|
||||
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); }
|
||||
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d, const T& e) { return min(min(min(a,b),min(c,d)),e); }
|
||||
|
||||
// template<typename T> __forceinline T mini(const T& a, const T& b, const T& c) { return mini(mini(a,b),c); }
|
||||
// template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d) { return mini(mini(a,b),mini(c,d)); }
|
||||
// template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d, const T& e) { return mini(mini(mini(a,b),mini(c,d)),e); }
|
||||
|
||||
__forceinline int max(int a, int b) { return cl::sycl::max(a,b); }
|
||||
__forceinline unsigned max(unsigned a, unsigned b) { return cl::sycl::max(a,b); }
|
||||
__forceinline int64_t max(int64_t a, int64_t b) { return cl::sycl::max(a,b); }
|
||||
__forceinline float max(float a, float b) { return cl::sycl::fmax(a,b); }
|
||||
__forceinline double max(double a, double b) { return cl::sycl::fmax(a,b); }
|
||||
#if defined(__X86_64__)
|
||||
__forceinline size_t max(size_t a, size_t b) { return cl::sycl::max(a,b); }
|
||||
#endif
|
||||
|
||||
template<typename T> __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); }
|
||||
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); }
|
||||
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d, const T& e) { return max(max(max(a,b),max(c,d)),e); }
|
||||
|
||||
// template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c) { return maxi(maxi(a,b),c); }
|
||||
// template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d) { return maxi(maxi(a,b),maxi(c,d)); }
|
||||
// template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d, const T& e) { return maxi(maxi(maxi(a,b),maxi(c,d)),e); }
|
||||
|
||||
template<typename T> __forceinline T clamp(const T& x, const T& lower = T(zero), const T& upper = T(one)) { return max(min(x,upper),lower); }
|
||||
template<typename T> __forceinline T clampz(const T& x, const T& upper) { return max(T(zero), min(x,upper)); }
|
||||
|
||||
template<typename T> __forceinline T deg2rad ( const T& x ) { return x * T(1.74532925199432957692e-2f); }
|
||||
template<typename T> __forceinline T rad2deg ( const T& x ) { return x * T(5.72957795130823208768e1f); }
|
||||
template<typename T> __forceinline T sin2cos ( const T& x ) { return sqrt(max(T(zero),T(one)-x*x)); }
|
||||
template<typename T> __forceinline T cos2sin ( const T& x ) { return sin2cos(x); }
|
||||
|
||||
__forceinline float madd ( const float a, const float b, const float c) { return +cl::sycl::fma(+a,b,+c); }
|
||||
__forceinline float msub ( const float a, const float b, const float c) { return +cl::sycl::fma(+a,b,-c); }
|
||||
__forceinline float nmadd ( const float a, const float b, const float c) { return +cl::sycl::fma(-a,b,+c); }
|
||||
__forceinline float nmsub ( const float a, const float b, const float c) { return -cl::sycl::fma(+a,b,+c); }
|
||||
|
||||
/*! random functions */
|
||||
/*
|
||||
template<typename T> T random() { return T(0); }
|
||||
template<> __forceinline int random() { return int(rand()); }
|
||||
template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 16); }
|
||||
template<> __forceinline float random() { return rand()/float(RAND_MAX); }
|
||||
template<> __forceinline double random() { return rand()/double(RAND_MAX); }
|
||||
*/
|
||||
|
||||
/*! selects */
|
||||
__forceinline bool select(bool s, bool t , bool f) { return s ? t : f; }
|
||||
__forceinline int select(bool s, int t, int f) { return s ? t : f; }
|
||||
__forceinline float select(bool s, float t, float f) { return s ? t : f; }
|
||||
|
||||
__forceinline float lerp(const float v0, const float v1, const float t) {
|
||||
return madd(1.0f-t,v0,t*v1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline T lerp2(const float x0, const float x1, const float x2, const float x3, const T& u, const T& v) {
|
||||
return madd((1.0f-u),madd((1.0f-v),T(x0),v*T(x2)),u*madd((1.0f-v),T(x1),v*T(x3)));
|
||||
}
|
||||
|
||||
/*! exchange */
|
||||
template<typename T> __forceinline void xchg ( T& a, T& b ) { const T tmp = a; a = b; b = tmp; }
|
||||
|
||||
/*! bit reverse operation */
|
||||
template<class T>
|
||||
__forceinline T bitReverse(const T& vin)
|
||||
{
|
||||
T v = vin;
|
||||
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
|
||||
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
|
||||
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
|
||||
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
|
||||
v = ( v >> 16 ) | ( v << 16);
|
||||
return v;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*! bit interleave operation */
|
||||
template<class T>
|
||||
__forceinline T bitInterleave(const T& xin, const T& yin, const T& zin)
|
||||
{
|
||||
T x = xin, y = yin, z = zin;
|
||||
x = (x | (x << 16)) & 0x030000FF;
|
||||
x = (x | (x << 8)) & 0x0300F00F;
|
||||
x = (x | (x << 4)) & 0x030C30C3;
|
||||
x = (x | (x << 2)) & 0x09249249;
|
||||
|
||||
y = (y | (y << 16)) & 0x030000FF;
|
||||
y = (y | (y << 8)) & 0x0300F00F;
|
||||
y = (y | (y << 4)) & 0x030C30C3;
|
||||
y = (y | (y << 2)) & 0x09249249;
|
||||
|
||||
z = (z | (z << 16)) & 0x030000FF;
|
||||
z = (z | (z << 8)) & 0x0300F00F;
|
||||
z = (z | (z << 4)) & 0x030C30C3;
|
||||
z = (z | (z << 2)) & 0x09249249;
|
||||
|
||||
return x | (y << 1) | (z << 2);
|
||||
}
|
||||
|
||||
/*! bit interleave operation for 64bit data types*/
|
||||
template<class T>
|
||||
__forceinline T bitInterleave64(const T& xin, const T& yin, const T& zin){
|
||||
T x = xin & 0x1fffff;
|
||||
T y = yin & 0x1fffff;
|
||||
T z = zin & 0x1fffff;
|
||||
|
||||
x = (x | x << 32) & 0x1f00000000ffff;
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff;
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f;
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3;
|
||||
x = (x | x << 2) & 0x1249249249249249;
|
||||
|
||||
y = (y | y << 32) & 0x1f00000000ffff;
|
||||
y = (y | y << 16) & 0x1f0000ff0000ff;
|
||||
y = (y | y << 8) & 0x100f00f00f00f00f;
|
||||
y = (y | y << 4) & 0x10c30c30c30c30c3;
|
||||
y = (y | y << 2) & 0x1249249249249249;
|
||||
|
||||
z = (z | z << 32) & 0x1f00000000ffff;
|
||||
z = (z | z << 16) & 0x1f0000ff0000ff;
|
||||
z = (z | z << 8) & 0x100f00f00f00f00f;
|
||||
z = (z | z << 4) & 0x10c30c30c30c30c3;
|
||||
z = (z | z << 2) & 0x1249249249249249;
|
||||
|
||||
return x | (y << 1) | (z << 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -299,6 +299,8 @@ namespace embree
|
||||
|
||||
template<> __forceinline Vec3<float>::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; }
|
||||
|
||||
#if !defined(EMBREE_SYCL_SIMD_LIBRARY) || !defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
|
||||
x = a.x; y = a.y; z = a.z;
|
||||
@@ -359,4 +361,6 @@ namespace embree
|
||||
#if defined(__AVX512F__)
|
||||
template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
|
||||
#include "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#include "vec3ba_sycl.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "../simd/sse.h"
|
||||
|
||||
namespace embree
|
||||
@@ -129,3 +136,5 @@ namespace embree
|
||||
return cout << "(" << (a.x ? "1" : "0") << ", " << (a.y ? "1" : "0") << ", " << (a.z ? "1" : "0") << ")";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
#include "../simd/sse.h"
|
||||
|
||||
#include "../../kernels/gpu/common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// SSE Vec3ba Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct __aligned(16) Vec3ba
|
||||
{
|
||||
//ALIGNED_STRUCT_(16);
|
||||
|
||||
struct { bool x,y,z; };
|
||||
|
||||
typedef bool Scalar;
|
||||
enum { N = 3 };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba( ) {}
|
||||
//__forceinline Vec3ba( const __m128 input ) : m128(input) {}
|
||||
//__forceinline Vec3ba( const Vec3ba& other ) : m128(other.m128) {}
|
||||
//__forceinline Vec3ba& operator =(const Vec3ba& other) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline explicit Vec3ba( bool a ) : x(a), y(a), z(a) {}
|
||||
__forceinline Vec3ba( bool a, bool b, bool c) : x(a), y(b), z(c) {}
|
||||
|
||||
//__forceinline operator const __m128&() const { return m128; }
|
||||
//__forceinline operator __m128&() { return m128; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba( FalseTy ) : x(false), y(false), z(false) {}
|
||||
__forceinline Vec3ba( TrueTy ) : x(true), y(true), z(true) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//__forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
|
||||
//__forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba operator !( const Vec3ba& a ) { return Vec3ba(!a.x,!a.y,!a.z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return Vec3ba(a.x & b.x, a.y & b.y, a.z & b.z); }
|
||||
__forceinline Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return Vec3ba(a.x | b.x, a.y | b.y, a.z | b.z); }
|
||||
__forceinline Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return Vec3ba(a.x != b.x, a.y != b.y, a.z != b.z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba& operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
|
||||
__forceinline Vec3ba& operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
|
||||
__forceinline Vec3ba& operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator ==( const Vec3ba& a, const Vec3ba& b ) {
|
||||
return a.x == b.x && a.y == b.y && a.z == b.z;
|
||||
}
|
||||
__forceinline bool operator !=( const Vec3ba& a, const Vec3ba& b ) {
|
||||
return a.x != b.x || a.y != b.y || a.z != b.z;
|
||||
}
|
||||
/*
|
||||
__forceinline bool operator < ( const Vec3ba& a, const Vec3ba& b ) {
|
||||
if (a.x != b.x) return a.x < b.x;
|
||||
if (a.y != b.y) return a.y < b.y;
|
||||
if (a.z != b.z) return a.z < b.z;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and( const Vec3ba& a ) { return a.x & a.y & a.z; }
|
||||
__forceinline bool reduce_or ( const Vec3ba& a ) { return a.x | a.y | a.z; }
|
||||
|
||||
__forceinline bool all ( const Vec3ba& b ) { return reduce_and(b); }
|
||||
__forceinline bool any ( const Vec3ba& b ) { return reduce_or(b); }
|
||||
__forceinline bool none ( const Vec3ba& b ) { return !reduce_or(b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3ba& a) {
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,13 @@
|
||||
|
||||
#include "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#include "vec3fa_sycl.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "../simd/sse.h"
|
||||
|
||||
namespace embree
|
||||
@@ -376,3 +383,5 @@ namespace embree
|
||||
|
||||
typedef Vec3fa Vec3fa_t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
#include "../simd/sse.h"
|
||||
|
||||
#include "../../kernels/gpu/common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// SSE Vec3fa Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct __aligned(16) Vec3fa
|
||||
{
|
||||
//ALIGNED_STRUCT_(16);
|
||||
|
||||
typedef float Scalar;
|
||||
enum { N = 3 };
|
||||
struct { float x,y,z; union { int a; unsigned u; float w; }; };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa( ) {}
|
||||
//__forceinline Vec3fa( const __m128 a ) : m128(a) {}
|
||||
|
||||
__forceinline Vec3fa ( const Vec3<float>& other ) { x = other.x; y = other.y; z = other.z; }
|
||||
__forceinline Vec3fa& operator =( const Vec3<float>& other ) { x = other.x; y = other.y; z = other.z; return *this; }
|
||||
|
||||
//__forceinline Vec3fa ( const Vec3fa& other ) { m128 = other.m128; }
|
||||
|
||||
//__forceinline Vec3fa& operator =( const Vec3fa& other ) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline explicit Vec3fa( const float a ) : x(a), y(a), z(a), w(a) {}
|
||||
__forceinline Vec3fa( const float x, const float y, const float z) : x(x), y(y), z(z), w(z) {}
|
||||
|
||||
__forceinline Vec3fa( const Vec3fa& other, const int a1) : x(other.x), y(other.y), z(other.z), a(a1) {}
|
||||
__forceinline Vec3fa( const Vec3fa& other, const unsigned a1) : x(other.x), y(other.y), z(other.z), u(a1) {}
|
||||
__forceinline Vec3fa( const Vec3fa& other, const float w1) : x(other.x), y(other.y), z(other.z), w(w1) {}
|
||||
|
||||
//__forceinline Vec3fa( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
|
||||
//__forceinline Vec3fa( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
|
||||
__forceinline Vec3fa( const float x, const float y, const float z, const float w) : x(x), y(y), z(z), w(w) {}
|
||||
|
||||
__forceinline explicit Vec3fa( const Vec3ia& a ) : x((float)a.x), y((float)a.y), z((float)a.z), w(0.0f) {}
|
||||
|
||||
//__forceinline operator const __m128&() const { return m128; }
|
||||
//__forceinline operator __m128&() { return m128; }
|
||||
|
||||
friend __forceinline Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { Vec3fa c = a; c.a = b.a; return c; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline Vec3fa load( const void* const a ) {
|
||||
const float* ptr = (const float*)a;
|
||||
return Vec3fa(ptr[0],ptr[1],ptr[2],ptr[3]);
|
||||
}
|
||||
|
||||
static __forceinline Vec3fa loadu( const void* const a ) {
|
||||
const float* ptr = (const float*)a;
|
||||
return Vec3fa(ptr[0],ptr[1],ptr[2],ptr[3]);
|
||||
}
|
||||
|
||||
static __forceinline void storeu ( void* a, const Vec3fa& v ) {
|
||||
float* ptr = (float*)a;
|
||||
ptr[0] = v.x; ptr[1] = v.y; ptr[2] = v.z; ptr[3] = v.w;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa( ZeroTy ) : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
|
||||
__forceinline Vec3fa( OneTy ) : x(1.0f), y(1.0f), z(1.0f), w(1.0f) {}
|
||||
__forceinline Vec3fa( PosInfTy ) : x(+INFINITY), y(+INFINITY), z(+INFINITY), w(+INFINITY) {}
|
||||
__forceinline Vec3fa( NegInfTy ) : x(-INFINITY), y(-INFINITY), z(-INFINITY), w(-INFINITY) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//__forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
|
||||
//__forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa operator +( const Vec3fa& a ) { return a; }
|
||||
__forceinline Vec3fa operator -( const Vec3fa& a ) { return Vec3fa(-a.x,-a.y,-a.z); }
|
||||
__forceinline Vec3fa abs ( const Vec3fa& a ) { return Vec3fa(cl::sycl::fabs(a.x),cl::sycl::fabs(a.y),cl::sycl::fabs(a.z)); }
|
||||
__forceinline Vec3fa sign ( const Vec3fa& a ) { return Vec3fa(cl::sycl::sign(a.x),cl::sycl::sign(a.y),cl::sycl::sign(a.z)); }
|
||||
|
||||
//__forceinline Vec3fa rcp ( const Vec3fa& a ) { return Vec3fa(cl::sycl::recip(a.x),cl::sycl::recip(a.y),cl::sycl::recip(a.z)); }
|
||||
__forceinline Vec3fa rcp ( const Vec3fa& a ) { return Vec3fa(__sycl_std::__invoke_native_recip<float>(a.x),__sycl_std::__invoke_native_recip<float>(a.y),__sycl_std::__invoke_native_recip<float>(a.z)); }
|
||||
__forceinline Vec3fa sqrt ( const Vec3fa& a ) { return Vec3fa(cl::sycl::sqrt(a.x),cl::sycl::sqrt(a.y),cl::sycl::sqrt(a.z)); }
|
||||
__forceinline Vec3fa sqr ( const Vec3fa& a ) { return Vec3fa(a.x*a.x,a.y*a.y,a.z*a.z); }
|
||||
|
||||
__forceinline Vec3fa rsqrt( const Vec3fa& a ) { return Vec3fa(cl::sycl::rsqrt(a.x),cl::sycl::rsqrt(a.y),cl::sycl::rsqrt(a.z)); }
|
||||
|
||||
__forceinline Vec3fa zero_fix(const Vec3fa& a) {
|
||||
const float x = cl::sycl::fabs(a.x) < min_rcp_input ? min_rcp_input : a.x;
|
||||
const float y = cl::sycl::fabs(a.y) < min_rcp_input ? min_rcp_input : a.y;
|
||||
const float z = cl::sycl::fabs(a.z) < min_rcp_input ? min_rcp_input : a.z;
|
||||
return Vec3fa(x,y,z);
|
||||
}
|
||||
__forceinline Vec3fa rcp_safe(const Vec3fa& a) {
|
||||
return rcp(zero_fix(a));
|
||||
}
|
||||
__forceinline Vec3fa log ( const Vec3fa& a ) {
|
||||
return Vec3fa(cl::sycl::log(a.x),cl::sycl::log(a.y),cl::sycl::log(a.z));
|
||||
}
|
||||
|
||||
__forceinline Vec3fa exp ( const Vec3fa& a ) {
|
||||
return Vec3fa(cl::sycl::exp(a.x),cl::sycl::exp(a.y),cl::sycl::exp(a.z));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return Vec3fa(a.x+b.x, a.y+b.y, a.z+b.z); }
|
||||
__forceinline Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return Vec3fa(a.x-b.x, a.y-b.y, a.z-b.z); }
|
||||
__forceinline Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return Vec3fa(a.x*b.x, a.y*b.y, a.z*b.z); }
|
||||
__forceinline Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
|
||||
__forceinline Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
|
||||
__forceinline Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return Vec3fa(a.x/b.x, a.y/b.y, a.z/b.z); }
|
||||
__forceinline Vec3fa operator /( const Vec3fa& a, const float b ) { return Vec3fa(a.x/b, a.y/b, a.z/b); }
|
||||
__forceinline Vec3fa operator /( const float a, const Vec3fa& b ) { return Vec3fa(a/b.x, a/b.y, a/b.z); }
|
||||
|
||||
__forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) {
|
||||
return Vec3fa(cl::sycl::fmin(a.x,b.x), cl::sycl::fmin(a.y,b.y), cl::sycl::fmin(a.z,b.z));
|
||||
}
|
||||
__forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) {
|
||||
return Vec3fa(cl::sycl::fmax(a.x,b.x), cl::sycl::fmax(a.y,b.y), cl::sycl::fmax(a.z,b.z));
|
||||
}
|
||||
|
||||
/*
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) {
|
||||
const vint4 ai = _mm_castps_si128(a);
|
||||
const vint4 bi = _mm_castps_si128(b);
|
||||
const vint4 ci = _mm_min_epi32(ai,bi);
|
||||
return _mm_castsi128_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) {
|
||||
const vint4 ai = _mm_castps_si128(a);
|
||||
const vint4 bi = _mm_castps_si128(b);
|
||||
const vint4 ci = _mm_max_epi32(ai,bi);
|
||||
return _mm_castsi128_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
|
||||
return Vec3fa(powf(a.x,b),powf(a.y,b),powf(a.z,b));
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return Vec3fa(madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
|
||||
__forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return Vec3fa(msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
|
||||
__forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return Vec3fa(nmadd(a.x,b.x,c.x), nmadd(a.y,b.y,c.y), nmadd(a.z,b.z,c.z)); }
|
||||
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return Vec3fa(nmsub(a.x,b.x,c.x), nmsub(a.y,b.y,c.y), nmsub(a.z,b.z,c.z)); }
|
||||
|
||||
__forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); }
|
||||
__forceinline Vec3fa msub ( const float a, const Vec3fa& b, const Vec3fa& c) { return msub(Vec3fa(a),b,c); }
|
||||
__forceinline Vec3fa nmadd ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmadd(Vec3fa(a),b,c); }
|
||||
__forceinline Vec3fa nmsub ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmsub(Vec3fa(a),b,c); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa& operator +=( Vec3fa& a, const Vec3fa& b ) { return a = a + b; }
|
||||
__forceinline Vec3fa& operator -=( Vec3fa& a, const Vec3fa& b ) { return a = a - b; }
|
||||
__forceinline Vec3fa& operator *=( Vec3fa& a, const Vec3fa& b ) { return a = a * b; }
|
||||
__forceinline Vec3fa& operator *=( Vec3fa& a, const float b ) { return a = a * b; }
|
||||
__forceinline Vec3fa& operator /=( Vec3fa& a, const Vec3fa& b ) { return a = a / b; }
|
||||
__forceinline Vec3fa& operator /=( Vec3fa& a, const float b ) { return a = a / b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float reduce_add(const Vec3fa& v) { return v.x+v.y+v.z; }
|
||||
__forceinline float reduce_mul(const Vec3fa& v) { return v.x*v.y*v.z; }
|
||||
__forceinline float reduce_min(const Vec3fa& v) { return cl::sycl::fmin(cl::sycl::fmin(v.x,v.y),v.z); }
|
||||
__forceinline float reduce_max(const Vec3fa& v) { return cl::sycl::fmax(cl::sycl::fmax(v.x,v.y),v.z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator ==( const Vec3fa& a, const Vec3fa& b ) { return a.x == b.x && a.y == b.y && a.z == b.z; }
|
||||
__forceinline bool operator !=( const Vec3fa& a, const Vec3fa& b ) { return a.x != b.x || a.y != b.y || a.z != b.z; }
|
||||
|
||||
__forceinline Vec3ba eq_mask( const Vec3fa& a, const Vec3fa& b ) { return Vec3ba(a.x == b.x, a.y == b.y, a.z == b.z); }
|
||||
__forceinline Vec3ba neq_mask(const Vec3fa& a, const Vec3fa& b ) { return Vec3ba(a.x != b.x, a.y != b.y, a.z != b.z); }
|
||||
__forceinline Vec3ba lt_mask( const Vec3fa& a, const Vec3fa& b ) { return Vec3ba(a.x < b.x, a.y < b.y, a.z < b.z); }
|
||||
__forceinline Vec3ba le_mask( const Vec3fa& a, const Vec3fa& b ) { return Vec3ba(a.x <= b.x, a.y <= b.y, a.z <= b.z); }
|
||||
__forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return Vec3ba(a.x > b.x, a.y > b.y, a.z > b.z); }
|
||||
__forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return Vec3ba(a.x >= b.x, a.y >= b.y, a.z >= b.z); }
|
||||
|
||||
__forceinline bool isvalid ( const Vec3fa& v ) {
|
||||
return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
|
||||
}
|
||||
|
||||
__forceinline bool is_finite ( const Vec3fa& a ) {
|
||||
return all(ge_mask(a,Vec3fa(-FLT_MAX)) & le_mask(a,Vec3fa(+FLT_MAX)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float dot ( const Vec3fa& a, const Vec3fa& b ) {
|
||||
return reduce_add(a*b);
|
||||
}
|
||||
|
||||
__forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b ) {
|
||||
return Vec3fa(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x));
|
||||
}
|
||||
|
||||
__forceinline float sqr_length ( const Vec3fa& a ) { return dot(a,a); }
|
||||
__forceinline float rcp_length ( const Vec3fa& a ) { return rsqrt(dot(a,a)); }
|
||||
__forceinline float rcp_length2( const Vec3fa& a ) { return rcp(dot(a,a)); }
|
||||
__forceinline float length ( const Vec3fa& a ) { return sqrt(dot(a,a)); }
|
||||
__forceinline Vec3fa normalize( const Vec3fa& a ) { return a*rsqrt(dot(a,a)); }
|
||||
__forceinline float distance ( const Vec3fa& a, const Vec3fa& b ) { return length(a-b); }
|
||||
__forceinline float halfArea ( const Vec3fa& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
|
||||
__forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
|
||||
|
||||
__forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
|
||||
const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
|
||||
}
|
||||
|
||||
/*! differentiated normalization */
|
||||
__forceinline Vec3fa dnormalize(const Vec3fa& p, const Vec3fa& dp)
|
||||
{
|
||||
const float pp = dot(p,p);
|
||||
const float pdp = dot(p,dp);
|
||||
return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
|
||||
return Vec3fa(s ? t.x : f.x, s ? t.y : f.y, s ? t.z : f.z);
|
||||
}
|
||||
|
||||
/*
|
||||
__forceinline Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
|
||||
return blendv_ps(f, t, s);
|
||||
}
|
||||
*/
|
||||
|
||||
__forceinline Vec3fa lerp(const Vec3fa& v0, const Vec3fa& v1, const float t) {
|
||||
return madd(1.0f-t,v0,t*v1);
|
||||
}
|
||||
|
||||
__forceinline int maxDim ( const Vec3fa& a )
|
||||
{
|
||||
const Vec3fa b = abs(a);
|
||||
if (b.x > b.y) {
|
||||
if (b.x > b.z) return 0; else return 2;
|
||||
} else {
|
||||
if (b.y > b.z) return 1; else return 2;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Rounding Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(cl::sycl::trunc(a.x),cl::sycl::trunc(a.y),cl::sycl::trunc(a.z)); }
|
||||
__forceinline Vec3fa floor( const Vec3fa& a ) { return Vec3fa(cl::sycl::floor(a.x),cl::sycl::floor(a.y),cl::sycl::floor(a.z)); }
|
||||
__forceinline Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(cl::sycl::ceil (a.x),cl::sycl::ceil (a.y),cl::sycl::ceil (a.z)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa& a) {
|
||||
return cout;
|
||||
}
|
||||
|
||||
typedef Vec3fa Vec3fa_t;
|
||||
}
|
||||
@@ -18,6 +18,13 @@
|
||||
|
||||
#include "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#include "vec3ia_sycl.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "../simd/sse.h"
|
||||
|
||||
namespace embree
|
||||
@@ -197,3 +204,5 @@ namespace embree
|
||||
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
#include "../simd/sse.h"
|
||||
|
||||
#include "../../kernels/gpu/common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// SSE Vec3ia Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct __aligned(16) Vec3ia
|
||||
{
|
||||
ALIGNED_STRUCT_(16);
|
||||
|
||||
struct { int x,y,z; };
|
||||
|
||||
typedef int Scalar;
|
||||
enum { N = 3 };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia( ) {}
|
||||
//__forceinline Vec3ia( const __m128i a ) : m128(a) {}
|
||||
//__forceinline Vec3ia( const Vec3ia& other ) : m128(other.m128) {}
|
||||
//__forceinline Vec3ia& operator =(const Vec3ia& other) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline explicit Vec3ia( const int a ) : x(a), y(a), z(a) {}
|
||||
__forceinline Vec3ia( const int x, const int y, const int z) : x(x), y(y), z(z) {}
|
||||
//__forceinline explicit Vec3ia( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
|
||||
|
||||
//__forceinline operator const __m128i&() const { return m128; }
|
||||
//__forceinline operator __m128i&() { return m128; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia( ZeroTy ) : x(0), y(0), z(0) {}
|
||||
__forceinline Vec3ia( OneTy ) : x(1), y(1), z(1) {}
|
||||
__forceinline Vec3ia( PosInfTy ) : x(0x7FFFFFFF), y(0x7FFFFFFF), z(0x7FFFFFFF) {}
|
||||
__forceinline Vec3ia( NegInfTy ) : x(0x80000000), y(0x80000000), z(0x80000000) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//__forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
|
||||
//__forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia operator +( const Vec3ia& a ) { return Vec3ia(+a.x,+a.y,+a.z); }
|
||||
__forceinline Vec3ia operator -( const Vec3ia& a ) { return Vec3ia(-a.x,-a.y,-a.z); }
|
||||
__forceinline Vec3ia abs ( const Vec3ia& a ) { return Vec3ia(cl::sycl::abs(a.x),cl::sycl::abs(a.y),cl::sycl::abs(a.z)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(a.x+b.x, a.y+b.y, a.z+b.z); }
|
||||
__forceinline Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
|
||||
__forceinline Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
|
||||
|
||||
__forceinline Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(a.x-b.x, a.y-b.y, a.z-b.z); }
|
||||
__forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
|
||||
__forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
|
||||
|
||||
__forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(a.x*b.x, a.y*b.y, a.z*b.z); }
|
||||
__forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
|
||||
__forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
|
||||
|
||||
__forceinline Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(a.x&b.x, a.y&b.y, a.z&b.z); }
|
||||
__forceinline Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
|
||||
__forceinline Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
|
||||
|
||||
__forceinline Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(a.x|b.x, a.y|b.y, a.z|b.z); }
|
||||
__forceinline Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
|
||||
__forceinline Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
|
||||
|
||||
__forceinline Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(a.x^b.x, a.y^b.y, a.z^b.z); }
|
||||
__forceinline Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
|
||||
__forceinline Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
|
||||
|
||||
__forceinline Vec3ia operator <<( const Vec3ia& a, const int n ) { return Vec3ia(a.x<<n, a.y<<n, a.z<<n); }
|
||||
__forceinline Vec3ia operator >>( const Vec3ia& a, const int n ) { return Vec3ia(a.x>>n, a.y>>n, a.z>>n); }
|
||||
|
||||
__forceinline Vec3ia sll ( const Vec3ia& a, const int b ) { return Vec3ia(a.x<<b, a.y<<b, a.z<<b); }
|
||||
__forceinline Vec3ia sra ( const Vec3ia& a, const int b ) { return Vec3ia(a.x>>b, a.y>>b, a.z>>b); }
|
||||
__forceinline Vec3ia srl ( const Vec3ia& a, const int b ) { return Vec3ia(unsigned(a.x)>>b, unsigned(a.y)>>b, unsigned(a.z)>>b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia& operator +=( Vec3ia& a, const Vec3ia& b ) { return a = a + b; }
|
||||
__forceinline Vec3ia& operator +=( Vec3ia& a, const int& b ) { return a = a + b; }
|
||||
|
||||
__forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia& b ) { return a = a - b; }
|
||||
__forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
|
||||
|
||||
__forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia& b ) { return a = a * b; }
|
||||
__forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
|
||||
|
||||
__forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia& b ) { return a = a & b; }
|
||||
__forceinline Vec3ia& operator &=( Vec3ia& a, const int& b ) { return a = a & b; }
|
||||
|
||||
__forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia& b ) { return a = a | b; }
|
||||
__forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
|
||||
|
||||
__forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; }
|
||||
__forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int reduce_add(const Vec3ia& v) { return v.x+v.y+v.z; }
|
||||
__forceinline int reduce_mul(const Vec3ia& v) { return v.x*v.y*v.z; }
|
||||
__forceinline int reduce_min(const Vec3ia& v) { return cl::sycl::min(cl::sycl::min(v.x,v.y),v.z); }
|
||||
__forceinline int reduce_max(const Vec3ia& v) { return cl::sycl::max(cl::sycl::max(v.x,v.y),v.z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator ==( const Vec3ia& a, const Vec3ia& b ) { return a.x == b.x & a.y == b.y & a.z == b.z; }
|
||||
__forceinline bool operator !=( const Vec3ia& a, const Vec3ia& b ) { return a.x != b.x & a.y != b.y & a.z != b.z; }
|
||||
|
||||
/*
|
||||
__forceinline bool operator < ( const Vec3ia& a, const Vec3ia& b ) {
|
||||
if (a.x != b.x) return a.x < b.x;
|
||||
if (a.y != b.y) return a.y < b.y;
|
||||
if (a.z != b.z) return a.z < b.z;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
__forceinline Vec3ba eq_mask( const Vec3ia& a, const Vec3ia& b ) { return Vec3ba(a.x == b.x, a.y == b.y, a.z == b.z); }
|
||||
__forceinline Vec3ba lt_mask( const Vec3ia& a, const Vec3ia& b ) { return Vec3ba(a.x < b.x, a.y < b.y, a.z < b.z); }
|
||||
__forceinline Vec3ba gt_mask( const Vec3ia& a, const Vec3ia& b ) { return Vec3ba(a.x > b.x, a.y > b.y, a.z > b.z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
|
||||
const int x = m.x ? t.x : f.x;
|
||||
const int y = m.y ? t.y : f.y;
|
||||
const int z = m.z ? t.z : f.z;
|
||||
return Vec3ia(x,y,z);
|
||||
}
|
||||
|
||||
__forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(cl::sycl::min(a.x,b.x), cl::sycl::min(a.y,b.y), cl::sycl::min(a.z,b.z)); }
|
||||
__forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return Vec3ia(cl::sycl::max(a.x,b.x), cl::sycl::max(a.y,b.y), cl::sycl::max(a.z,b.z)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3ia& a) {
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
@@ -234,6 +234,8 @@ namespace embree
|
||||
{
|
||||
template<> __forceinline Vec4<float>::Vec4( const Vec3fa& a ) { x = a.x; y = a.y; z = a.z; w = a.w; }
|
||||
|
||||
#if !defined(EMBREE_SYCL_SIMD_LIBRARY) || !defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fa& a ) {
|
||||
x = a.x; y = a.y; z = a.z; w = a.w;
|
||||
@@ -268,4 +270,7 @@ namespace embree
|
||||
#if defined(__AVX512F__)
|
||||
template<> __forceinline Vec4<vfloat16>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../math/math.h"
|
||||
#include "../../kernels/gpu/common.h"
|
||||
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
# include "sycl.h"
|
||||
#else
|
||||
|
||||
/* include SSE wrapper classes */
|
||||
#if defined(__SSE__)
|
||||
@@ -114,3 +119,5 @@ namespace embree
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../sys/platform.h"
|
||||
#include "../sys/intrinsics.h"
|
||||
#include "../sys/alloc.h"
|
||||
#include "../math/constants.h"
|
||||
#include "varying.h"
|
||||
|
||||
#include "vbooln_sycl.h"
|
||||
#include "vintn_sycl.h"
|
||||
#include "vfloatn_sycl.h"
|
||||
+34
-3
@@ -20,6 +20,35 @@
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
/* Varying numeric types */
|
||||
template<int N> struct vfloat;
|
||||
template<int N> struct vdouble;
|
||||
template<int N> struct vint;
|
||||
template<int N> struct vuint;
|
||||
template<int N> struct vllong;
|
||||
template<int N> struct vboolf; // for float/int
|
||||
template<int N> struct vboold; // for double/long long
|
||||
|
||||
/* Aliases to default types */
|
||||
template<int N> using vreal = vfloat<N>;
|
||||
template<int N> using vbool = vboolf<N>;
|
||||
|
||||
/* Varying size constants */
|
||||
const int VSIZEX = 16; // default size
|
||||
const int VSIZEL = 16; // large size
|
||||
|
||||
/* Extends varying size N to optimal or up to max(N, N2) */
|
||||
template<int N, int N2 = VSIZEX>
|
||||
struct vextend
|
||||
{
|
||||
static const int size = N;
|
||||
#define SIMD_MODE(N) N, N
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/* Varying numeric types */
|
||||
template<int N>
|
||||
struct vfloat
|
||||
@@ -28,7 +57,7 @@ namespace embree
|
||||
__forceinline const float& operator [](size_t index) const { assert(index < N); return f[index]; }
|
||||
__forceinline float& operator [](size_t index) { assert(index < N); return f[index]; }
|
||||
};
|
||||
|
||||
|
||||
template<int N>
|
||||
struct vdouble
|
||||
{
|
||||
@@ -44,7 +73,7 @@ namespace embree
|
||||
__forceinline const int& operator [](size_t index) const { assert(index < N); return i[index]; }
|
||||
__forceinline int& operator [](size_t index) { assert(index < N); return i[index]; }
|
||||
};
|
||||
|
||||
|
||||
template<int N>
|
||||
struct vuint
|
||||
{
|
||||
@@ -64,7 +93,7 @@ namespace embree
|
||||
/* Varying bool types */
|
||||
template<int N> struct vboolf { int i[N]; }; // for float/int
|
||||
template<int N> struct vboold { long long i[N]; }; // for double/long long
|
||||
|
||||
|
||||
/* Aliases to default types */
|
||||
template<int N> using vreal = vfloat<N>;
|
||||
template<int N> using vbool = vboolf<N>;
|
||||
@@ -99,6 +128,8 @@ namespace embree
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* 4-wide shortcuts */
|
||||
typedef vfloat<4> vfloat4;
|
||||
typedef vdouble<4> vdouble4;
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* N-wide SYCL bool type */
|
||||
template<int N>
|
||||
struct vboolf
|
||||
{
|
||||
//ALIGNED_STRUCT_(16);
|
||||
|
||||
typedef vboolf<N> Bool;
|
||||
typedef vint<N> Int;
|
||||
typedef vfloat<N> Float;
|
||||
|
||||
enum { size = N }; // number of SIMD elements
|
||||
//union { __m128 v; int i[N]; }; // data
|
||||
bool v;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf() {}
|
||||
//__forceinline vboolf(const vboolf& other) { v = other.v; }
|
||||
//__forceinline vboolf& operator =(const vboolf& other) { v = other.v; return *this; }
|
||||
|
||||
//__forceinline vboolf(__m128 input) : v(input) {}
|
||||
//__forceinline operator const __m128&() const { return v; }
|
||||
//__forceinline operator const __m128i() const { return _mm_castps_si128(v); }
|
||||
//__forceinline operator const __m128d() const { return _mm_castps_pd(v); }
|
||||
|
||||
__forceinline vboolf(bool a)
|
||||
: v(a) {}
|
||||
|
||||
__forceinline vboolf(bool a, bool b)
|
||||
{
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid == 0) v = a;
|
||||
if (lid == 1) v = b;
|
||||
if (lid == 2) v = a;
|
||||
if (lid == 3) v = b;
|
||||
}
|
||||
|
||||
__forceinline vboolf(bool a, bool b, bool c, bool d)
|
||||
{
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid == 0) v = a;
|
||||
if (lid == 1) v = b;
|
||||
if (lid == 2) v = c;
|
||||
if (lid == 3) v = d;
|
||||
}
|
||||
|
||||
//__forceinline vboolf(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 {
|
||||
// return _mm_castps_si128(v);
|
||||
//}
|
||||
|
||||
vboolf fix_upper(bool c) const {
|
||||
if (N == 16) return c;
|
||||
return vboolf(__spirv_BuiltInSubgroupLocalInvocationId < N ? v : c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf(FalseTy) : v(false) {}
|
||||
__forceinline vboolf(TrueTy) : v(true) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//__forceinline bool operator [](size_t index) const { assert(index < N); return (_mm_movemask_ps(v) >> index) & 1; }
|
||||
//__forceinline int& operator [](size_t index) { assert(index < N); return i[index]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator !(const vboolf<N>& a) { return vboolf<N>(!a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator &(const vboolf<N>& a, const vboolf<N>& b) { return vboolf<N>(a.v && b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator |(const vboolf<N>& a, const vboolf<N>& b) { return vboolf<N>(a.v || b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator ^(const vboolf<N>& a, const vboolf<N>& b) { return vboolf<N>(a.v != b.v); }
|
||||
|
||||
//template<int N> __forceinline vboolf<N> andn(const vboolf<N>& a, const vboolf<N>& b) { return _mm_andnot_ps(b, a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vboolf<N>& operator &=(vboolf<N>& a, const vboolf<N>& b) { return a = a & b; }
|
||||
template<int N> __forceinline vboolf<N>& operator |=(vboolf<N>& a, const vboolf<N>& b) { return a = a | b; }
|
||||
template<int N> __forceinline vboolf<N>& operator ^=(vboolf<N>& a, const vboolf<N>& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator !=(const vboolf<N>& a, const vboolf<N>& b) { return vboolf<N>(a.v != b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator ==(const vboolf<N>& a, const vboolf<N>& b) { return vboolf<N>(a.v == b.v); }
|
||||
|
||||
template<int N> __forceinline vboolf<N> select(const vboolf<N>& m, const vboolf<N>& t, const vboolf<N>& f) {
|
||||
return vboolf<N>(m.v ? t.v : f.v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//template<int N> __forceinline vboolf<N> unpacklo(const vboolf<N>& a, const vboolf<N>& b) { return _mm_unpacklo_ps(a, b); }
|
||||
//template<int N> __forceinline vboolf<N> unpackhi(const vboolf<N>& a, const vboolf<N>& b) { return _mm_unpackhi_ps(a, b); }
|
||||
|
||||
//template<int i0, int i1, int i2, int i3>
|
||||
//template<int N> __forceinline vboolf<N> shuffle(const vboolf<N>& v) {
|
||||
// return _mm_castsi128_ps(_mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
//}
|
||||
|
||||
//template<int i0, int i1, int i2, int i3>
|
||||
//template<int N> __forceinline vboolf<N> shuffle(const vboolf<N>& a, const vboolf<N>& b) {
|
||||
// return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
//}
|
||||
|
||||
//template<int i0>
|
||||
//template<int N> __forceinline vboolf<N> shuffle(const vboolf<N>& v) {
|
||||
// return shuffle<i0,i0,i0,i0>(v);
|
||||
//}
|
||||
|
||||
//template<int dst, int src, int clr> template<int N> __forceinline vboolf<N> insert(const vboolf<N>& a, const vboolf<N>& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
|
||||
//template<int dst, int src> template<int N> __forceinline vboolf<N> insert(const vboolf<N>& a, const vboolf<N>& b) { return insert<dst, src, 0>(a, b); }
|
||||
//template<int dst> template<int N> __forceinline vboolf<N> insert(const vboolf<N>& a, const bool b) { return insert<dst, 0>(a, vboolf<N>(b)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline bool reduce_and(const vboolf<N>& a) {
|
||||
return __spirv_GroupAll(__spv::Scope::Subgroup, a.fix_upper(true).v);
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool reduce_or(const vboolf<N>& a) {
|
||||
return __spirv_GroupAny(__spv::Scope::Subgroup, a.fix_upper(false).v);
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool all(const vboolf<N>& a) {
|
||||
return __spirv_GroupAll(__spv::Scope::Subgroup, a.fix_upper(true).v);
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool any(const vboolf<N>& a) {
|
||||
return __spirv_GroupAny(__spv::Scope::Subgroup, a.fix_upper(false).v);
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool none(const vboolf<N>& a) {
|
||||
return !any(a);
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool all (const vboolf<N>& valid, const vboolf<N>& b) { return all((!valid) | b); }
|
||||
template<int N> __forceinline bool any (const vboolf<N>& valid, const vboolf<N>& b) { return any(valid & b); }
|
||||
template<int N> __forceinline bool none(const vboolf<N>& valid, const vboolf<N>& b) { return none(valid & b); }
|
||||
|
||||
template<int N> __forceinline size_t movemask(const vboolf<N>& a) {
|
||||
return intel_sub_group_ballot(a.fix_upper(false).v);
|
||||
}
|
||||
template<int N> __forceinline size_t popcnt(const vboolf<N>& a) {
|
||||
return cl::sycl::popcount(movemask(a));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//template<int N> __forceinline bool get(const vboolf<N>& a, size_t index) { return a[index]; }
|
||||
//template<int N> __forceinline void set(vboolf<N>& a, size_t index) { a[index] = -1; }
|
||||
//template<int N> __forceinline void clear(vboolf<N>& a, size_t index) { a[index] = 0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> inline const cl::sycl::stream& operator <<(const cl::sycl::stream& cout, const vboolf<N>& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (int i=0; i<N; i++) {
|
||||
if (__spirv_BuiltInSubgroupLocalInvocationId == i) {
|
||||
cout << a.v;
|
||||
if (i != N-1) cout << ", ";
|
||||
}
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
|
||||
template<int N> inline std::ostream& operator <<(std::ostream& cout, const vboolf<N>& a) {
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,595 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* N-wide SSE float type */
|
||||
template<int N>
|
||||
struct vfloat
|
||||
{
|
||||
//ALIGNED_STRUCT_(16);
|
||||
|
||||
typedef vboolf<N> Bool;
|
||||
typedef vint<N> Int;
|
||||
typedef vfloat<N> Float;
|
||||
|
||||
enum { size = N }; // number of SIMD elements
|
||||
//union { __m128 v; float f[N]; int i[N]; }; // data
|
||||
float v;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vfloat() {}
|
||||
//__forceinline vfloat(const vfloat<N>& other) { v = other.v; }
|
||||
//__forceinline vfloat<N>& operator =(const vfloat<N>& other) { v = other.v; return *this; }
|
||||
|
||||
//__forceinline vfloat(__m128 a) : v(a) {}
|
||||
//__forceinline operator const __m128&() const { return v; }
|
||||
//__forceinline operator __m128&() { return v; }
|
||||
|
||||
__forceinline vfloat(float a) : v(a) {}
|
||||
__forceinline vfloat(float a, float b, float c, float d)
|
||||
{
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid == 0) v = a;
|
||||
if (lid == 1) v = b;
|
||||
if (lid == 2) v = c;
|
||||
if (lid == 3) v = d;
|
||||
}
|
||||
|
||||
__forceinline explicit vfloat(const vint<N>& a) : v((float)a.v) {}
|
||||
|
||||
/*__forceinline explicit vfloat(const vuintN& x) {
|
||||
const __m128i a = _mm_and_si128(x,_mm_set1_epi32(0x7FFFFFFF));
|
||||
const __m128i b = _mm_and_si128(_mm_srai_epi32(x,31),_mm_set1_epi32(0x4F000000)); //0x4F000000 = 2^31
|
||||
const __m128 af = _mm_cvtepi32_ps(a);
|
||||
const __m128 bf = _mm_castsi128_ps(b);
|
||||
v = _mm_add_ps(af,bf);
|
||||
}*/
|
||||
|
||||
vfloat<N> fix_upper(float c) const {
|
||||
if (N == 16) return c;
|
||||
return vfloat<N>(__spirv_BuiltInSubgroupLocalInvocationId < N ? v : c);
|
||||
}
|
||||
|
||||
static uint sgid() {
|
||||
if (N == 16) return __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
return cl::sycl::min(__spirv_BuiltInSubgroupLocalInvocationId,unsigned(N-1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vfloat(ZeroTy) : v(0.0f) {}
|
||||
__forceinline vfloat(OneTy) : v(1.0f) {}
|
||||
__forceinline vfloat(PosInfTy) : v(pos_inf) {}
|
||||
__forceinline vfloat(NegInfTy) : v(neg_inf) {}
|
||||
__forceinline vfloat(StepTy) : v(__spirv_BuiltInSubgroupLocalInvocationId) {}
|
||||
//__forceinline vfloat(NaNTy) : v(_mm_set1_ps(nan)) {}
|
||||
//__forceinline vfloat(UndefinedTy) : v(_mm_undefined_ps()) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline vfloat<N> load (const void* a)
|
||||
{
|
||||
if (N == 16) {
|
||||
return vfloat<N>(__spirv_SubgroupBlockReadINTEL<float>((const __attribute__((opencl_global)) uint32_t*) a));
|
||||
} else {
|
||||
return ((float*)a)[vfloat<N>::sgid()];
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline vfloat<N> loadu(const void* a) {
|
||||
return ((float*)a)[vfloat<N>::sgid()];
|
||||
}
|
||||
|
||||
static __forceinline void store (void* ptr, const vfloat<N>& v)
|
||||
{
|
||||
if (N == 16) {
|
||||
__spirv_SubgroupBlockWriteINTEL<uint32_t>((__attribute__((opencl_global)) uint32_t*) ptr, *(uint32_t*)&v.v);
|
||||
} else {
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid < N) ((float*)ptr)[lid] = v.v;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const vfloat<N>& v) {
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid < N) ((float*)ptr)[lid] = v.v;
|
||||
}
|
||||
|
||||
//static __forceinline vfloat<N> compact(const vboolf<N>& mask, vfloat<N> &v) {
|
||||
// return _mm_mask_compress_ps(v, mask, v);
|
||||
//}
|
||||
//static __forceinline vfloat<N> compact(const vboolf<N>& mask, vfloat<N> &a, const vfloat<N>& b) {
|
||||
// return _mm_mask_compress_ps(a, mask, b);
|
||||
//}
|
||||
|
||||
static __forceinline vfloat<N> load (const vboolf<N>& mask, const void* ptr) {
|
||||
if (mask.v) return loadu(ptr); else return vfloat<N>(0.0f);
|
||||
}
|
||||
static __forceinline vfloat<N> loadu(const vboolf<N>& mask, const void* ptr) {
|
||||
if (mask.v) return loadu(ptr); else return vfloat<N>(0.0f);
|
||||
}
|
||||
|
||||
static __forceinline void store (const vboolf<N>& mask, void* ptr, const vfloat<N>& v) {
|
||||
if (mask.v) storeu(ptr,v);
|
||||
}
|
||||
static __forceinline void storeu(const vboolf<N>& mask, void* ptr, const vfloat<N>& v) {
|
||||
if (mask.v) storeu(ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline vfloat<N> broadcast(const void* a) {
|
||||
return vfloat<N>(*(float*)a);
|
||||
}
|
||||
|
||||
static __forceinline vfloat<N> load_nt (const float* ptr) {
|
||||
return load(ptr);
|
||||
}
|
||||
|
||||
static __forceinline void store_nt(void* ptr, const vfloat<N>& v) {
|
||||
store(ptr,v);
|
||||
}
|
||||
|
||||
//static __forceinline vfloat<N> load(const char* ptr) {
|
||||
// return _mm_cvtepi32_ps(_mm_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
//}
|
||||
|
||||
//static __forceinline vfloat<N> load(const unsigned char* ptr) {
|
||||
// return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
//}
|
||||
|
||||
//static __forceinline vfloat<N> load(const short* ptr) {
|
||||
// return _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
//}
|
||||
|
||||
//static __forceinline vfloat<N> load(const unsigned short* ptr) {
|
||||
// return _mm_mul_ps(vfloat<N>(vint<N>::load(ptr)),vfloat<N>(1.0f/65535.0f));
|
||||
//}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline vfloat<N> gather(const float* ptr, const vint<N>& index) {
|
||||
return *(float*)((char*)ptr + scale*index.v);
|
||||
}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline vfloat<N> gather(const vboolf<N>& mask, const float* ptr, const vint<N>& index) {
|
||||
if (mask.v) return gather<scale>(ptr,index);
|
||||
else return vfloat<N>(0.0f);
|
||||
}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline void scatter(void* ptr, const vint<N>& index, const vfloat<N>& v) {
|
||||
*(float*) ((char*)ptr + scale*index.v) = v.v;
|
||||
}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline void scatter(const vboolf<N>& mask, void* ptr, const vint<N>& index, const vfloat<N>& v) {
|
||||
if (mask.v) scatter<scale>(ptr,index,v);
|
||||
}
|
||||
|
||||
static __forceinline void store(const vboolf<N>& mask, char* ptr, const vint<N>& ofs, const vfloat<N>& v) {
|
||||
scatter<1>(mask,ptr,ofs,v);
|
||||
}
|
||||
static __forceinline void store(const vboolf<N>& mask, float* ptr, const vint<N>& ofs, const vfloat<N>& v) {
|
||||
scatter<4>(mask,ptr,ofs,v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float operator [](size_t index) const {
|
||||
assert(index < 4);
|
||||
return __spirv_GroupBroadcast<float>(__spv::Scope::Subgroup, v, index);
|
||||
}
|
||||
__forceinline float operator [](size_t index) {
|
||||
assert(index < 4);
|
||||
return __spirv_GroupBroadcast<float>(__spv::Scope::Subgroup, v, index);
|
||||
}
|
||||
|
||||
friend __forceinline vfloat<N> select(const vboolf<N>& m, const vfloat<N>& t, const vfloat<N>& f) {
|
||||
return m.v ? t : f;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vfloat<N> asFloat(const vint<N>& a) { return vfloat<N>(__builtin_bit_cast(float,a.v)); }
|
||||
template<int N> __forceinline vint<N> asInt (const vfloat<N>& a) { return vint<N>(__builtin_bit_cast(int,a.v)); }
|
||||
//template<int N> __forceinline vuintN asUInt (const vfloat<N>& a) { return _mm_castps_si128(a); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> operator +(const vfloat<N>& a) { return a; }
|
||||
template<int N> __forceinline vfloat<N> operator -(const vfloat<N>& a) { return vfloat<N>(-a.v); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> abs(const vfloat<N>& a) { return vfloat<N>(cl::sycl::fabs(a.v)); }
|
||||
template<int N> __forceinline vfloat<N> sign(const vfloat<N>& a) { return vfloat<N>(cl::sycl::sign(a.v)); }
|
||||
template<int N> __forceinline vfloat<N> signmsk(const vfloat<N>& a) { return asFloat(asInt(a.v) & 0x80000000); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> rcp(const vfloat<N>& a) { return vfloat<N>(cl::sycl::native::recip(a.v)); }
|
||||
//template<int N> __forceinline vfloat<N> rcp(const vfloat<N>& a) { return vfloat<N>(__sycl_std::__invoke_native_recip<float>(a.v)); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> sqr (const vfloat<N>& a) { return vfloat<N>(a.v*a.v); }
|
||||
template<int N> __forceinline vfloat<N> sqrt(const vfloat<N>& a) { return vfloat<N>(cl::sycl::sqrt(a.v)); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> rsqrt(const vfloat<N>& a) { return vfloat<N>(cl::sycl::rsqrt(a.v)); }
|
||||
|
||||
template<int N> __forceinline vboolf<N> isnan(const vfloat<N>& a) { return vboolf<N>(cl::sycl::isnan(a.v)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vfloat<N> operator +(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(a.v+b.v); }
|
||||
template<int N> __forceinline vfloat<N> operator +(const vfloat<N>& a, float b) { return a + vfloat<N>(b); }
|
||||
template<int N> __forceinline vfloat<N> operator +(float a, const vfloat<N>& b) { return vfloat<N>(a) + b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N> operator -(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(a.v-b.v); }
|
||||
template<int N> __forceinline vfloat<N> operator -(const vfloat<N>& a, float b) { return a - vfloat<N>(b); }
|
||||
template<int N> __forceinline vfloat<N> operator -(float a, const vfloat<N>& b) { return vfloat<N>(a) - b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N> operator *(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(a.v*b.v); }
|
||||
template<int N> __forceinline vfloat<N> operator *(const vfloat<N>& a, float b) { return a * vfloat<N>(b); }
|
||||
template<int N> __forceinline vfloat<N> operator *(float a, const vfloat<N>& b) { return vfloat<N>(a) * b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N> operator /(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(a.v/b.v); }
|
||||
template<int N> __forceinline vfloat<N> operator /(const vfloat<N>& a, float b) { return a/vfloat<N>(b); }
|
||||
template<int N> __forceinline vfloat<N> operator /(float a, const vfloat<N>& b) { return vfloat<N>(a)/b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N> operator ^(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(asFloat(asInt(a.v) ^ asInt(b.v))); }
|
||||
template<int N> __forceinline vfloat<N> operator ^(const vfloat<N>& a, const vint<N>& b) { return vfloat<N>(asFloat(asInt(a.v) ^ b.v)); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> min(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(cl::sycl::fmin(a.v,b.v)); }
|
||||
template<int N> __forceinline vfloat<N> min(const vfloat<N>& a, float b) { return min(a,vfloat<N>(b)); }
|
||||
template<int N> __forceinline vfloat<N> min(float a, const vfloat<N>& b) { return min(vfloat<N>(a),b); }
|
||||
|
||||
template<int N> __forceinline vfloat<N> max(const vfloat<N>& a, const vfloat<N>& b) { return vfloat<N>(cl::sycl::fmax(a.v,b.v)); }
|
||||
template<int N> __forceinline vfloat<N> max(const vfloat<N>& a, float b) { return max(a,vfloat<N>(b)); }
|
||||
template<int N> __forceinline vfloat<N> max(float a, const vfloat<N>& b) { return max(vfloat<N>(a),b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vfloat<N> madd (const vfloat<N>& a, const vfloat<N>& b, const vfloat<N>& c) { return vfloat<N>(+cl::sycl::fma(+a.v,b.v,+c.v)); }
|
||||
template<int N> __forceinline vfloat<N> msub (const vfloat<N>& a, const vfloat<N>& b, const vfloat<N>& c) { return vfloat<N>(+cl::sycl::fma(+a.v,b.v,-c.v)); }
|
||||
template<int N> __forceinline vfloat<N> nmadd(const vfloat<N>& a, const vfloat<N>& b, const vfloat<N>& c) { return vfloat<N>(+cl::sycl::fma(-a.v,b.v,+c.v));}
|
||||
template<int N> __forceinline vfloat<N> nmsub(const vfloat<N>& a, const vfloat<N>& b, const vfloat<N>& c) { return vfloat<N>(-cl::sycl::fma(+a.v,b.v,+c.v)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vfloat<N>& operator +=(vfloat<N>& a, const vfloat<N>& b) { return a = a + b; }
|
||||
template<int N> __forceinline vfloat<N>& operator +=(vfloat<N>& a, float b) { return a = a + b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N>& operator -=(vfloat<N>& a, const vfloat<N>& b) { return a = a - b; }
|
||||
template<int N> __forceinline vfloat<N>& operator -=(vfloat<N>& a, float b) { return a = a - b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N>& operator *=(vfloat<N>& a, const vfloat<N>& b) { return a = a * b; }
|
||||
template<int N> __forceinline vfloat<N>& operator *=(vfloat<N>& a, float b) { return a = a * b; }
|
||||
|
||||
template<int N> __forceinline vfloat<N>& operator /=(vfloat<N>& a, const vfloat<N>& b) { return a = a / b; }
|
||||
template<int N> __forceinline vfloat<N>& operator /=(vfloat<N>& a, float b) { return a = a / b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator ==(const vfloat<N>& a, const vfloat<N>& b) { return vboolf<N>(a.v == b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator !=(const vfloat<N>& a, const vfloat<N>& b) { return vboolf<N>(a.v != b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator < (const vfloat<N>& a, const vfloat<N>& b) { return vboolf<N>(a.v < b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator >=(const vfloat<N>& a, const vfloat<N>& b) { return vboolf<N>(a.v >= b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator > (const vfloat<N>& a, const vfloat<N>& b) { return vboolf<N>(a.v > b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator <=(const vfloat<N>& a, const vfloat<N>& b) { return vboolf<N>(a.v <= b.v); }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator ==(const vfloat<N>& a, float b) { return a == vfloat<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator ==(float a, const vfloat<N>& b) { return vfloat<N>(a) == b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator !=(const vfloat<N>& a, float b) { return a != vfloat<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator !=(float a, const vfloat<N>& b) { return vfloat<N>(a) != b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator < (const vfloat<N>& a, float b) { return a < vfloat<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator < (float a, const vfloat<N>& b) { return vfloat<N>(a) < b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator >=(const vfloat<N>& a, float b) { return a >= vfloat<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator >=(float a, const vfloat<N>& b) { return vfloat<N>(a) >= b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator > (const vfloat<N>& a, float b) { return a > vfloat<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator > (float a, const vfloat<N>& b) { return vfloat<N>(a) > b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator <=(const vfloat<N>& a, float b) { return a <= vfloat<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator <=(float a, const vfloat<N>& b) { return vfloat<N>(a) <= b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> eq(const vfloat<N>& a, const vfloat<N>& b) { return a == b; }
|
||||
template<int N> __forceinline vboolf<N> ne(const vfloat<N>& a, const vfloat<N>& b) { return a != b; }
|
||||
template<int N> __forceinline vboolf<N> lt(const vfloat<N>& a, const vfloat<N>& b) { return a < b; }
|
||||
template<int N> __forceinline vboolf<N> ge(const vfloat<N>& a, const vfloat<N>& b) { return a >= b; }
|
||||
template<int N> __forceinline vboolf<N> gt(const vfloat<N>& a, const vfloat<N>& b) { return a > b; }
|
||||
template<int N> __forceinline vboolf<N> le(const vfloat<N>& a, const vfloat<N>& b) { return a <= b; }
|
||||
|
||||
//template<int N> __forceinline vboolf<N> eq(const vboolf<N>& mask, const vfloat<N>& a, const vfloat<N>& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_EQ); }
|
||||
//template<int N> __forceinline vboolf<N> ne(const vboolf<N>& mask, const vfloat<N>& a, const vfloat<N>& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_NE); }
|
||||
//template<int N> __forceinline vboolf<N> lt(const vboolf<N>& mask, const vfloat<N>& a, const vfloat<N>& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LT); }
|
||||
//template<int N> __forceinline vboolf<N> ge(const vboolf<N>& mask, const vfloat<N>& a, const vfloat<N>& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GE); }
|
||||
//template<int N> __forceinline vboolf<N> gt(const vboolf<N>& mask, const vfloat<N>& a, const vfloat<N>& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_GT); }
|
||||
//template<int N> __forceinline vboolf<N> le(const vboolf<N>& mask, const vfloat<N>& a, const vfloat<N>& b) { return _mm_mask_cmp_ps_mask(mask, a, b, _MM_CMPINT_LE); }
|
||||
|
||||
/*
|
||||
template<int mask>
|
||||
template<int N> __forceinline vfloat<N> select(const vfloat<N>& t, const vfloat<N>& f)
|
||||
{
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_blend_ps(f, t, mask);
|
||||
#else
|
||||
return select(vboolf<N>(mask), t, f);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
template<int N> __forceinline vfloat<N> lerp(const float& a, const float& b, const vfloat<N>& t) {
|
||||
return vfloat<N>(madd(t.v,b-a,a));
|
||||
}
|
||||
|
||||
template<int N> __forceinline vfloat<N> lerp(const vfloat<N>& a, const vfloat<N>& b, const vfloat<N>& t) {
|
||||
return vfloat<N>(madd(t.v,b.v-a.v,a.v));
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool isvalid(const vfloat<N>& v) {
|
||||
return all((v > vfloat<N>(-FLT_LARGE)) & (v < vfloat<N>(+FLT_LARGE)));
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool is_finite(const vfloat<N>& a) {
|
||||
return all((a >= vfloat<N>(-FLT_MAX)) & (a <= vfloat<N>(+FLT_MAX)));
|
||||
}
|
||||
|
||||
template<int N> __forceinline bool is_finite(const vboolf<N>& valid, const vfloat<N>& a) {
|
||||
return all(valid, (a >= vfloat<N>(-FLT_MAX)) & (a <= vfloat<N>(+FLT_MAX)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Rounding Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vfloat<N> floor(const vfloat<N>& a) { return vfloat<N>(cl::sycl::floor(a.v)); }
|
||||
template<int N> __forceinline vfloat<N> ceil (const vfloat<N>& a) { return vfloat<N>(cl::sycl::ceil(a.v)); }
|
||||
template<int N> __forceinline vfloat<N> trunc(const vfloat<N>& a) { return vfloat<N>(cl::sycl::trunc(a.v)); }
|
||||
template<int N> __forceinline vfloat<N> frac (const vfloat<N>& a) { return a-floor(a); }
|
||||
template<int N> __forceinline vint<N> floori(const vfloat<N>& a){ return vint<N>((int)floor(a).v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
template<int N> __forceinline vfloat<N> unpacklo(const vfloat<N>& a, const vfloat<N>& b) { return _mm_unpacklo_ps(a, b); }
|
||||
template<int N> __forceinline vfloat<N> unpackhi(const vfloat<N>& a, const vfloat<N>& b) { return _mm_unpackhi_ps(a, b); }
|
||||
*/
|
||||
|
||||
template<int i0, int i1, int i2, int i3, int N>
|
||||
__forceinline vfloat<N> shuffle(const vfloat<N>& v) {
|
||||
return vfloat<N>(__spirv_SubgroupShuffleINTEL(v.v, vint<N>(i0,i1,i2,i3).v));
|
||||
}
|
||||
/*
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
template<int N> __forceinline vfloat<N> shuffle(const vfloat<N>& a, const vfloat<N>& b) {
|
||||
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
template<int N> __forceinline vfloat<N> shuffle8(const vfloat<N>& a, const vint<N>& shuf) {
|
||||
return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
|
||||
}
|
||||
*/
|
||||
|
||||
template<int i, int N>
|
||||
__forceinline vfloat<N> shuffle(const vfloat<N>& v) {
|
||||
return vfloat<N>(__spirv_GroupBroadcast(__spv::Scope::Subgroup, v.v, i));
|
||||
}
|
||||
|
||||
template<int i, int N> __forceinline float extract(const vfloat<N>& a) {
|
||||
return __spirv_GroupBroadcast(__spv::Scope::Subgroup, a.v, i);
|
||||
}
|
||||
/*
|
||||
#if defined (__SSE4_1__)
|
||||
template<int dst, int src, int clr> template<int N> __forceinline vfloat<N> insert(const vfloat<N>& a, const vfloat<N>& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
|
||||
template<int dst, int src> template<int N> __forceinline vfloat<N> insert(const vfloat<N>& a, const vfloat<N>& b) { return insert<dst, src, 0>(a, b); }
|
||||
template<int dst> template<int N> __forceinline vfloat<N> insert(const vfloat<N>& a, const float b) { return insert<dst, 0>(a, _mm_set_ss(b)); }
|
||||
#else
|
||||
template<int dst, int src> template<int N> __forceinline vfloat<N> insert(const vfloat<N>& a, const vfloat<N>& b) { vfloat<N> c = a; c[dst&3] = b[src&3]; return c; }
|
||||
template<int dst> template<int N> __forceinline vfloat<N> insert(const vfloat<N>& a, float b) { vfloat<N> c = a; c[dst&3] = b; return c; }
|
||||
#endif
|
||||
*/
|
||||
template<int N> __forceinline float toScalar(const vfloat<N>& v) { return extract<0>(v); }
|
||||
|
||||
/*
|
||||
template<int N> __forceinline vfloat<N> broadcast4f(const vfloat<N>& a, size_t k) {
|
||||
return vfloat<N>::broadcast(&a[k]);
|
||||
}
|
||||
*/
|
||||
|
||||
template<int N> __forceinline vfloat<N> shift_right_1(const vfloat<N>& x) {
|
||||
return vfloat<N>(__spirv_SubgroupShuffleDownINTEL(x.v, x.v, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
template<int N> __forceinline vfloat<N> permute(const vfloat<N> &a, const __m128i &index) {
|
||||
return _mm_permutevar_ps(a,index);
|
||||
}
|
||||
*/
|
||||
template<int N> __forceinline vfloat<N> broadcast1f(const void* a) {
|
||||
return vfloat<N>::broadcast(a);
|
||||
}
|
||||
|
||||
/*
|
||||
template<int i>
|
||||
template<int N> __forceinline vfloat<N> align_shift_right(const vfloat<N>& a, const vfloat<N>& b) {
|
||||
return _mm_castsi128_ps(_mm_alignr_epi32(_mm_castps_si128(a), _mm_castps_si128(b), i));
|
||||
}
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sorting Network
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
template<int N> __forceinline vfloat<N> sort_ascending(const vfloat<N>& v)
|
||||
{
|
||||
const vfloat<N> a0 = v;
|
||||
const vfloat<N> b0 = shuffle<1,0,3,2>(a0);
|
||||
const vfloat<N> c0 = min(a0,b0);
|
||||
const vfloat<N> d0 = max(a0,b0);
|
||||
const vfloat<N> a1 = select<0x5 /* 0b0101 */>(c0,d0);
|
||||
const vfloat<N> b1 = shuffle<2,3,0,1>(a1);
|
||||
const vfloat<N> c1 = min(a1,b1);
|
||||
const vfloat<N> d1 = max(a1,b1);
|
||||
const vfloat<N> a2 = select<0x3 /* 0b0011 */>(c1,d1);
|
||||
const vfloat<N> b2 = shuffle<0,2,1,3>(a2);
|
||||
const vfloat<N> c2 = min(a2,b2);
|
||||
const vfloat<N> d2 = max(a2,b2);
|
||||
const vfloat<N> a3 = select<0x2 /* 0b0010 */>(c2,d2);
|
||||
return a3;
|
||||
}
|
||||
|
||||
template<int N> __forceinline vfloat<N> sort_descending(const vfloat<N>& v)
|
||||
{
|
||||
const vfloat<N> a0 = v;
|
||||
const vfloat<N> b0 = shuffle<1,0,3,2>(a0);
|
||||
const vfloat<N> c0 = max(a0,b0);
|
||||
const vfloat<N> d0 = min(a0,b0);
|
||||
const vfloat<N> a1 = select<0x5 /* 0b0101 */>(c0,d0);
|
||||
const vfloat<N> b1 = shuffle<2,3,0,1>(a1);
|
||||
const vfloat<N> c1 = max(a1,b1);
|
||||
const vfloat<N> d1 = min(a1,b1);
|
||||
const vfloat<N> a2 = select<0x3 /* 0b0011 */>(c1,d1);
|
||||
const vfloat<N> b2 = shuffle<0,2,1,3>(a2);
|
||||
const vfloat<N> c2 = max(a2,b2);
|
||||
const vfloat<N> d2 = min(a2,b2);
|
||||
const vfloat<N> a3 = select<0x2 /* 0b0010 */>(c2,d2);
|
||||
return a3;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Transpose
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
template<int N> __forceinline void transpose(const vfloat<N>& r0, const vfloat<N>& r1, const vfloat<N>& r2, const vfloat<N>& r3, vfloat<N>& c0, vfloat<N>& c1, vfloat<N>& c2, vfloat<N>& c3)
|
||||
{
|
||||
vfloat<N> l02 = unpacklo(r0,r2);
|
||||
vfloat<N> h02 = unpackhi(r0,r2);
|
||||
vfloat<N> l13 = unpacklo(r1,r3);
|
||||
vfloat<N> h13 = unpackhi(r1,r3);
|
||||
c0 = unpacklo(l02,l13);
|
||||
c1 = unpackhi(l02,l13);
|
||||
c2 = unpacklo(h02,h13);
|
||||
c3 = unpackhi(h02,h13);
|
||||
}
|
||||
|
||||
template<int N> __forceinline void transpose(const vfloat<N>& r0, const vfloat<N>& r1, const vfloat<N>& r2, const vfloat<N>& r3, vfloat<N>& c0, vfloat<N>& c1, vfloat<N>& c2)
|
||||
{
|
||||
vfloat<N> l02 = unpacklo(r0,r2);
|
||||
vfloat<N> h02 = unpackhi(r0,r2);
|
||||
vfloat<N> l13 = unpacklo(r1,r3);
|
||||
vfloat<N> h13 = unpackhi(r1,r3);
|
||||
c0 = unpacklo(l02,l13);
|
||||
c1 = unpackhi(l02,l13);
|
||||
c2 = unpacklo(h02,h13);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vfloat<N> vreduce_min(const vfloat<N>& v) {
|
||||
return cl::sycl::detail::calc<float, __spv::GroupOperation::Reduce>(v.fix_upper(+INFINITY).v, cl::sycl::intel::minimum<float>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline vfloat<N> vreduce_max(const vfloat<N>& v) {
|
||||
return cl::sycl::detail::calc<float, __spv::GroupOperation::Reduce>(v.fix_upper(-INFINITY).v, cl::sycl::intel::maximum<float>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline vfloat<N> vreduce_add(const vfloat<N>& v) {
|
||||
return cl::sycl::detail::calc<float, __spv::GroupOperation::Reduce>(v.fix_upper(0.0f).v, cl::sycl::intel::plus<float>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline float reduce_min(const vfloat<N>& v) { return vreduce_min(v).v; }
|
||||
template<int N> __forceinline float reduce_max(const vfloat<N>& v) { return vreduce_max(v).v; }
|
||||
template<int N> __forceinline float reduce_add(const vfloat<N>& v) { return vreduce_add(v).v; }
|
||||
|
||||
template<int N> __forceinline size_t select_min(const vboolf<N>& valid, const vfloat<N>& v)
|
||||
{
|
||||
const vfloat<N> a = select(valid,v,vfloat<N>(pos_inf));
|
||||
const vboolf<N> valid_min = valid & (a == vreduce_min(a));
|
||||
return cl::sycl::intel::ctz(movemask(any(valid_min) ? valid_min : valid));
|
||||
}
|
||||
template<int N> __forceinline size_t select_max(const vboolf<N>& valid, const vfloat<N>& v)
|
||||
{
|
||||
const vfloat<N> a = select(valid,v,vfloat<N>(neg_inf));
|
||||
const vboolf<N> valid_max = valid & (a == vreduce_max(a));
|
||||
return cl::sycl::intel::ctz(movemask(any(valid_max) ? valid_max : valid));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline float dot(const vfloat<N>& a, const vfloat<N>& b) {
|
||||
return cl::sycl::detail::calc<float, __spv::GroupOperation::Reduce>((a*b).fix_upper(0.0f).v, cl::sycl::intel::plus<float>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline vfloat<N> cross(const vfloat<N>& a, const vfloat<N>& b)
|
||||
{
|
||||
const vfloat<N> a0 = a;
|
||||
const vfloat<N> b0 = shuffle<1,2,0,3>(b);
|
||||
const vfloat<N> a1 = shuffle<1,2,0,3>(a);
|
||||
const vfloat<N> b1 = b;
|
||||
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> inline const cl::sycl::stream& operator <<(const cl::sycl::stream& cout, const vfloat<N>& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (int i=0; i<N; i++) {
|
||||
if (__spirv_BuiltInSubgroupLocalInvocationId == i) {
|
||||
cout << a.v;
|
||||
if (i != N-1) cout << ", ";
|
||||
}
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
|
||||
template<int N> inline std::ostream& operator <<(std::ostream& cout, const vfloat<N>& a) {
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../math/math.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 4-wide SSE integer type */
|
||||
template<int N>
|
||||
struct vint
|
||||
{
|
||||
//ALIGNED_STRUCT_(16);
|
||||
|
||||
typedef vboolf<N> Bool;
|
||||
typedef vint<N> Int;
|
||||
typedef vfloat<N> Float;
|
||||
|
||||
enum { size = N }; // number of SIMD elements
|
||||
//union { __m128i v; int i[N]; }; // data
|
||||
int v;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vint() {}
|
||||
//__forceinline vint(const vint<N>& a) { v = a.v; }
|
||||
//__forceinline vint<N>& operator =(const vint<N>& a) { v = a.v; return *this; }
|
||||
|
||||
//__forceinline vint(__m128i a) : v(a) {}
|
||||
//__forceinline operator const __m128i&() const { return v; }
|
||||
//__forceinline operator __m128i&() { return v; }
|
||||
|
||||
__forceinline vint(int a) : v(a) {}
|
||||
__forceinline vint(int a, int b, int c, int d)
|
||||
{
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid == 0) v = a;
|
||||
if (lid == 1) v = b;
|
||||
if (lid == 2) v = c;
|
||||
if (lid == 3) v = d;
|
||||
}
|
||||
|
||||
//__forceinline explicit vint(__m128 a) : v(_mm_cvtps_epi32(a)) {}
|
||||
//__forceinline explicit vint(const vboolf<N>& a) : v(_mm_castps_si128((__m128)a)) {}
|
||||
|
||||
//__forceinline vint(long long a, long long b) : v(_mm_set_epi64x(b,a)) {}
|
||||
|
||||
vint<N> fix_upper(int c) const {
|
||||
return vint<N>(__spirv_BuiltInSubgroupLocalInvocationId < N ? v : c);
|
||||
}
|
||||
|
||||
static uint sgid() {
|
||||
if (N == 16) return __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
return cl::sycl::min(__spirv_BuiltInSubgroupLocalInvocationId,unsigned(N-1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vint(ZeroTy) : v(0) {}
|
||||
__forceinline vint(OneTy) : v(1) {}
|
||||
__forceinline vint(PosInfTy) : v(0x7FFFFFFF) {}
|
||||
__forceinline vint(NegInfTy) : v(0x80000000) {}
|
||||
__forceinline vint(StepTy) : v(__spirv_BuiltInSubgroupLocalInvocationId) {}
|
||||
//__forceinline vint(ReverseStepTy) : v(_mm_set_epi32(0, 1, 2, 3)) {}
|
||||
|
||||
//__forceinline vint(TrueTy) { v = _mm_cmpeq_epi32(v,v); }
|
||||
//__forceinline vint(UndefinedTy) : v(_mm_castps_si128(_mm_undefined_ps())) {}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline vint<N> load (const void* a)
|
||||
{
|
||||
if (N == 16) {
|
||||
return vint<N>(__spirv_SubgroupBlockReadINTEL<uint32_t>((const __attribute__((opencl_global)) uint32_t*) a));
|
||||
} else {
|
||||
return ((int*)a)[vint<N>::sgid()];
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline vint<N> loadu(const void* a) {
|
||||
return ((int*)a)[vint<N>::sgid()];
|
||||
}
|
||||
|
||||
static __forceinline void store (void* ptr, const vint<N>& v)
|
||||
{
|
||||
if (N == 16) {
|
||||
__spirv_SubgroupBlockWriteINTEL<uint32_t>((__attribute__((opencl_global)) uint32_t*) ptr, *(uint32_t*)&v.v);
|
||||
} else {
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid < N) ((int*)ptr)[lid] = v.v;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const vint<N>& v) {
|
||||
const uint lid = __spirv_BuiltInSubgroupLocalInvocationId;
|
||||
if (lid < N) ((int*)ptr)[lid] = v.v;
|
||||
}
|
||||
|
||||
//static __forceinline vint<N> compact(const vboolf<N>& mask, vint<N> &v) {
|
||||
// return _mm_mask_compress_ps(v, mask, v);
|
||||
//}
|
||||
//static __forceinline vint<N> compact(const vboolf<N>& mask, vint<N> &a, const vint<N>& b) {
|
||||
// return _mm_mask_compress_ps(a, mask, b);
|
||||
//}
|
||||
|
||||
static __forceinline vint<N> load (const vboolf<N>& mask, const void* ptr) {
|
||||
if (mask.v) return loadu(ptr); else return vint<N>(0.0f);
|
||||
}
|
||||
static __forceinline vint<N> loadu(const vboolf<N>& mask, const void* ptr) {
|
||||
if (mask.v) return loadu(ptr); else return vint<N>(0.0f);
|
||||
}
|
||||
|
||||
static __forceinline void store (const vboolf<N>& mask, void* ptr, const vint<N>& v) {
|
||||
if (mask.v) storeu(ptr,v);
|
||||
}
|
||||
static __forceinline void storeu(const vboolf<N>& mask, void* ptr, const vint<N>& v) {
|
||||
if (mask.v) storeu(ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline vint<N> broadcast(const void* a) {
|
||||
return vint<N>(*(int*)a);
|
||||
}
|
||||
|
||||
static __forceinline vint<N> load_nt (const int* ptr) {
|
||||
return load(ptr);
|
||||
}
|
||||
|
||||
static __forceinline void store_nt(void* ptr, const vint<N>& v) {
|
||||
store(ptr,v);
|
||||
}
|
||||
|
||||
//static __forceinline vint<N> load(const char* ptr) {
|
||||
// return _mm_cvtepi32_ps(_mm_cvtepi8_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
//}
|
||||
|
||||
//static __forceinline vint<N> load(const unsigned char* ptr) {
|
||||
// return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
//}
|
||||
|
||||
//static __forceinline vint<N> load(const short* ptr) {
|
||||
// return _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
//}
|
||||
|
||||
//static __forceinline vint<N> load(const unsigned short* ptr) {
|
||||
// return _mm_mul_ps(vint<N>(vint<N>::load(ptr)),vint<N>(1.0f/65535.0f));
|
||||
//}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline vint<N> gather(const int* ptr, const vint<N>& index) {
|
||||
return *(int*)((char*)ptr + scale*index.v);
|
||||
}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline vint<N> gather(const vboolf<N>& mask, const int* ptr, const vint<N>& index) {
|
||||
if (mask.v) return gather<scale>(ptr,index);
|
||||
else return vint<N>(0.0f);
|
||||
}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline void scatter(void* ptr, const vint<N>& index, const vint<N>& v) {
|
||||
*(int*) ((char*)ptr + scale*index.v) = v.v;
|
||||
}
|
||||
|
||||
template<int scale = 4>
|
||||
static __forceinline void scatter(const vboolf<N>& mask, void* ptr, const vint<N>& index, const vint<N>& v) {
|
||||
if (mask.v) scatter<scale>(ptr,index,v);
|
||||
}
|
||||
|
||||
static __forceinline void store(const vboolf<N>& mask, char* ptr, const vint<N>& ofs, const vint<N>& v) {
|
||||
scatter<1>(mask,ptr,ofs,v);
|
||||
}
|
||||
static __forceinline void store(const vboolf<N>& mask, int* ptr, const vint<N>& ofs, const vint<N>& v) {
|
||||
scatter<4>(mask,ptr,ofs,v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int operator [](size_t index) const {
|
||||
assert(index < 4);
|
||||
return __spirv_GroupBroadcast<int>(__spv::Scope::Subgroup, v, index);
|
||||
}
|
||||
__forceinline int operator [](size_t index) {
|
||||
assert(index < 4);
|
||||
return __spirv_GroupBroadcast<int>(__spv::Scope::Subgroup, v, index);
|
||||
}
|
||||
|
||||
friend __forceinline vint<N> select(const vboolf<N>& m, const vint<N>& t, const vint<N>& f) {
|
||||
return m.v ? t : f;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//template<int N> __forceinline vboolf<N> asBool(const vint<N>& a) { return _mm_movepi32_mask(a); }
|
||||
|
||||
template<int N> __forceinline vint<N> operator +(const vint<N>& a) { return vint<N>(+a.v); }
|
||||
template<int N> __forceinline vint<N> operator -(const vint<N>& a) { return vint<N>(-a.v); }
|
||||
template<int N> __forceinline vint<N> abs (const vint<N>& a) { return vint<N>(std::abs(a.v)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vint<N> operator +(const vint<N>& a, const vint<N>& b) { return vint<N>(a.v+b.v); }
|
||||
template<int N> __forceinline vint<N> operator +(const vint<N>& a, int b) { return a + vint<N>(b); }
|
||||
template<int N> __forceinline vint<N> operator +(int a, const vint<N>& b) { return vint<N>(a) + b; }
|
||||
|
||||
template<int N> __forceinline vint<N> operator -(const vint<N>& a, const vint<N>& b) { return vint<N>(a.v+b.v); }
|
||||
template<int N> __forceinline vint<N> operator -(const vint<N>& a, int b) { return a - vint<N>(b); }
|
||||
template<int N> __forceinline vint<N> operator -(int a, const vint<N>& b) { return vint<N>(a) - b; }
|
||||
|
||||
template<int N> __forceinline vint<N> operator *(const vint<N>& a, const vint<N>& b) { return vint<N>(a.v*b.v); }
|
||||
template<int N> __forceinline vint<N> operator *(const vint<N>& a, int b) { return a * vint<N>(b); }
|
||||
template<int N> __forceinline vint<N> operator *(int a, const vint<N>& b) { return vint<N>(a) * b; }
|
||||
|
||||
template<int N> __forceinline vint<N> operator &(const vint<N>& a, const vint<N>& b) { return vint<N>(a.v & b.v); }
|
||||
template<int N> __forceinline vint<N> operator &(const vint<N>& a, int b) { return a & vint<N>(b); }
|
||||
template<int N> __forceinline vint<N> operator &(int a, const vint<N>& b) { return vint<N>(a) & b; }
|
||||
|
||||
template<int N> __forceinline vint<N> operator |(const vint<N>& a, const vint<N>& b) { return vint<N>(a.v | b.v); }
|
||||
template<int N> __forceinline vint<N> operator |(const vint<N>& a, int b) { return a | vint<N>(b); }
|
||||
template<int N> __forceinline vint<N> operator |(int a, const vint<N>& b) { return vint<N>(a) | b; }
|
||||
|
||||
template<int N> __forceinline vint<N> operator ^(const vint<N>& a, const vint<N>& b) { return vint<N>(a.v ^ b.v); }
|
||||
template<int N> __forceinline vint<N> operator ^(const vint<N>& a, int b) { return a ^ vint<N>(b); }
|
||||
template<int N> __forceinline vint<N> operator ^(int a, const vint<N>& b) { return vint<N>(a) ^ b; }
|
||||
|
||||
template<int N> __forceinline vint<N> operator <<(const vint<N>& a, int n) { return vint<N>(a.v << n); }
|
||||
template<int N> __forceinline vint<N> operator >>(const vint<N>& a, int n) { return vint<N>(a.v >> n); }
|
||||
|
||||
template<int N> __forceinline vint<N> sll (const vint<N>& a, int b) { return vint<N>(a.v << b); }
|
||||
template<int N> __forceinline vint<N> sra (const vint<N>& a, int b) { return vint<N>(a.v >> b); }
|
||||
template<int N> __forceinline vint<N> srl (const vint<N>& a, int b) { return vint<N>(unsigned(a.v) >> b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vint<N>& operator +=(vint<N>& a, const vint<N>& b) { return a = a + b; }
|
||||
template<int N> __forceinline vint<N>& operator +=(vint<N>& a, int b) { return a = a + b; }
|
||||
|
||||
template<int N> __forceinline vint<N>& operator -=(vint<N>& a, const vint<N>& b) { return a = a - b; }
|
||||
template<int N> __forceinline vint<N>& operator -=(vint<N>& a, int b) { return a = a - b; }
|
||||
|
||||
template<int N> __forceinline vint<N>& operator *=(vint<N>& a, const vint<N>& b) { return a = a * b; }
|
||||
template<int N> __forceinline vint<N>& operator *=(vint<N>& a, int b) { return a = a * b; }
|
||||
|
||||
template<int N> __forceinline vint<N>& operator &=(vint<N>& a, const vint<N>& b) { return a = a & b; }
|
||||
template<int N> __forceinline vint<N>& operator &=(vint<N>& a, int b) { return a = a & b; }
|
||||
|
||||
template<int N> __forceinline vint<N>& operator |=(vint<N>& a, const vint<N>& b) { return a = a | b; }
|
||||
template<int N> __forceinline vint<N>& operator |=(vint<N>& a, int b) { return a = a | b; }
|
||||
|
||||
template<int N> __forceinline vint<N>& operator <<=(vint<N>& a, int b) { return a = a << b; }
|
||||
template<int N> __forceinline vint<N>& operator >>=(vint<N>& a, int b) { return a = a >> b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator ==(const vint<N>& a, const vint<N>& b) { return vboolf<N>(a.v == b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator !=(const vint<N>& a, const vint<N>& b) { return vboolf<N>(a.v != b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator < (const vint<N>& a, const vint<N>& b) { return vboolf<N>(a.v < b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator >=(const vint<N>& a, const vint<N>& b) { return vboolf<N>(a.v >= b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator > (const vint<N>& a, const vint<N>& b) { return vboolf<N>(a.v > b.v); }
|
||||
template<int N> __forceinline vboolf<N> operator <=(const vint<N>& a, const vint<N>& b) { return vboolf<N>(a.v <= b.v); }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator ==(const vint<N>& a, int b) { return a == vint<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator ==(int a, const vint<N>& b) { return vint<N>(a) == b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator !=(const vint<N>& a, int b) { return a != vint<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator !=(int a, const vint<N>& b) { return vint<N>(a) != b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator < (const vint<N>& a, int b) { return a < vint<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator < (int a, const vint<N>& b) { return vint<N>(a) < b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator >=(const vint<N>& a, int b) { return a >= vint<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator >=(int a, const vint<N>& b) { return vint<N>(a) >= b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator > (const vint<N>& a, int b) { return a > vint<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator > (int a, const vint<N>& b) { return vint<N>(a) > b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> operator <=(const vint<N>& a, int b) { return a <= vint<N>(b); }
|
||||
template<int N> __forceinline vboolf<N> operator <=(int a, const vint<N>& b) { return vint<N>(a) <= b; }
|
||||
|
||||
template<int N> __forceinline vboolf<N> eq(const vint<N>& a, const vint<N>& b) { return a == b; }
|
||||
template<int N> __forceinline vboolf<N> ne(const vint<N>& a, const vint<N>& b) { return a != b; }
|
||||
template<int N> __forceinline vboolf<N> lt(const vint<N>& a, const vint<N>& b) { return a < b; }
|
||||
template<int N> __forceinline vboolf<N> ge(const vint<N>& a, const vint<N>& b) { return a >= b; }
|
||||
template<int N> __forceinline vboolf<N> gt(const vint<N>& a, const vint<N>& b) { return a > b; }
|
||||
template<int N> __forceinline vboolf<N> le(const vint<N>& a, const vint<N>& b) { return a <= b; }
|
||||
|
||||
//template<int N> __forceinline vboolf<N> eq(const vboolf<N>& mask, const vint<N>& a, const vint<N>& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_EQ); }
|
||||
//template<int N> __forceinline vboolf<N> ne(const vboolf<N>& mask, const vint<N>& a, const vint<N>& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_NE); }
|
||||
//template<int N> __forceinline vboolf<N> lt(const vboolf<N>& mask, const vint<N>& a, const vint<N>& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); }
|
||||
//template<int N> __forceinline vboolf<N> ge(const vboolf<N>& mask, const vint<N>& a, const vint<N>& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GE); }
|
||||
//template<int N> __forceinline vboolf<N> gt(const vboolf<N>& mask, const vint<N>& a, const vint<N>& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_GT); }
|
||||
//template<int N> __forceinline vboolf<N> le(const vboolf<N>& mask, const vint<N>& a, const vint<N>& b) { return _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LE); }
|
||||
|
||||
/*
|
||||
template<int mask>
|
||||
template<int N> __forceinline vint<N> select(const vint<N>& t, const vint<N>& f) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
|
||||
#else
|
||||
return select(vboolf<N>(mask), t, f);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
template<int N> __forceinline vint<N> min(const vint<N>& a, const vint<N>& b) { return vint<N>(cl::sycl::min(a.v,b.v)); }
|
||||
template<int N> __forceinline vint<N> max(const vint<N>& a, const vint<N>& b) { return vint<N>(cl::sycl::max(a.v,b.v)); }
|
||||
|
||||
template<int N> __forceinline vint<N> umin(const vint<N>& a, const vint<N>& b) { return vint<N>(cl::sycl::min(unsigned(a.v),unsigned(b.v))); }
|
||||
template<int N> __forceinline vint<N> umax(const vint<N>& a, const vint<N>& b) { return vint<N>(cl::sycl::max(unsigned(a.v),unsigned(b.v))); }
|
||||
|
||||
template<int N> __forceinline vint<N> min(const vint<N>& a, int b) { return min(a,vint<N>(b)); }
|
||||
template<int N> __forceinline vint<N> min(int a, const vint<N>& b) { return min(vint<N>(a),b); }
|
||||
template<int N> __forceinline vint<N> max(const vint<N>& a, int b) { return max(a,vint<N>(b)); }
|
||||
template<int N> __forceinline vint<N> max(int a, const vint<N>& b) { return max(vint<N>(a),b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
template<int N> __forceinline vint<N> unpacklo(const vint<N>& a, const vint<N>& b) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
|
||||
template<int N> __forceinline vint<N> unpackhi(const vint<N>& a, const vint<N>& b) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b))); }
|
||||
*/
|
||||
|
||||
template<int i0, int i1, int i2, int i3, int N>
|
||||
__forceinline vint<N> shuffle(const vint<N>& v) {
|
||||
return vint<N>(__spirv_SubgroupShuffleINTEL(v.v, vint<N>(i0,i1,i2,i3).v));
|
||||
}
|
||||
|
||||
/*
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
template<int N> __forceinline vint<N> shuffle(const vint<N>& a, const vint<N>& b) {
|
||||
return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
*/
|
||||
|
||||
template<int i, int N>
|
||||
__forceinline vint<N> shuffle(const vint<N>& v) {
|
||||
return vint<N>(__spirv_GroupBroadcast(__spv::Scope::Subgroup, v.v, i));
|
||||
}
|
||||
|
||||
template<int i, int N> __forceinline int extract(const vint<N>& a) {
|
||||
return __spirv_GroupBroadcast(__spv::Scope::Subgroup, a.v, i);
|
||||
}
|
||||
|
||||
//template<int dst> template<int N> __forceinline vint<N> insert(const vint<N>& a, const int b) { return _mm_insert_epi32(a, b, dst); }
|
||||
|
||||
template<int N> __forceinline int toScalar(const vint<N>& v) { return extract<0>(v); }
|
||||
template<int N> __forceinline size_t toSizeT(const vint<N>& v) { return toScalar(v); }
|
||||
|
||||
/*
|
||||
template<int N> __forceinline vint<N> permute(const vint<N> &a, const vint<N> &index) {
|
||||
return _mm_castps_si128(_mm_permutevar_ps(_mm_castsi128_ps(a),index));
|
||||
}
|
||||
*/
|
||||
/*
|
||||
template<int i>
|
||||
template<int N> __forceinline vint<N> align_shift_right(const vint<N>& a, const vint<N>& b) {
|
||||
return _mm_alignr_epi32(a, b, i);
|
||||
}
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> __forceinline vint<N> vreduce_min(const vint<N>& v) {
|
||||
return cl::sycl::detail::calc<int, __spv::GroupOperation::Reduce>(v.fix_upper(0x7FFFFFFF).v, cl::sycl::intel::minimum<int>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline vint<N> vreduce_max(const vint<N>& v) {
|
||||
return cl::sycl::detail::calc<int, __spv::GroupOperation::Reduce>(v.fix_upper(0x80000000).v, cl::sycl::intel::maximum<int>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline vint<N> vreduce_add(const vint<N>& v) {
|
||||
return cl::sycl::detail::calc<int, __spv::GroupOperation::Reduce>(v.fix_upper(0).v, cl::sycl::intel::plus<int>());
|
||||
}
|
||||
|
||||
template<int N> __forceinline int reduce_min(const vint<N>& v) { return vreduce_min(v).v; }
|
||||
template<int N> __forceinline int reduce_max(const vint<N>& v) { return vreduce_max(v).v; }
|
||||
template<int N> __forceinline int reduce_add(const vint<N>& v) { return vreduce_add(v).v; }
|
||||
|
||||
//template<int N> __forceinline size_t select_min(const vint<N>& v) { return bsf(movemask(v == vreduce_min(v))); }
|
||||
//template<int N> __forceinline size_t select_max(const vint<N>& v) { return bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
//template<int N> __forceinline size_t select_min(const vboolf<N>& valid, const vint<N>& v) { const vint<N> a = select(valid,v,vint<N>(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
//template<int N> __forceinline size_t select_max(const vboolf<N>& valid, const vint<N>& v) { const vint<N> a = select(valid,v,vint<N>(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sorting networks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
|
||||
template<int N> __forceinline vint<N> usort_ascending(const vint<N>& v)
|
||||
{
|
||||
const vint<N> a0 = v;
|
||||
const vint<N> b0 = shuffle<1,0,3,2>(a0);
|
||||
const vint<N> c0 = umin(a0,b0);
|
||||
const vint<N> d0 = umax(a0,b0);
|
||||
const vint<N> a1 = select<0x5 /* 0b0101 */>(c0,d0);
|
||||
const vint<N> b1 = shuffle<2,3,0,1>(a1);
|
||||
const vint<N> c1 = umin(a1,b1);
|
||||
const vint<N> d1 = umax(a1,b1);
|
||||
const vint<N> a2 = select<0x3 /* 0b0011 */>(c1,d1);
|
||||
const vint<N> b2 = shuffle<0,2,1,3>(a2);
|
||||
const vint<N> c2 = umin(a2,b2);
|
||||
const vint<N> d2 = umax(a2,b2);
|
||||
const vint<N> a3 = select<0x2 /* 0b0010 */>(c2,d2);
|
||||
return a3;
|
||||
}
|
||||
|
||||
template<int N> __forceinline vint<N> usort_descending(const vint<N>& v)
|
||||
{
|
||||
const vint<N> a0 = v;
|
||||
const vint<N> b0 = shuffle<1,0,3,2>(a0);
|
||||
const vint<N> c0 = umax(a0,b0);
|
||||
const vint<N> d0 = umin(a0,b0);
|
||||
const vint<N> a1 = select<0x5 /* 0b0101 */>(c0,d0);
|
||||
const vint<N> b1 = shuffle<2,3,0,1>(a1);
|
||||
const vint<N> c1 = umax(a1,b1);
|
||||
const vint<N> d1 = umin(a1,b1);
|
||||
const vint<N> a2 = select<0x3 /* 0b0011 */>(c1,d1);
|
||||
const vint<N> b2 = shuffle<0,2,1,3>(a2);
|
||||
const vint<N> c2 = umax(a2,b2);
|
||||
const vint<N> d2 = umin(a2,b2);
|
||||
const vint<N> a3 = select<0x2 /* 0b0010 */>(c2,d2);
|
||||
return a3;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int N> inline const cl::sycl::stream& operator <<(const cl::sycl::stream& cout, const vint<N>& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (int i=0; i<N; i++) {
|
||||
if (__spirv_BuiltInSubgroupLocalInvocationId == i) {
|
||||
cout << a.v;
|
||||
if (i != N-1) cout << ", ";
|
||||
}
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
|
||||
template<int N> inline std::ostream& operator <<(std::ostream& cout, const vint<N>& a) {
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
|
||||
+52
-3
@@ -19,12 +19,61 @@
|
||||
#include "sysinfo.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#define CL_TARGET_OPENCL_VERSION 220
|
||||
#define SYCL_SIMPLE_SWIZZLES
|
||||
#include <CL/sycl.hpp>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// All Platforms
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
cl::sycl::queue *global_gpu_queue = nullptr;
|
||||
cl::sycl::device *global_gpu_device = nullptr;
|
||||
#endif
|
||||
|
||||
void* internal_alignedMalloc(size_t size, size_t align)
|
||||
{
|
||||
if (size == 0)
|
||||
return nullptr;
|
||||
|
||||
assert((align & (align-1)) == 0);
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (global_gpu_queue && global_gpu_device)
|
||||
{
|
||||
void* ptr = cl::sycl::aligned_alloc(align,size,*global_gpu_device,global_gpu_queue->get_context(),cl::sycl::usm::alloc::shared);
|
||||
PRINT(ptr);
|
||||
if (size != 0 && ptr == nullptr)
|
||||
throw std::bad_alloc();
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
void* ptr = _mm_malloc(size,align);
|
||||
if (size != 0 && ptr == nullptr)
|
||||
throw std::bad_alloc();
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void internal_alignedFree(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (global_gpu_queue && global_gpu_device)
|
||||
{
|
||||
cl::sycl::free(ptr,global_gpu_queue->get_context());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
_mm_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void* alignedMalloc(size_t size, size_t align)
|
||||
{
|
||||
if (size == 0)
|
||||
@@ -32,10 +81,8 @@ namespace embree
|
||||
|
||||
assert((align & (align-1)) == 0);
|
||||
void* ptr = _mm_malloc(size,align);
|
||||
|
||||
if (size != 0 && ptr == nullptr)
|
||||
throw std::bad_alloc();
|
||||
|
||||
throw std::bad_alloc();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -45,6 +92,8 @@ namespace embree
|
||||
_mm_free(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool huge_pages_enabled = false;
|
||||
static MutexSys os_init_mutex;
|
||||
|
||||
|
||||
+21
-6
@@ -22,20 +22,35 @@
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#define ALIGNED_STRUCT_(align) \
|
||||
void* operator new(size_t size) { return alignedMalloc(size,align); } \
|
||||
void operator delete(void* ptr) { alignedFree(ptr); } \
|
||||
#define ALIGNED_STRUCT_(align) \
|
||||
void* operator new(size_t size) { return alignedMalloc(size,align); } \
|
||||
void operator delete(void* ptr) { alignedFree(ptr); } \
|
||||
void* operator new[](size_t size) { return alignedMalloc(size,align); } \
|
||||
void operator delete[](void* ptr) { alignedFree(ptr); }
|
||||
|
||||
#define ALIGNED_CLASS_(align) \
|
||||
#define ALIGNED_STRUCT_USM_(align) \
|
||||
void* operator new(size_t size) { return internal_alignedMalloc(size,align); } \
|
||||
void operator delete(void* ptr) { internal_alignedFree(ptr); } \
|
||||
void* operator new[](size_t size) { return internal_alignedMalloc(size,align); } \
|
||||
void operator delete[](void* ptr) { internal_alignedFree(ptr); }
|
||||
|
||||
#define ALIGNED_CLASS_(align) \
|
||||
public: \
|
||||
ALIGNED_STRUCT_(align) \
|
||||
ALIGNED_STRUCT_(align) \
|
||||
private:
|
||||
|
||||
#define ALIGNED_CLASS_USM_(align) \
|
||||
public: \
|
||||
ALIGNED_STRUCT_USM_(align) \
|
||||
private:
|
||||
|
||||
/*! aligned allocation */
|
||||
void* alignedMalloc(size_t size, size_t align);
|
||||
void alignedFree(void* ptr);
|
||||
|
||||
/*! embree internal aligned allocation */
|
||||
void* internal_alignedMalloc(size_t size, size_t align);
|
||||
void internal_alignedFree(void* ptr);
|
||||
|
||||
/*! allocator that performs aligned allocations */
|
||||
template<typename T, size_t alignment>
|
||||
@@ -63,7 +78,7 @@ namespace embree
|
||||
|
||||
__forceinline void destroy( pointer p ) {
|
||||
p->~T();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*! allocates pages directly from OS */
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ namespace embree
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
__forceinline void atomic_min(std::atomic<T>& aref, const T& bref)
|
||||
__forceinline void _atomic_min(std::atomic<T>& aref, const T& bref)
|
||||
{
|
||||
const T b = bref.load();
|
||||
while (true) {
|
||||
@@ -60,7 +60,7 @@ namespace embree
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline void atomic_max(std::atomic<T>& aref, const T& bref)
|
||||
__forceinline void _atomic_max(std::atomic<T>& aref, const T& bref)
|
||||
{
|
||||
const T b = bref.load();
|
||||
while (true) {
|
||||
|
||||
@@ -76,6 +76,11 @@ namespace embree
|
||||
return *this;
|
||||
}
|
||||
|
||||
__forceinline allocator& getAlloc()
|
||||
{
|
||||
return alloc;
|
||||
}
|
||||
|
||||
/********************** Iterators ****************************/
|
||||
|
||||
__forceinline iterator begin() { return items; };
|
||||
|
||||
@@ -185,7 +185,9 @@ enum RTCIntersectContextFlags
|
||||
{
|
||||
RTC_INTERSECT_CONTEXT_FLAG_NONE = 0,
|
||||
RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT = (0 << 0), // optimize for incoherent rays
|
||||
RTC_INTERSECT_CONTEXT_FLAG_COHERENT = (1 << 0) // optimize for coherent rays
|
||||
RTC_INTERSECT_CONTEXT_FLAG_COHERENT = (1 << 0), // optimize for coherent rays
|
||||
RTC_INTERSECT_CONTEXT_FLAG_GPU = (1 << 31) // trace ray stream on the GPU
|
||||
|
||||
};
|
||||
|
||||
/* Arguments for RTCFilterFunctionN */
|
||||
|
||||
@@ -26,6 +26,9 @@ typedef struct RTCDeviceTy* RTCDevice;
|
||||
/* Creates a new Embree device. */
|
||||
RTC_API RTCDevice rtcNewDevice(const char* config);
|
||||
|
||||
/* Creates a new Embree GPU device. */
|
||||
RTC_API RTCDevice rtcNewDeviceGPU(const char* config, void *device, void *queue);
|
||||
|
||||
/* Retains the Embree device (increments the reference count). */
|
||||
RTC_API void rtcRetainDevice(RTCDevice device);
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
#include "rtcore_device.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include <CL/sycl.hpp>
|
||||
#endif
|
||||
|
||||
RTC_NAMESPACE_BEGIN
|
||||
|
||||
/* Forward declarations for ray structures */
|
||||
@@ -124,6 +128,11 @@ RTC_API void rtcIntersectNM(RTCScene scene, struct RTCIntersectContext* context,
|
||||
/* Intersects a stream of M ray packets of size N in SOA format with the scene. */
|
||||
RTC_API void rtcIntersectNp(RTCScene scene, struct RTCIntersectContext* context, const struct RTCRayHitNp* rayhit, unsigned int N);
|
||||
|
||||
/* SYCL rtcIntersect interface */
|
||||
#if defined(__cplusplus)
|
||||
[[cl::intel_reqd_sub_group_size(16)]] SYCL_EXTERNAL void rtcIntersectSYCL(cl::sycl::intel::sub_group& sg, cl::sycl::global_ptr<RTCSceneTy> scene, cl::sycl::global_ptr<struct RTCRayHit> rayhit);
|
||||
#endif
|
||||
|
||||
/* Tests a single ray for occlusion with the scene. */
|
||||
RTC_API void rtcOccluded1(RTCScene scene, struct RTCIntersectContext* context, struct RTCRay* ray);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ SET(EMBREE_LIBRARY_FILES
|
||||
subdiv/bspline_curve.cpp
|
||||
subdiv/catmullrom_curve.cpp
|
||||
|
||||
geometry/primitive1.cpp
|
||||
geometry/primitive4.cpp
|
||||
geometry/instance_intersector.cpp
|
||||
geometry/curve_intersector_virtual.cpp
|
||||
@@ -67,6 +68,7 @@ SET(EMBREE_LIBRARY_FILES
|
||||
bvh/bvh_statistics.cpp
|
||||
bvh/bvh4_factory.cpp
|
||||
bvh/bvh8_factory.cpp
|
||||
bvh/bvh_gpu_factory.cpp
|
||||
|
||||
bvh/bvh_rotate.cpp
|
||||
bvh/bvh_refit.cpp
|
||||
@@ -78,8 +80,11 @@ SET(EMBREE_LIBRARY_FILES
|
||||
bvh/bvh_builder_sah_spatial.cpp
|
||||
bvh/bvh_builder_sah_mb.cpp
|
||||
bvh/bvh_builder_twolevel.cpp
|
||||
|
||||
bvh/bvh_builder_gpu.cpp
|
||||
bvh/bvh_builder_gpu_mb.cpp
|
||||
bvh/bvh_intersector1_bvh4.cpp
|
||||
bvh/bvh_intersector_stream_gpu.cpp
|
||||
bvh/bvh_intersector_stream_gpu_mb.cpp
|
||||
)
|
||||
|
||||
IF (EMBREE_GEOMETRY_SUBDIVISION)
|
||||
@@ -95,7 +100,6 @@ ENDIF()
|
||||
|
||||
IF (EMBREE_RAY_PACKETS)
|
||||
SET(EMBREE_LIBRARY_FILES ${EMBREE_LIBRARY_FILES}
|
||||
|
||||
bvh/bvh_intersector_hybrid4_bvh4.cpp
|
||||
bvh/bvh_intersector_stream_bvh4.cpp
|
||||
bvh/bvh_intersector_stream_filters.cpp)
|
||||
|
||||
@@ -451,11 +451,11 @@ namespace embree
|
||||
|
||||
force_split = c.lower > p.lower || c.upper < p.upper;
|
||||
}
|
||||
|
||||
|
||||
/* create leaf for few primitives */
|
||||
if (current.size() <= cfg.maxLeafSize && current.split.data < Split::SPLIT_ENFORCE && !force_split)
|
||||
return createLeaf(current,alloc);
|
||||
|
||||
|
||||
/* fill all children by always splitting the largest one */
|
||||
bool hasTimeSplits = false;
|
||||
NodeRecordMB4D values[MAX_BRANCHING_FACTOR];
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "heuristic_spatial_array.h"
|
||||
#include "heuristic_openmerge_array.h"
|
||||
|
||||
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
|
||||
#if 1 // defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
|
||||
# define NUM_OBJECT_BINS 16
|
||||
# define NUM_SPATIAL_BINS 16
|
||||
#else
|
||||
@@ -234,7 +234,7 @@ namespace embree
|
||||
/*! perform initial split */
|
||||
Set lprims,rprims;
|
||||
heuristic.split(split,current.prims,lprims,rprims);
|
||||
|
||||
|
||||
/*! initialize child list with initial split */
|
||||
ReductionTy values[MAX_BRANCHING_FACTOR];
|
||||
BuildRecord children[MAX_BRANCHING_FACTOR];
|
||||
|
||||
@@ -356,6 +356,7 @@ namespace embree
|
||||
vfloat4 rAreas[BINS];
|
||||
vuint4 rCounts[BINS];
|
||||
vuint4 count = 0; BBox bx = empty; BBox by = empty; BBox bz = empty;
|
||||
|
||||
for (size_t i=mapping.size()-1; i>0; i--)
|
||||
{
|
||||
count += counts(i);
|
||||
@@ -403,6 +404,7 @@ namespace embree
|
||||
bestSAH = vbestSAH[dim];
|
||||
}
|
||||
}
|
||||
|
||||
return Split(bestSAH,bestDim,bestPos,mapping);
|
||||
}
|
||||
|
||||
|
||||
+119
-119
@@ -33,8 +33,8 @@ namespace embree
|
||||
|
||||
//namespace isa
|
||||
//{
|
||||
template<typename BBox>
|
||||
class CentGeom
|
||||
template<typename BBox>
|
||||
class CentGeom
|
||||
{
|
||||
public:
|
||||
__forceinline CentGeom () {}
|
||||
@@ -47,20 +47,20 @@ namespace embree
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void extend_primref(const PrimRef& prim)
|
||||
{
|
||||
BBox bounds; Vec3fa center;
|
||||
prim.binBoundsAndCenter(bounds,center);
|
||||
geomBounds.extend(bounds);
|
||||
centBounds.extend(center);
|
||||
}
|
||||
{
|
||||
BBox bounds; Vec3fa center;
|
||||
prim.binBoundsAndCenter(bounds,center);
|
||||
geomBounds.extend(bounds);
|
||||
centBounds.extend(center);
|
||||
}
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void extend_center2(const PrimRef& prim)
|
||||
{
|
||||
BBox3fa bounds = prim.bounds();
|
||||
geomBounds.extend(bounds);
|
||||
centBounds.extend(bounds.center2());
|
||||
}
|
||||
template<typename PrimRef>
|
||||
__forceinline void extend_center2(const PrimRef& prim)
|
||||
{
|
||||
BBox3fa bounds = prim.bounds();
|
||||
geomBounds.extend(bounds);
|
||||
centBounds.extend(bounds.center2());
|
||||
}
|
||||
|
||||
__forceinline void extend(const BBox& geomBounds_) {
|
||||
geomBounds.extend(geomBounds_);
|
||||
@@ -82,11 +82,11 @@ namespace embree
|
||||
BBox3fa centBounds; //!< centroid bounds of primitives
|
||||
};
|
||||
|
||||
typedef CentGeom<BBox3fa> CentGeomBBox3fa;
|
||||
typedef CentGeom<BBox3fa> CentGeomBBox3fa;
|
||||
|
||||
/*! stores bounding information for a set of primitives */
|
||||
template<typename BBox>
|
||||
class PrimInfoT : public CentGeom<BBox>
|
||||
/*! stores bounding information for a set of primitives */
|
||||
template<typename BBox>
|
||||
class PrimInfoT : public CentGeom<BBox>
|
||||
{
|
||||
public:
|
||||
using CentGeom<BBox>::geomBounds;
|
||||
@@ -102,29 +102,29 @@ namespace embree
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_primref(const PrimRef& prim)
|
||||
{
|
||||
CentGeom<BBox>::extend_primref(prim);
|
||||
end++;
|
||||
{
|
||||
CentGeom<BBox>::extend_primref(prim);
|
||||
end++;
|
||||
}
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_center2(const PrimRef& prim) {
|
||||
CentGeom<BBox>::extend_center2(prim);
|
||||
end++;
|
||||
}
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_center2(const PrimRef& prim) {
|
||||
CentGeom<BBox>::extend_center2(prim);
|
||||
end++;
|
||||
}
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_center2(const PrimRef& prim, const size_t i) {
|
||||
CentGeom<BBox>::extend_center2(prim);
|
||||
end+=i;
|
||||
}
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_center2(const PrimRef& prim, const size_t i) {
|
||||
CentGeom<BBox>::extend_center2(prim);
|
||||
end+=i;
|
||||
}
|
||||
|
||||
/*__forceinline void add(const BBox& geomBounds_) {
|
||||
CentGeom<BBox>::extend(geomBounds_);
|
||||
end++;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void add(const BBox& geomBounds_, const size_t i) {
|
||||
__forceinline void add(const BBox& geomBounds_, const size_t i) {
|
||||
CentGeom<BBox>::extend(geomBounds_);
|
||||
end+=i;
|
||||
}*/
|
||||
@@ -169,12 +169,12 @@ namespace embree
|
||||
size_t begin,end; //!< number of primitives
|
||||
};
|
||||
|
||||
typedef PrimInfoT<BBox3fa> PrimInfo;
|
||||
//typedef PrimInfoT<LBBox3fa> PrimInfoMB;
|
||||
typedef PrimInfoT<BBox3fa> PrimInfo;
|
||||
//typedef PrimInfoT<LBBox3fa> PrimInfoMB;
|
||||
|
||||
/*! stores bounding information for a set of primitives */
|
||||
template<typename BBox>
|
||||
class PrimInfoMBT : public CentGeom<BBox>
|
||||
/*! stores bounding information for a set of primitives */
|
||||
template<typename BBox>
|
||||
class PrimInfoMBT : public CentGeom<BBox>
|
||||
{
|
||||
public:
|
||||
using CentGeom<BBox>::geomBounds;
|
||||
@@ -191,16 +191,16 @@ namespace embree
|
||||
|
||||
template<typename PrimRef>
|
||||
__forceinline void add_primref(const PrimRef& prim)
|
||||
{
|
||||
CentGeom<BBox>::extend_primref(prim);
|
||||
time_range.extend(prim.time_range);
|
||||
object_range._end++;
|
||||
num_time_segments += prim.size();
|
||||
if (max_num_time_segments < prim.totalTimeSegments()) {
|
||||
max_num_time_segments = prim.totalTimeSegments();
|
||||
max_time_range = prim.time_range;
|
||||
}
|
||||
}
|
||||
{
|
||||
CentGeom<BBox>::extend_primref(prim);
|
||||
time_range.extend(prim.time_range);
|
||||
object_range._end++;
|
||||
num_time_segments += prim.size();
|
||||
if (max_num_time_segments < prim.totalTimeSegments()) {
|
||||
max_num_time_segments = prim.totalTimeSegments();
|
||||
max_time_range = prim.time_range;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void merge(const PrimInfoMBT& other)
|
||||
{
|
||||
@@ -272,95 +272,95 @@ namespace embree
|
||||
BBox1f time_range; //!< merged time range of primitives when merging prims, or additionally clipped with build time range when used in SetMB
|
||||
};
|
||||
|
||||
typedef PrimInfoMBT<typename PrimRefMB::BBox> PrimInfoMB;
|
||||
typedef PrimInfoMBT<typename PrimRefMB::BBox> PrimInfoMB;
|
||||
|
||||
struct SetMB : public PrimInfoMB
|
||||
struct SetMB : public PrimInfoMB
|
||||
{
|
||||
static const size_t PARALLEL_THRESHOLD = 3 * 1024;
|
||||
static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
|
||||
static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
|
||||
|
||||
typedef mvector<PrimRefMB>* PrimRefVector;
|
||||
|
||||
__forceinline SetMB() {}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
|
||||
: PrimInfoMB(pinfo_i), prims(prims) {}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in)
|
||||
: PrimInfoMB(pinfo_i), prims(prims)
|
||||
{
|
||||
static const size_t PARALLEL_THRESHOLD = 3 * 1024;
|
||||
static const size_t PARALLEL_FIND_BLOCK_SIZE = 1024;
|
||||
static const size_t PARALLEL_PARTITION_BLOCK_SIZE = 128;
|
||||
|
||||
typedef mvector<PrimRefMB>* PrimRefVector;
|
||||
|
||||
__forceinline SetMB() {}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims)
|
||||
: PrimInfoMB(pinfo_i), prims(prims) {}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, range<size_t> object_range_in, BBox1f time_range_in)
|
||||
: PrimInfoMB(pinfo_i), prims(prims)
|
||||
{
|
||||
object_range = object_range_in;
|
||||
time_range = intersect(time_range,time_range_in);
|
||||
}
|
||||
object_range = object_range_in;
|
||||
time_range = intersect(time_range,time_range_in);
|
||||
}
|
||||
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, BBox1f time_range_in)
|
||||
: PrimInfoMB(pinfo_i), prims(prims)
|
||||
{
|
||||
time_range = intersect(time_range,time_range_in);
|
||||
}
|
||||
__forceinline SetMB(const PrimInfoMB& pinfo_i, PrimRefVector prims, BBox1f time_range_in)
|
||||
: PrimInfoMB(pinfo_i), prims(prims)
|
||||
{
|
||||
time_range = intersect(time_range,time_range_in);
|
||||
}
|
||||
|
||||
void deterministic_order() const
|
||||
{
|
||||
/* required as parallel partition destroys original primitive order */
|
||||
PrimRefMB* prim = prims->data();
|
||||
std::sort(&prim[object_range.begin()],&prim[object_range.end()]);
|
||||
}
|
||||
void deterministic_order() const
|
||||
{
|
||||
/* required as parallel partition destroys original primitive order */
|
||||
PrimRefMB* prim = prims->data();
|
||||
std::sort(&prim[object_range.begin()],&prim[object_range.end()]);
|
||||
}
|
||||
|
||||
template<typename RecalculatePrimRef>
|
||||
template<typename RecalculatePrimRef>
|
||||
__forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef) const
|
||||
{
|
||||
auto reduce = [&](const range<size_t>& r) -> LBBox3fa
|
||||
{
|
||||
LBBox3fa cbounds(empty);
|
||||
for (size_t j = r.begin(); j < r.end(); j++)
|
||||
{
|
||||
PrimRefMB& ref = (*prims)[j];
|
||||
const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range);
|
||||
cbounds.extend(bn);
|
||||
};
|
||||
return cbounds;
|
||||
};
|
||||
{
|
||||
LBBox3fa cbounds(empty);
|
||||
for (size_t j = r.begin(); j < r.end(); j++)
|
||||
{
|
||||
PrimRefMB& ref = (*prims)[j];
|
||||
const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range);
|
||||
cbounds.extend(bn);
|
||||
};
|
||||
return cbounds;
|
||||
};
|
||||
|
||||
return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
|
||||
reduce,
|
||||
[&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
|
||||
}
|
||||
|
||||
template<typename RecalculatePrimRef>
|
||||
__forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
|
||||
template<typename RecalculatePrimRef>
|
||||
__forceinline LBBox3fa linearBounds(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
|
||||
{
|
||||
auto reduce = [&](const range<size_t>& r) -> LBBox3fa
|
||||
{
|
||||
LBBox3fa cbounds(empty);
|
||||
for (size_t j = r.begin(); j < r.end(); j++)
|
||||
{
|
||||
PrimRefMB& ref = (*prims)[j];
|
||||
const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range, space);
|
||||
cbounds.extend(bn);
|
||||
};
|
||||
return cbounds;
|
||||
};
|
||||
{
|
||||
LBBox3fa cbounds(empty);
|
||||
for (size_t j = r.begin(); j < r.end(); j++)
|
||||
{
|
||||
PrimRefMB& ref = (*prims)[j];
|
||||
const LBBox3fa bn = recalculatePrimRef.linearBounds(ref, time_range, space);
|
||||
cbounds.extend(bn);
|
||||
};
|
||||
return cbounds;
|
||||
};
|
||||
|
||||
return parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD, LBBox3fa(empty),
|
||||
reduce,
|
||||
[&](const LBBox3fa& b0, const LBBox3fa& b1) -> LBBox3fa { return embree::merge(b0, b1); });
|
||||
}
|
||||
|
||||
template<typename RecalculatePrimRef>
|
||||
const SetMB primInfo(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
|
||||
template<typename RecalculatePrimRef>
|
||||
const SetMB primInfo(const RecalculatePrimRef& recalculatePrimRef, const LinearSpace3fa& space) const
|
||||
{
|
||||
auto computePrimInfo = [&](const range<size_t>& r) -> PrimInfoMB
|
||||
{
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
PrimRefMB& ref = (*prims)[j];
|
||||
PrimRefMB ref1 = recalculatePrimRef(ref,time_range,space);
|
||||
pinfo.add_primref(ref1);
|
||||
};
|
||||
return pinfo;
|
||||
};
|
||||
{
|
||||
PrimInfoMB pinfo(empty);
|
||||
for (size_t j=r.begin(); j<r.end(); j++)
|
||||
{
|
||||
PrimRefMB& ref = (*prims)[j];
|
||||
PrimRefMB ref1 = recalculatePrimRef(ref,time_range,space);
|
||||
pinfo.add_primref(ref1);
|
||||
};
|
||||
return pinfo;
|
||||
};
|
||||
|
||||
const PrimInfoMB pinfo = parallel_reduce(object_range.begin(), object_range.end(), PARALLEL_FIND_BLOCK_SIZE, PARALLEL_THRESHOLD,
|
||||
PrimInfoMB(empty), computePrimInfo, PrimInfoMB::merge2);
|
||||
@@ -368,8 +368,8 @@ namespace embree
|
||||
return SetMB(pinfo,prims,object_range,time_range);
|
||||
}
|
||||
|
||||
public:
|
||||
PrimRefVector prims;
|
||||
};
|
||||
//}
|
||||
public:
|
||||
PrimRefVector prims;
|
||||
};
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace embree
|
||||
{
|
||||
namespace isa
|
||||
{
|
||||
PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
|
||||
PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
|
||||
{
|
||||
ParallelPrefixSumState<PrimInfo> pstate;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace embree
|
||||
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
|
||||
|
||||
/* if we need to filter out geometry, run again */
|
||||
if (pinfo.size() != prims.size())
|
||||
if (pinfo.size() != numPrimRefs)
|
||||
{
|
||||
progressMonitor(0);
|
||||
pinfo = parallel_prefix_sum( pstate, size_t(0), geometry->size(), size_t(1024), PrimInfo(empty), [&](const range<size_t>& r, const PrimInfo& base) -> PrimInfo {
|
||||
@@ -45,7 +45,7 @@ namespace embree
|
||||
return pinfo;
|
||||
}
|
||||
|
||||
PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
|
||||
PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
|
||||
{
|
||||
ParallelForForPrefixSumState<PrimInfo> pstate;
|
||||
Scene::Iterator2 iter(scene,types,mblur);
|
||||
@@ -58,7 +58,7 @@ namespace embree
|
||||
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
|
||||
|
||||
/* if we need to filter out geometry, run again */
|
||||
if (pinfo.size() != prims.size())
|
||||
if (pinfo.size() != numPrimRefs)
|
||||
{
|
||||
progressMonitor(0);
|
||||
pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
|
||||
@@ -68,7 +68,7 @@ namespace embree
|
||||
return pinfo;
|
||||
}
|
||||
|
||||
PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
|
||||
PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
|
||||
{
|
||||
ParallelForForPrefixSumState<PrimInfo> pstate;
|
||||
Scene::Iterator2 iter(scene,types,true);
|
||||
@@ -81,7 +81,7 @@ namespace embree
|
||||
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
|
||||
|
||||
/* if we need to filter out geometry, run again */
|
||||
if (pinfo.size() != prims.size())
|
||||
if (pinfo.size() != numPrimRefs)
|
||||
{
|
||||
progressMonitor(0);
|
||||
pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
|
||||
@@ -91,7 +91,7 @@ namespace embree
|
||||
return pinfo;
|
||||
}
|
||||
|
||||
PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
|
||||
PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, const size_t numPrimRefs, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1)
|
||||
{
|
||||
ParallelForForPrefixSumState<PrimInfoMB> pstate;
|
||||
Scene::Iterator2 iter(scene,types,true);
|
||||
@@ -104,7 +104,7 @@ namespace embree
|
||||
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
|
||||
|
||||
/* if we need to filter out geometry, run again */
|
||||
if (pinfo.size() != prims.size())
|
||||
if (pinfo.size() != numPrimRefs)
|
||||
{
|
||||
progressMonitor(0);
|
||||
pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](Geometry* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
|
||||
@@ -199,7 +199,7 @@ namespace embree
|
||||
|
||||
#if 0
|
||||
template<>
|
||||
PrimInfo createPrimRefArray<GridMesh,false>(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
|
||||
PrimInfo createPrimRefArray<GridMesh,false>(Scene* scene, const size_t numPrimRefs, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor)
|
||||
{
|
||||
PING;
|
||||
ParallelForForPrefixSumState<PrimInfo> pstate;
|
||||
@@ -223,7 +223,7 @@ namespace embree
|
||||
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
|
||||
|
||||
/* if we need to filter out geometry, run again */
|
||||
if (pinfo.size() != prims.size())
|
||||
if (pinfo.size() != numPrimRefs)
|
||||
{
|
||||
progressMonitor(0);
|
||||
pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, const PrimInfo& base) -> PrimInfo
|
||||
|
||||
@@ -23,16 +23,16 @@
|
||||
#include "bvh_builder_morton.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
{
|
||||
namespace isa
|
||||
{
|
||||
PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
|
||||
PrimInfo createPrimRefArray(Geometry* geometry, unsigned int geomID, size_t numPrimitives, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
|
||||
|
||||
PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
|
||||
PrimInfo createPrimRefArray(Scene* scene, Geometry::GTypeMask types, bool mblur, size_t numPrimitives, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor);
|
||||
|
||||
PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime = 0);
|
||||
PrimInfo createPrimRefArrayMBlur(Scene* scene, Geometry::GTypeMask types, size_t numPrimitives, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime = 0);
|
||||
|
||||
PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f));
|
||||
PrimInfoMB createPrimRefArrayMSMBlur(Scene* scene, Geometry::GTypeMask types, size_t numPrimitives, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f));
|
||||
|
||||
template<typename Mesh>
|
||||
size_t createMortonCodeArray(Mesh* mesh, mvector<BVHBuilderMorton::BuildPrim>& morton, BuildProgressMonitor& progressMonitor);
|
||||
|
||||
@@ -199,5 +199,6 @@ namespace embree
|
||||
#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)
|
||||
template class BVHN<4>;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
+16
-4
@@ -403,6 +403,15 @@ namespace embree
|
||||
return true;
|
||||
}
|
||||
|
||||
__forceinline bool numValid() const
|
||||
{
|
||||
size_t num = 0;
|
||||
for (size_t i=0; i<N; i++)
|
||||
if (child(i) != BVHN::emptyNode)
|
||||
num++;
|
||||
return num;
|
||||
}
|
||||
|
||||
NodeRef children[N]; //!< Pointer to the N children (can be a node or leaf)
|
||||
};
|
||||
|
||||
@@ -855,9 +864,9 @@ namespace embree
|
||||
|
||||
/*! Clears the node. */
|
||||
__forceinline void clear() {
|
||||
AlignedNodeMB::clear();
|
||||
lower_t = vfloat<N>(pos_inf);
|
||||
upper_t = vfloat<N>(neg_inf);
|
||||
AlignedNodeMB::clear();
|
||||
}
|
||||
|
||||
/*! Sets bounding box of child. */
|
||||
@@ -925,9 +934,11 @@ namespace embree
|
||||
{
|
||||
const BBox3fa b0 = n.bounds0(i);
|
||||
const BBox3fa b1 = n.bounds1(i);
|
||||
cout << " child" << i << " { " << std::endl;
|
||||
cout << " bounds0 = " << lerp(b0,b1,n.lower_t[i]) << ", " << std::endl;
|
||||
cout << " bounds1 = " << lerp(b0,b1,n.upper_t[i]) << ", " << std::endl;
|
||||
cout << " child" << i << " " << n.child(i) << " { " << std::endl;
|
||||
/* cout << " bounds0 = " << lerp(b0,b1,n.lower_t[i]) << ", " << std::endl; */
|
||||
/* cout << " bounds1 = " << lerp(b0,b1,n.upper_t[i]) << ", " << std::endl; */
|
||||
cout << " bounds0 = " << b0 << ", " << std::endl;
|
||||
cout << " bounds1 = " << b1 << ", " << std::endl;
|
||||
cout << " time_bounds = " << n.lower_t[i] << ", " << n.upper_t[i] << std::endl;
|
||||
cout << " }";
|
||||
}
|
||||
@@ -1548,4 +1559,5 @@ namespace embree
|
||||
|
||||
typedef BVHN<4> BVH4;
|
||||
typedef BVHN<8> BVH8;
|
||||
typedef BVHN<16> BVH16;
|
||||
}
|
||||
|
||||
@@ -272,6 +272,8 @@ namespace embree
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVH4Quad4vMeshBuilderMortonGeneral,void* COMMA QuadMesh* COMMA unsigned int COMMA size_t);
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVH4VirtualMeshBuilderMortonGeneral,void* COMMA UserGeometry* COMMA unsigned int COMMA size_t);
|
||||
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVHNTriangle1vSceneBuilderSAH_GPU,void* COMMA Scene* COMMA size_t);
|
||||
|
||||
BVH4Factory::BVH4Factory(int bfeatures, int ifeatures)
|
||||
{
|
||||
selectBuilders(bfeatures);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,871 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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. //
|
||||
// ======================================================================== //
|
||||
|
||||
#include "bvh.h"
|
||||
#include "bvh_builder.h"
|
||||
#include "../builders/bvh_builder_msmblur.h"
|
||||
|
||||
#include "../builders/primrefgen.h"
|
||||
#include "../builders/splitter.h"
|
||||
|
||||
#include "../geometry/linei.h"
|
||||
#include "../geometry/triangle.h"
|
||||
#include "../geometry/trianglev.h"
|
||||
#include "../geometry/trianglev_mb.h"
|
||||
#include "../geometry/trianglei.h"
|
||||
#include "../geometry/triangle1v.h"
|
||||
#include "../geometry/triangle1vmb.h"
|
||||
#include "../geometry/quadv.h"
|
||||
#include "../geometry/quadi.h"
|
||||
#include "../geometry/object.h"
|
||||
#include "../geometry/instance.h"
|
||||
#include "../geometry/subgrid.h"
|
||||
|
||||
#include "../common/state.h"
|
||||
|
||||
#include "../gpu/AABB.h"
|
||||
#include "../gpu/AABB3f.h"
|
||||
#include "../gpu/builder.h"
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
namespace embree
|
||||
{
|
||||
|
||||
namespace isa
|
||||
{
|
||||
|
||||
template<int N, typename Mesh, typename Primitive>
|
||||
struct CreateMSMBlurLeaf
|
||||
{
|
||||
typedef BVHN<N> BVH;
|
||||
typedef typename BVH::NodeRef NodeRef;
|
||||
typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
|
||||
|
||||
__forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {}
|
||||
|
||||
__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
|
||||
{
|
||||
size_t items = Primitive::blocks(current.prims.size());
|
||||
size_t start = current.prims.begin();
|
||||
size_t end = current.prims.end();
|
||||
for (size_t i=start; i<end; i++) assert((*current.prims.prims)[start].geomID() == (*current.prims.prims)[i].geomID()); // assert that all geomIDs are identical
|
||||
Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);
|
||||
NodeRef node = bvh->encodeLeaf((char*)accel,items);
|
||||
LBBox3fa allBounds = empty;
|
||||
for (size_t i=0; i<items; i++)
|
||||
allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));
|
||||
return NodeRecordMB4D(node,allBounds,current.prims.time_range);
|
||||
}
|
||||
|
||||
BVH* bvh;
|
||||
};
|
||||
|
||||
|
||||
/* Motion blur BVH with 4D nodes and internal time splits */
|
||||
template<int N, typename Mesh, typename Primitive>
|
||||
struct BVHGPUBuilderMBlurSAH : public Builder
|
||||
{
|
||||
typedef BVHN<N> BVH;
|
||||
typedef typename BVHN<N>::NodeRef NodeRef;
|
||||
typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
|
||||
typedef typename BVHN<N>::AlignedNodeMB AlignedNodeMB;
|
||||
typedef typename BVHN<N>::AlignedNodeMB4D AlignedNodeMB4D;
|
||||
typedef typename BVHN<N>::AlignedNode AlignedNode;
|
||||
typedef typename BVHN<N>::UnalignedNode UnalignedNode;
|
||||
typedef typename BVHN<N>::UnalignedNodeMB UnalignedNodeMB;
|
||||
typedef typename BVHN<N>::QuantizedNode QuantizedNode;
|
||||
|
||||
BVH* bvh;
|
||||
Scene* scene;
|
||||
const size_t sahBlockSize;
|
||||
const float intCost;
|
||||
const size_t minLeafSize;
|
||||
const size_t maxLeafSize;
|
||||
const Geometry::GTypeMask gtype_;
|
||||
|
||||
BVHGPUBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
|
||||
: bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {}
|
||||
|
||||
inline size_t convertToBVHNodeNMB(gpu::BVHNodeNMB *gpu_node, const AlignedNodeMB4D *const n, NodeRef *refs, const size_t offset = 0, const size_t offset_input = 0, const size_t numElements = N)
|
||||
{
|
||||
size_t num = 0;
|
||||
for (size_t i=0;i<numElements;i++)
|
||||
{
|
||||
if (n->child(i) == BVH::emptyNode) continue;
|
||||
gpu_node->offset[offset+num] = 0;
|
||||
gpu_node->lower_t[offset+num] = n->lower_t[i+offset_input];
|
||||
gpu_node->upper_t[offset+num] = n->upper_t[i+offset_input];
|
||||
gpu_node->lower_x[offset+num] = n->lower_x[i+offset_input];
|
||||
gpu_node->upper_x[offset+num] = n->upper_x[i+offset_input];
|
||||
gpu_node->lower_y[offset+num] = n->lower_y[i+offset_input];
|
||||
gpu_node->upper_y[offset+num] = n->upper_y[i+offset_input];
|
||||
gpu_node->lower_z[offset+num] = n->lower_z[i+offset_input];
|
||||
gpu_node->upper_z[offset+num] = n->upper_z[i+offset_input];
|
||||
gpu_node->lower_dx[offset+num] = n->lower_dx[i+offset_input];
|
||||
gpu_node->upper_dx[offset+num] = n->upper_dx[i+offset_input];
|
||||
gpu_node->lower_dy[offset+num] = n->lower_dy[i+offset_input];
|
||||
gpu_node->upper_dy[offset+num] = n->upper_dy[i+offset_input];
|
||||
gpu_node->lower_dz[offset+num] = n->lower_dz[i+offset_input];
|
||||
gpu_node->upper_dz[offset+num] = n->upper_dz[i+offset_input];
|
||||
|
||||
assert(!std::isnan( gpu_node->lower_t[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_t[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_x[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_y[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_z[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_x[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_y[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_z[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_dx[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_dy[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_dz[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_dx[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_dy[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_dz[offset+num] ));
|
||||
refs[offset+num] = n->child(i+offset_input);
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
inline size_t convertToBVHNodeNMB(gpu::BVHNodeNMB *gpu_node, const AlignedNodeMB *const n, NodeRef *refs, const size_t offset = 0, const size_t offset_input = 0, const size_t numElements = N)
|
||||
{
|
||||
size_t num = 0;
|
||||
for (size_t i=0;i<numElements;i++)
|
||||
{
|
||||
if (n->child(i) == BVH::emptyNode) continue;
|
||||
|
||||
gpu_node->offset[offset+num] = 0;
|
||||
gpu_node->lower_t[offset+num] = neg_inf;
|
||||
gpu_node->upper_t[offset+num] = pos_inf;
|
||||
gpu_node->lower_x[offset+num] = n->lower_x[i+offset_input];
|
||||
gpu_node->upper_x[offset+num] = n->upper_x[i+offset_input];
|
||||
gpu_node->lower_y[offset+num] = n->lower_y[i+offset_input];
|
||||
gpu_node->upper_y[offset+num] = n->upper_y[i+offset_input];
|
||||
gpu_node->lower_z[offset+num] = n->lower_z[i+offset_input];
|
||||
gpu_node->upper_z[offset+num] = n->upper_z[i+offset_input];
|
||||
gpu_node->lower_dx[offset+num] = n->lower_dx[i+offset_input];
|
||||
gpu_node->upper_dx[offset+num] = n->upper_dx[i+offset_input];
|
||||
gpu_node->lower_dy[offset+num] = n->lower_dy[i+offset_input];
|
||||
gpu_node->upper_dy[offset+num] = n->upper_dy[i+offset_input];
|
||||
gpu_node->lower_dz[offset+num] = n->lower_dz[i+offset_input];
|
||||
gpu_node->upper_dz[offset+num] = n->upper_dz[i+offset_input];
|
||||
|
||||
assert(!std::isnan( gpu_node->lower_t[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_t[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_x[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_y[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_z[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_x[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_y[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_z[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_dx[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_dy[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->lower_dz[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_dx[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_dy[offset+num] ));
|
||||
assert(!std::isnan( gpu_node->upper_dz[offset+num] ));
|
||||
refs[offset+num] = n->child(i+offset_input);
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
inline void convertToTriangle1vMB(gpu::Triangle1vMB &tri1v, const Triangle4vMB &tri_block, const size_t slot)
|
||||
{
|
||||
tri1v.v0.x() = tri_block.v0.x[slot];
|
||||
tri1v.v0.y() = tri_block.v0.y[slot];
|
||||
tri1v.v0.z() = tri_block.v0.z[slot];
|
||||
tri1v.v0.w() = gpu::as_float(tri_block.primID()[slot]);
|
||||
|
||||
tri1v.v1.x() = tri_block.v1.x[slot];
|
||||
tri1v.v1.y() = tri_block.v1.y[slot];
|
||||
tri1v.v1.z() = tri_block.v1.z[slot];
|
||||
tri1v.v1.w() = gpu::as_float(tri_block.geomID()[slot]);
|
||||
|
||||
tri1v.v2.x() = tri_block.v2.x[slot];
|
||||
tri1v.v2.y() = tri_block.v2.y[slot];
|
||||
tri1v.v2.z() = tri_block.v2.z[slot];
|
||||
tri1v.v2.w() = 0.0f;
|
||||
|
||||
tri1v.d0.x() = tri_block.dv0.x[slot];
|
||||
tri1v.d0.y() = tri_block.dv0.y[slot];
|
||||
tri1v.d0.z() = tri_block.dv0.z[slot];
|
||||
|
||||
tri1v.d1.x() = tri_block.dv1.x[slot];
|
||||
tri1v.d1.y() = tri_block.dv1.y[slot];
|
||||
tri1v.d1.z() = tri_block.dv1.z[slot];
|
||||
|
||||
tri1v.d2.x() = tri_block.dv2.x[slot];
|
||||
tri1v.d2.y() = tri_block.dv2.y[slot];
|
||||
tri1v.d2.z() = tri_block.dv2.z[slot];
|
||||
}
|
||||
|
||||
inline size_t convertToBVHNodeNMB16(gpu::BVHNodeNMB *gpu_node, AlignedNodeMB *n, NodeRef *refs, const size_t index_output, const size_t index_input, const float time0, const float time1)
|
||||
{
|
||||
if (n->child(index_input) == BVH::emptyNode) return 0;
|
||||
refs[index_output] = n->child(index_input);
|
||||
|
||||
gpu_node->offset[index_output] = 0;
|
||||
gpu_node->lower_t[index_output] = time0;
|
||||
gpu_node->upper_t[index_output] = time1;
|
||||
|
||||
gpu_node->lower_x[index_output] = n->lower_x[index_input];
|
||||
gpu_node->upper_x[index_output] = n->upper_x[index_input];
|
||||
gpu_node->lower_y[index_output] = n->lower_y[index_input];
|
||||
gpu_node->upper_y[index_output] = n->upper_y[index_input];
|
||||
gpu_node->lower_z[index_output] = n->lower_z[index_input];
|
||||
gpu_node->upper_z[index_output] = n->upper_z[index_input];
|
||||
gpu_node->lower_dx[index_output] = n->lower_dx[index_input];
|
||||
gpu_node->upper_dx[index_output] = n->upper_dx[index_input];
|
||||
gpu_node->lower_dy[index_output] = n->lower_dy[index_input];
|
||||
gpu_node->upper_dy[index_output] = n->upper_dy[index_input];
|
||||
gpu_node->lower_dz[index_output] = n->lower_dz[index_input];
|
||||
gpu_node->upper_dz[index_output] = n->upper_dz[index_input];
|
||||
|
||||
assert(!std::isnan( gpu_node->lower_x[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_y[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_z[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_x[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_y[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_z[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_dx[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_dy[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_dz[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_dx[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_dy[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_dz[index_output] ));
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline size_t convertToBVHNodeNMB16(gpu::BVHNodeNMB *gpu_node, AlignedNodeMB4D *n, NodeRef *refs, const size_t index_output, const size_t index_input)
|
||||
{
|
||||
if (n->child(index_input) == BVH::emptyNode) return 0;
|
||||
refs[index_output] = n->child(index_input);
|
||||
|
||||
gpu_node->offset[index_output] = 0;
|
||||
gpu_node->lower_t[index_output] = n->lower_t[index_input];
|
||||
gpu_node->upper_t[index_output] = n->upper_t[index_input];
|
||||
gpu_node->lower_x[index_output] = n->lower_x[index_input];
|
||||
gpu_node->upper_x[index_output] = n->upper_x[index_input];
|
||||
gpu_node->lower_y[index_output] = n->lower_y[index_input];
|
||||
gpu_node->upper_y[index_output] = n->upper_y[index_input];
|
||||
gpu_node->lower_z[index_output] = n->lower_z[index_input];
|
||||
gpu_node->upper_z[index_output] = n->upper_z[index_input];
|
||||
gpu_node->lower_dx[index_output] = n->lower_dx[index_input];
|
||||
gpu_node->upper_dx[index_output] = n->upper_dx[index_input];
|
||||
gpu_node->lower_dy[index_output] = n->lower_dy[index_input];
|
||||
gpu_node->upper_dy[index_output] = n->upper_dy[index_input];
|
||||
gpu_node->lower_dz[index_output] = n->lower_dz[index_input];
|
||||
gpu_node->upper_dz[index_output] = n->upper_dz[index_input];
|
||||
|
||||
assert(!std::isnan( gpu_node->lower_t[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_t[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_x[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_y[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_z[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_x[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_y[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_z[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_dx[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_dy[index_output] ));
|
||||
assert(!std::isnan( gpu_node->lower_dz[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_dx[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_dy[index_output] ));
|
||||
assert(!std::isnan( gpu_node->upper_dz[index_output] ));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
size_t countLeafPrimitives(NodeRef node)
|
||||
{
|
||||
size_t prims = 0;
|
||||
if (node.isAlignedNodeMB())
|
||||
{
|
||||
AlignedNodeMB* n = node.alignedNodeMB();
|
||||
for (size_t i=0;i<N;i++)
|
||||
if (n->child(i) != BVH::emptyNode)
|
||||
prims += countLeafPrimitives(n->child(i));
|
||||
}
|
||||
else if (node.isAlignedNodeMB4D())
|
||||
{
|
||||
AlignedNodeMB4D* n = node.alignedNodeMB4D();
|
||||
for (size_t i=0;i<N;i++)
|
||||
if (n->child(i) != BVH::emptyNode)
|
||||
prims += countLeafPrimitives(n->child(i));
|
||||
}
|
||||
else if (node.isLeaf())
|
||||
{
|
||||
size_t num; const char* tri = node.leaf(num);
|
||||
if (num)
|
||||
{
|
||||
Triangle4vMB *tri_mb = (Triangle4vMB*)tri;
|
||||
|
||||
size_t numTris=0;
|
||||
for (size_t i=0; i<num; i++)
|
||||
numTris += tri_mb[i].size();
|
||||
|
||||
assert(numTris <= BVH_MAX_NUM_ITEMS);
|
||||
prims += numTris;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("not supported node type in bvh_statistics");
|
||||
}
|
||||
return prims;
|
||||
}
|
||||
|
||||
void convertToGPULayout(NodeRef node,
|
||||
char* bvh_mem,
|
||||
gpu::Triangle1vMB *leaf_ptr,
|
||||
size_t parent_node_offset,
|
||||
size_t slot,
|
||||
std::atomic<size_t> &gpu_node_allocator,
|
||||
std::atomic<size_t> &gpu_leaf_allocator)
|
||||
{
|
||||
if (node.isAlignedNode())
|
||||
{
|
||||
DBG(PRINT("ALIGNED NODE"));
|
||||
AlignedNode* n = node.alignedNode();
|
||||
for (size_t i=0;i<N;i++)
|
||||
if (n->child(i) != BVH::emptyNode)
|
||||
convertToGPULayout(n->child(i),bvh_mem,leaf_ptr,0,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
}
|
||||
else if (node.isUnalignedNode())
|
||||
{
|
||||
DBG(PRINT("UNALIGNED NODE"));
|
||||
UnalignedNode* n = node.unalignedNode();
|
||||
for (size_t i=0;i<N;i++)
|
||||
if (n->child(i) != BVH::emptyNode)
|
||||
convertToGPULayout(n->child(i),bvh_mem,leaf_ptr,0,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
}
|
||||
else if (node.isAlignedNodeMB())
|
||||
{
|
||||
DBG(PRINT("ALIGNED NODE MB"));
|
||||
NodeRef refs[BVH_NODE_N];
|
||||
|
||||
AlignedNodeMB* n = node.alignedNodeMB();
|
||||
const size_t offset = gpu_node_allocator.fetch_add(sizeof(gpu::QBVHNodeNMB));
|
||||
DBG(
|
||||
PRINT(offset);
|
||||
PRINT(parent_node_offset);
|
||||
PRINT(slot);
|
||||
);
|
||||
|
||||
/* set parent offset */
|
||||
if (parent_node_offset)
|
||||
{
|
||||
gpu::QBVHNodeNMB *parent_gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + parent_node_offset);
|
||||
assert(((offset - parent_node_offset) & BVH_LEAF_MASK) == 0);
|
||||
parent_gpu_node->offset[slot] = offset - parent_node_offset;
|
||||
}
|
||||
|
||||
/* create new gpu node and convert layout */
|
||||
gpu::QBVHNodeNMB *gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + offset);
|
||||
gpu_node->clear();
|
||||
const size_t slots = convertToBVHNodeNMB(gpu_node,n,refs,0);
|
||||
for (size_t i=0;i<slots;i++)
|
||||
{
|
||||
assert(refs[i] != BVH::emptyNode && refs[i] != BVH::invalidNode);
|
||||
convertToGPULayout(refs[i],bvh_mem,leaf_ptr,offset,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
}
|
||||
}
|
||||
else if (node.isAlignedNodeMB4D())
|
||||
{
|
||||
DBG(PRINT("ALIGNED NODE MB 4D"));
|
||||
NodeRef refs[BVH_NODE_N];
|
||||
AlignedNodeMB4D* n = node.alignedNodeMB4D();
|
||||
const size_t offset = gpu_node_allocator.fetch_add(sizeof(gpu::QBVHNodeNMB));
|
||||
DBG(
|
||||
PRINT(offset);
|
||||
PRINT(parent_node_offset);
|
||||
PRINT(slot);
|
||||
);
|
||||
|
||||
/* set parent offset */
|
||||
if (parent_node_offset)
|
||||
{
|
||||
gpu::QBVHNodeNMB *parent_gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + parent_node_offset);
|
||||
parent_gpu_node->offset[slot] = offset - parent_node_offset;
|
||||
DBG (PRINT( parent_gpu_node->offset[slot] ); );
|
||||
assert(((offset - parent_node_offset) & BVH_LEAF_MASK) == 0);
|
||||
}
|
||||
|
||||
/* create new gpu node and convert layout */
|
||||
gpu::QBVHNodeNMB *gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + offset);
|
||||
gpu_node->clear();
|
||||
const size_t slots = convertToBVHNodeNMB(gpu_node,n,refs,0);
|
||||
|
||||
for (size_t i=0;i<slots;i++)
|
||||
{
|
||||
assert(refs[i] != BVH::emptyNode && refs[i] != BVH::invalidNode);
|
||||
convertToGPULayout(refs[i],bvh_mem,leaf_ptr,offset,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
}
|
||||
}
|
||||
else if (node.isUnalignedNodeMB())
|
||||
{
|
||||
DBG(PRINT("UNALIGNED NODE MB"));
|
||||
UnalignedNodeMB* n = node.unalignedNodeMB();
|
||||
for (size_t i=0;i<N;i++)
|
||||
if (n->child(i) != BVH::emptyNode)
|
||||
convertToGPULayout(n->child(i),bvh_mem,leaf_ptr,0,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
}
|
||||
else if (node.isQuantizedNode())
|
||||
{
|
||||
DBG(PRINT("QUANTIZED NODE"));
|
||||
QuantizedNode* n = node.quantizedNode();
|
||||
for (size_t i=0;i<N;i++)
|
||||
if (n->child(i) != BVH::emptyNode)
|
||||
convertToGPULayout(n->child(i),bvh_mem,leaf_ptr,0,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
}
|
||||
else if (node.isLeaf())
|
||||
{
|
||||
size_t num; const char* tri = node.leaf(num);
|
||||
DBG(
|
||||
PRINT("LEAF");
|
||||
PRINT(num);
|
||||
);
|
||||
|
||||
if (num)
|
||||
{
|
||||
Triangle4vMB *tri_mb = (Triangle4vMB*)tri;
|
||||
|
||||
size_t numTris=0;
|
||||
for (size_t i=0; i<num; i++)
|
||||
numTris += tri_mb[i].size();
|
||||
|
||||
DBG( PRINT(numTris) );
|
||||
assert(numTris <= BVH_MAX_NUM_ITEMS);
|
||||
|
||||
const size_t leaf_index = gpu_leaf_allocator.fetch_add(numTris);
|
||||
|
||||
size_t index=0;
|
||||
for (size_t i=0; i<num; i++)
|
||||
{
|
||||
for (size_t j=0;j<tri_mb[i].size();j++)
|
||||
convertToTriangle1vMB(leaf_ptr[leaf_index+index++],tri_mb[i],j);
|
||||
}
|
||||
assert(numTris == index);
|
||||
|
||||
/* set parent offset */
|
||||
if (parent_node_offset)
|
||||
{
|
||||
DBG( PRINT("LEAF PARENT") );
|
||||
gpu::QBVHNodeNMB *parent_gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + parent_node_offset);
|
||||
assert( ((size_t)parent_gpu_node % 64) == 0 );
|
||||
assert( ((size_t)leaf_ptr % 16) == 0 );
|
||||
|
||||
const unsigned int offset = (size_t)((char*)&leaf_ptr[leaf_index] - (char*)parent_gpu_node);
|
||||
assert(((offset - parent_node_offset) & BVH_LOWER_BITS_MASK) == 0);
|
||||
|
||||
parent_gpu_node->offset[slot] = offset | BVH_LEAF_MASK | (index-1);
|
||||
DBG(
|
||||
PRINT( (size_t)((char*)&leaf_ptr[leaf_index] - (char*)bvh_mem) );
|
||||
PRINT( offset );
|
||||
PRINT( numTris );
|
||||
gpu::NodeRef ref( parent_gpu_node->offset[slot] );
|
||||
PRINT( ref.getLeafOffset() );
|
||||
PRINT( ref.getNumLeafPrims() );
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("not supported node type in bvh mb conversion");
|
||||
}
|
||||
|
||||
|
||||
void convertToGPULayout16(NodeRef node,
|
||||
char* bvh_mem,
|
||||
gpu::Triangle1vMB *leaf_ptr,
|
||||
size_t parent_node_offset,
|
||||
size_t slot,
|
||||
std::atomic<size_t> &gpu_node_allocator,
|
||||
std::atomic<size_t> &gpu_leaf_allocator)
|
||||
{
|
||||
if (node.isLeaf())
|
||||
{
|
||||
size_t num; const char* tri = node.leaf(num);
|
||||
DBG(
|
||||
PRINT("LEAF");
|
||||
PRINT(num);
|
||||
);
|
||||
|
||||
if (num)
|
||||
{
|
||||
Triangle4vMB *tri_mb = (Triangle4vMB*)tri;
|
||||
|
||||
size_t numTris=0;
|
||||
for (size_t i=0; i<num; i++)
|
||||
numTris += tri_mb[i].size();
|
||||
|
||||
DBG( PRINT(numTris) );
|
||||
assert(numTris <= BVH_MAX_NUM_ITEMS);
|
||||
|
||||
const size_t leaf_index = gpu_leaf_allocator.fetch_add(numTris);
|
||||
|
||||
size_t index=0;
|
||||
for (size_t i=0; i<num; i++)
|
||||
for (size_t j=0;j<tri_mb[i].size();j++)
|
||||
convertToTriangle1vMB(leaf_ptr[leaf_index+index++],tri_mb[i],j);
|
||||
assert(numTris == index);
|
||||
|
||||
/* set parent offset */
|
||||
if (parent_node_offset)
|
||||
{
|
||||
DBG( PRINT("LEAF PARENT") );
|
||||
gpu::QBVHNodeNMB *parent_gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + parent_node_offset);
|
||||
const unsigned int offset = (size_t)((char*)&leaf_ptr[leaf_index] - (char*)parent_gpu_node);
|
||||
parent_gpu_node->offset[slot] = offset | BVH_LEAF_MASK | (index-1);
|
||||
assert( ((size_t)parent_gpu_node % 64) == 0 );
|
||||
assert( ((size_t)leaf_ptr % 16) == 0 );
|
||||
assert(((offset - parent_node_offset) & BVH_LOWER_BITS_MASK) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeRef refs[BVH_NODE_N];
|
||||
|
||||
const size_t gpu_node_offset = gpu_node_allocator.fetch_add(sizeof(gpu::QBVHNodeNMB));
|
||||
gpu::QBVHNodeNMB *gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + gpu_node_offset);
|
||||
gpu_node->clear();
|
||||
|
||||
gpu::BVHNodeNMB bvh_node;
|
||||
bvh_node.clear();
|
||||
|
||||
|
||||
size_t slots = 0;
|
||||
for (size_t i=0;i<N;i++)
|
||||
{
|
||||
DBG(
|
||||
PRINT(i);
|
||||
PRINT(slots);
|
||||
);
|
||||
NodeRef child = node.baseNode()->child(i);
|
||||
float time0 = neg_inf;
|
||||
float time1 = pos_inf;
|
||||
if (node.isAlignedNodeMB4D())
|
||||
{
|
||||
DBG(PRINT("MAIN node MB4D"));
|
||||
AlignedNodeMB4D* n = node.alignedNodeMB4D();
|
||||
time0 = n->lower_t[i];
|
||||
time1 = n->upper_t[i];
|
||||
DBG(PRINT(*n));
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(
|
||||
PRINT("MAIN node MB");
|
||||
AlignedNodeMB* n = node.alignedNodeMB();
|
||||
PRINT(*n));
|
||||
}
|
||||
|
||||
if (child != BVH::invalidNode && child != BVH::emptyNode)
|
||||
{
|
||||
if (child.isAlignedNodeMB())
|
||||
{
|
||||
AlignedNodeMB* n = child.alignedNodeMB();
|
||||
DBG(
|
||||
PRINT("AlignedNodeMB");
|
||||
PRINT(*n);
|
||||
);
|
||||
for (size_t j=0;j<N;j++)
|
||||
slots += convertToBVHNodeNMB16(&bvh_node,n,refs,slots,j,time0,time1);
|
||||
}
|
||||
else if (child.isAlignedNodeMB4D())
|
||||
{
|
||||
AlignedNodeMB4D* n = child.alignedNodeMB4D();
|
||||
DBG(
|
||||
PRINT("AlignedNodeMB4D");
|
||||
PRINT(*n);
|
||||
);
|
||||
for (size_t j=0;j<N;j++)
|
||||
slots += convertToBVHNodeNMB16(&bvh_node,n,refs,slots,j);
|
||||
}
|
||||
else if (child.isLeaf())
|
||||
{
|
||||
DBG(
|
||||
PRINT("direct leaf");
|
||||
PRINT(slots);
|
||||
PRINT(i);
|
||||
);
|
||||
/* direct child is a leaf */
|
||||
if (node.isAlignedNodeMB())
|
||||
{
|
||||
DBG(PRINT("1"));
|
||||
AlignedNodeMB* n = node.alignedNodeMB();
|
||||
DBG(PRINT(*n));
|
||||
slots += convertToBVHNodeNMB16(&bvh_node,n,refs,slots,i,time0,time1);
|
||||
}
|
||||
else if (node.isAlignedNodeMB4D())
|
||||
{
|
||||
DBG(PRINT("2"));
|
||||
AlignedNodeMB4D* n = node.alignedNodeMB4D();
|
||||
DBG(PRINT(*n));
|
||||
slots += convertToBVHNodeNMB16(&bvh_node,n,refs,slots,i);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("not supported node type in bvh mb conversion");
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("not supported node type in bvh mb conversion");
|
||||
}
|
||||
}
|
||||
DBG(PRINT(slots));
|
||||
assert(slots <= BVH_NODE_N);
|
||||
|
||||
/* set parent offset */
|
||||
if (parent_node_offset)
|
||||
{
|
||||
gpu::QBVHNodeNMB *parent_gpu_node = (gpu::QBVHNodeNMB*)(bvh_mem + parent_node_offset);
|
||||
parent_gpu_node->offset[slot] = gpu_node_offset - parent_node_offset;
|
||||
assert(((gpu_node_offset - parent_node_offset) & BVH_LEAF_MASK) == 0);
|
||||
}
|
||||
|
||||
/* recursive continue with children of child(i) */
|
||||
for (size_t i=0;i<slots;i++)
|
||||
{
|
||||
assert(refs[i] != BVH::invalidNode);
|
||||
assert(refs[i] != BVH::emptyNode);
|
||||
|
||||
DBG(
|
||||
PRINT(i);
|
||||
PRINT(bvh_node.offset[i]);
|
||||
PRINT(refs[i]);
|
||||
PRINT(refs[i].isLeaf());
|
||||
PRINT(bvh_node.lower_t[i]);
|
||||
PRINT(bvh_node.upper_t[i]);
|
||||
PRINT(bvh_node.lower_x[i]);
|
||||
PRINT(bvh_node.lower_y[i]);
|
||||
PRINT(bvh_node.lower_z[i]);
|
||||
PRINT(bvh_node.upper_x[i]);
|
||||
PRINT(bvh_node.upper_y[i]);
|
||||
PRINT(bvh_node.upper_z[i]);
|
||||
|
||||
PRINT(bvh_node.lower_x[i]+bvh_node.lower_dx[i]);
|
||||
PRINT(bvh_node.lower_y[i]+bvh_node.lower_dy[i]);
|
||||
PRINT(bvh_node.lower_z[i]+bvh_node.lower_dz[i]);
|
||||
|
||||
PRINT(bvh_node.upper_x[i]+bvh_node.upper_dx[i]);
|
||||
PRINT(bvh_node.upper_y[i]+bvh_node.upper_dy[i]);
|
||||
PRINT(bvh_node.upper_z[i]+bvh_node.upper_dz[i]);
|
||||
);
|
||||
assert(!std::isnan( bvh_node.lower_t[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_t[i] ));
|
||||
assert(!std::isnan( bvh_node.lower_x[i] ));
|
||||
assert(!std::isnan( bvh_node.lower_y[i] ));
|
||||
assert(!std::isnan( bvh_node.lower_z[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_x[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_y[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_z[i] ));
|
||||
assert(!std::isnan( bvh_node.lower_dx[i] ));
|
||||
assert(!std::isnan( bvh_node.lower_dy[i] ));
|
||||
assert(!std::isnan( bvh_node.lower_dz[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_dx[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_dy[i] ));
|
||||
assert(!std::isnan( bvh_node.upper_dz[i] ));
|
||||
|
||||
}
|
||||
|
||||
/* convert to compressed layout */
|
||||
*gpu_node = bvh_node.convert();
|
||||
|
||||
for (size_t i=0;i<slots;i++)
|
||||
if (refs[i] != BVH::invalidNode && refs[i] != BVH::emptyNode)
|
||||
convertToGPULayout16(refs[i],bvh_mem,leaf_ptr,gpu_node_offset,i,gpu_node_allocator,gpu_leaf_allocator);
|
||||
|
||||
DBG(
|
||||
PING;
|
||||
|
||||
PRINT(gpu_node->org0.x());
|
||||
PRINT(gpu_node->org0.y());
|
||||
PRINT(gpu_node->org0.z());
|
||||
|
||||
PRINT(gpu_node->scale0.x());
|
||||
PRINT(gpu_node->scale0.y());
|
||||
PRINT(gpu_node->scale0.z());
|
||||
|
||||
PRINT(gpu_node->org1.x());
|
||||
PRINT(gpu_node->org1.y());
|
||||
PRINT(gpu_node->org1.z());
|
||||
|
||||
PRINT(gpu_node->scale1.x());
|
||||
PRINT(gpu_node->scale1.y());
|
||||
PRINT(gpu_node->scale1.z());
|
||||
|
||||
for (size_t i=0;i<slots;i++)
|
||||
{
|
||||
PRINT(i);
|
||||
PRINT(gpu_node->offset[i]);
|
||||
PRINT(gpu_node->lower_t[i]);
|
||||
PRINT(gpu_node->upper_t[i]);
|
||||
const gpu::AABB bounds0 = gpu_node->getBounds0(i);
|
||||
const gpu::AABB bounds1 = gpu_node->getBounds1(i);
|
||||
PRINT(bounds0.lower.x());
|
||||
PRINT(bounds0.lower.y());
|
||||
PRINT(bounds0.lower.z());
|
||||
PRINT(bounds0.upper.x());
|
||||
PRINT(bounds0.upper.y());
|
||||
PRINT(bounds0.upper.z());
|
||||
|
||||
PRINT(bounds1.lower.x());
|
||||
PRINT(bounds1.lower.y());
|
||||
PRINT(bounds1.lower.z());
|
||||
PRINT(bounds1.upper.x());
|
||||
PRINT(bounds1.upper.y());
|
||||
PRINT(bounds1.upper.z());
|
||||
|
||||
};
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void build()
|
||||
{
|
||||
/* skip build for empty scene */
|
||||
const size_t numPrimitives = scene->getNumPrimitives(gtype_,true);
|
||||
if (numPrimitives == 0) { bvh->clear(); return; }
|
||||
|
||||
double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH");
|
||||
|
||||
buildMultiSegment(numPrimitives);
|
||||
|
||||
/* clear temporary data for static geometry */
|
||||
if (scene->isStaticAccel()) bvh->shrink();
|
||||
bvh->cleanup();
|
||||
bvh->postBuild(t0);
|
||||
|
||||
const size_t numOrgBVHNodes = bvh->alloc.getUsedBytes() / sizeof(AlignedNodeMB);
|
||||
/* count leaf primitives in original bvh */
|
||||
const size_t leafPrimitives = countLeafPrimitives(bvh->root);
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
DeviceGPU* deviceGPU = (DeviceGPU*)scene->device;
|
||||
const uint leaf_primitive_size = sizeof(Triangle1vMB);
|
||||
const uint node_size = sizeof(gpu::QBVHNodeNMB) * numOrgBVHNodes;
|
||||
const uint leaf_size = leafPrimitives * leaf_primitive_size;
|
||||
const uint totalSize = sizeof(gpu::BVHBase) + node_size + leaf_size;
|
||||
const uint node_data_start = sizeof(gpu::BVHBase);
|
||||
const uint leaf_data_start = sizeof(gpu::BVHBase) + node_size;
|
||||
assert( (leaf_data_start % 64) == 0 );
|
||||
|
||||
if (unlikely(deviceGPU->verbosity(2)))
|
||||
{
|
||||
PRINT( numOrgBVHNodes );
|
||||
PRINT( leaf_primitive_size );
|
||||
PRINT( node_size );
|
||||
PRINT( leaf_size );
|
||||
PRINT( totalSize );
|
||||
PRINT( node_data_start );
|
||||
PRINT( leaf_data_start );
|
||||
}
|
||||
|
||||
|
||||
char *bvh_mem = (char*)cl::sycl::aligned_alloc(64,totalSize,deviceGPU->getGPUDevice(),deviceGPU->getGPUContext(),cl::sycl::usm::alloc::shared);
|
||||
assert(bvh_mem);
|
||||
|
||||
std::atomic<size_t> gpu_node_allocator;
|
||||
std::atomic<size_t> gpu_leaf_allocator;
|
||||
|
||||
gpu_node_allocator.store(node_data_start);
|
||||
gpu_leaf_allocator.store(0);
|
||||
|
||||
//convertToGPULayout(bvh->root,bvh_mem,(gpu::Triangle1vMB*)(bvh_mem+leaf_data_start),0,0,gpu_node_allocator,gpu_leaf_allocator);
|
||||
convertToGPULayout16(bvh->root,bvh_mem,(gpu::Triangle1vMB*)(bvh_mem+leaf_data_start),0,0,gpu_node_allocator,gpu_leaf_allocator);
|
||||
|
||||
PRINT(sizeof(gpu::QBVHNodeNMB));
|
||||
|
||||
if (unlikely(deviceGPU->verbosity(2)))
|
||||
{
|
||||
PRINT(gpu_node_allocator.load());
|
||||
PRINT(gpu_leaf_allocator.load());
|
||||
PRINT(numPrimitives);
|
||||
PRINT(leafPrimitives);
|
||||
PRINT("BVH MB BUILDING DONE");
|
||||
}
|
||||
|
||||
assert(gpu_node_allocator.load() <= leaf_data_start);
|
||||
assert(gpu_leaf_allocator.load() <= leafPrimitives);
|
||||
|
||||
scene->gpu_bvh_mb_root = (size_t)bvh_mem;
|
||||
//exit(0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void buildMultiSegment(size_t numPrimitives)
|
||||
{
|
||||
/* create primref array */
|
||||
mvector<PrimRefMB> prims(scene->device,numPrimitives);
|
||||
PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface);
|
||||
|
||||
/* early out if no valid primitives */
|
||||
if (pinfo.size() == 0) { bvh->clear(); return; }
|
||||
|
||||
/* estimate acceleration structure size */
|
||||
const size_t node_bytes = pinfo.num_time_segments*sizeof(AlignedNodeMB)/(4*N);
|
||||
const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive));
|
||||
bvh->alloc.init_estimate(node_bytes+leaf_bytes);
|
||||
|
||||
/* settings for BVH build */
|
||||
BVHBuilderMSMBlur::Settings settings;
|
||||
settings.branchingFactor = N;
|
||||
settings.maxDepth = BVH::maxDepth;
|
||||
settings.logBlockSize = bsr(sahBlockSize);
|
||||
settings.minLeafSize = minLeafSize;
|
||||
settings.maxLeafSize = maxLeafSize;
|
||||
settings.travCost = travCost;
|
||||
settings.intCost = intCost;
|
||||
settings.singleLeafTimeSegment = Primitive::singleTimeSegment;
|
||||
settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
|
||||
|
||||
/* build hierarchy */
|
||||
auto root =
|
||||
BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
|
||||
RecalculatePrimRef<Mesh>(scene),
|
||||
typename BVH::CreateAlloc(bvh),
|
||||
typename BVH::AlignedNodeMB4D::Create(),
|
||||
typename BVH::AlignedNodeMB4D::Set(),
|
||||
CreateMSMBlurLeaf<N,Mesh,Primitive>(bvh),
|
||||
bvh->scene->progressInterface,
|
||||
settings);
|
||||
|
||||
bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
|
||||
}
|
||||
|
||||
|
||||
void clear() {
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(EMBREE_GEOMETRY_TRIANGLE)
|
||||
Builder* BVHGPUTriangle1vMBSceneBuilderSAH (void* bvh, Scene* scene) { return new BVHGPUBuilderMBlurSAH<4,TriangleMesh,Triangle4vMB>((BVH4*)bvh,scene,4,1.0f,4,16,TriangleMesh::geom_type); }
|
||||
#endif
|
||||
|
||||
#if defined(EMBREE_GEOMETRY_QUAD)
|
||||
Builder* BVHGPUQuad1vMBSceneBuilderSAH (void* bvh, Scene* scene) { return new BVHGPUBuilderMBlurSAH<4,QuadMesh,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,16,QuadMesh::geom_type); }
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ namespace embree
|
||||
|
||||
/* create primref array */
|
||||
prims.resize(numPrimitives);
|
||||
const PrimInfo pinfo = createPrimRefArray(scene,Geometry::MTY_CURVES,false,prims,scene->progressInterface);
|
||||
const PrimInfo pinfo = createPrimRefArray(scene,Geometry::MTY_CURVES,false,numPrimitives,prims,scene->progressInterface);
|
||||
|
||||
/* estimate acceleration structure size */
|
||||
const size_t node_bytes = pinfo.size()*sizeof(typename BVH::UnalignedNode)/(4*N);
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace embree
|
||||
|
||||
/* create primref array */
|
||||
mvector<PrimRefMB> prims0(scene->device,numPrimitives);
|
||||
const PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,Geometry::MTY_CURVES,prims0,bvh->scene->progressInterface);
|
||||
const PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,Geometry::MTY_CURVES,numPrimitives,prims0,bvh->scene->progressInterface);
|
||||
|
||||
/* estimate acceleration structure size */
|
||||
const size_t node_bytes = pinfo.num_time_segments*sizeof(typename BVH::AlignedNodeMB)/(4*N);
|
||||
|
||||
@@ -164,8 +164,10 @@ namespace embree
|
||||
prims.resize(numPrimitives);
|
||||
|
||||
PrimInfo pinfo = mesh ?
|
||||
createPrimRefArray(mesh,geomID_,prims,bvh->scene->progressInterface) :
|
||||
createPrimRefArray(scene,gtype_,false,prims,bvh->scene->progressInterface);
|
||||
//createPrimRefArray(mesh,numPrimitives,prims,bvh->scene->progressInterface) :
|
||||
//createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
|
||||
createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) :
|
||||
createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
|
||||
|
||||
/* pinfo might has zero size due to invalid geometry */
|
||||
if (unlikely(pinfo.size() == 0))
|
||||
@@ -252,8 +254,8 @@ namespace embree
|
||||
/* create primref array */
|
||||
prims.resize(numPrimitives);
|
||||
PrimInfo pinfo = mesh ?
|
||||
createPrimRefArray(mesh,geomID_,prims,bvh->scene->progressInterface) :
|
||||
createPrimRefArray(scene,gtype_,false,prims,bvh->scene->progressInterface);
|
||||
createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) :
|
||||
createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
|
||||
|
||||
/* enable os_malloc for two level build */
|
||||
if (mesh)
|
||||
@@ -554,6 +556,7 @@ namespace embree
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
|
||||
#if defined(EMBREE_GEOMETRY_TRIANGLE)
|
||||
Builder* BVH4Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
Builder* BVH4Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
@@ -563,7 +566,6 @@ namespace embree
|
||||
Builder* BVH4Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4v>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
Builder* BVH4Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); }
|
||||
|
||||
|
||||
Builder* BVH4QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
#if defined(__AVX__)
|
||||
Builder* BVH8Triangle4MeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
@@ -576,6 +578,8 @@ namespace embree
|
||||
Builder* BVH8QuantizedTriangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
Builder* BVH8QuantizedTriangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace embree
|
||||
{
|
||||
/* create primref array */
|
||||
mvector<PrimRef> prims(scene->device,numPrimitives);
|
||||
const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,prims,bvh->scene->progressInterface,0);
|
||||
const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0);
|
||||
/* early out if no valid primitives */
|
||||
if (pinfo.size() == 0) { bvh->clear(); return; }
|
||||
/* estimate acceleration structure size */
|
||||
@@ -189,7 +189,7 @@ namespace embree
|
||||
{
|
||||
/* create primref array */
|
||||
mvector<PrimRefMB> prims(scene->device,numPrimitives);
|
||||
PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,prims,bvh->scene->progressInterface);
|
||||
PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface);
|
||||
|
||||
/* early out if no valid primitives */
|
||||
if (pinfo.size() == 0) { bvh->clear(); return; }
|
||||
|
||||
@@ -138,8 +138,10 @@ namespace embree
|
||||
{
|
||||
/* standard spatial split SAH BVH builder */
|
||||
pinfo = mesh ?
|
||||
createPrimRefArray(mesh,geomID_,/*numSplitPrimitives,*/prims0,bvh->scene->progressInterface) :
|
||||
createPrimRefArray(scene,Mesh::geom_type,false,/*numSplitPrimitives,*/prims0,bvh->scene->progressInterface);
|
||||
//createPrimRefArray(mesh,numSplitPrimitives,prims0,bvh->scene->progressInterface) :
|
||||
//createPrimRefArray(scene,Mesh::geom_type,false,numSplitPrimitives,prims0,bvh->scene->progressInterface);
|
||||
createPrimRefArray(mesh,geomID_,numSplitPrimitives,prims0,bvh->scene->progressInterface) :
|
||||
createPrimRefArray(scene,Mesh::geom_type,false,numSplitPrimitives,prims0,bvh->scene->progressInterface);
|
||||
|
||||
Splitter splitter(scene);
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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. //
|
||||
// ======================================================================== //
|
||||
|
||||
#include "../common/isa.h"
|
||||
#include "bvh_gpu_factory.h"
|
||||
#include "../bvh/bvh.h"
|
||||
#include "../geometry/triangle1v.h"
|
||||
#include "../geometry/quad1v.h"
|
||||
#include "../geometry/triangle1vmb.h"
|
||||
#include "../geometry/quad1vmb.h"
|
||||
#include "../common/accelinstance.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVHGPUTriangle1vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVHGPUQuad1vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
|
||||
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVHGPUTriangle1vMBSceneBuilderSAH,void* COMMA Scene*);
|
||||
DECLARE_ISA_FUNCTION(Builder*,BVHGPUQuad1vMBSceneBuilderSAH,void* COMMA Scene*);
|
||||
|
||||
DECLARE_SYMBOL2(Accel::Intersector1,BVHGPUTriangle1vIntersector1);
|
||||
DECLARE_SYMBOL2(Accel::Intersector4,BVHGPUTriangle1vIntersector4);
|
||||
DECLARE_SYMBOL2(Accel::IntersectorN,BVHGPUTriangle1vIntersectorStream);
|
||||
|
||||
DECLARE_SYMBOL2(Accel::Intersector1,BVHGPUTriangle1vMBIntersector1);
|
||||
DECLARE_SYMBOL2(Accel::Intersector4,BVHGPUTriangle1vMBIntersector4);
|
||||
DECLARE_SYMBOL2(Accel::IntersectorN,BVHGPUTriangle1vMBIntersectorStream);
|
||||
|
||||
DECLARE_SYMBOL2(Accel::Intersector1,BVHGPUQuad1vIntersector1);
|
||||
DECLARE_SYMBOL2(Accel::Intersector4,BVHGPUQuad1vIntersector4);
|
||||
DECLARE_SYMBOL2(Accel::IntersectorN,BVHGPUQuad1vIntersectorStream);
|
||||
|
||||
DECLARE_SYMBOL2(Accel::Intersector1,BVHGPUQuad1vMBIntersector1);
|
||||
DECLARE_SYMBOL2(Accel::Intersector4,BVHGPUQuad1vMBIntersector4);
|
||||
DECLARE_SYMBOL2(Accel::IntersectorN,BVHGPUQuad1vMBIntersectorStream);
|
||||
|
||||
BVHGPUFactory::BVHGPUFactory()
|
||||
{
|
||||
int features = 0;
|
||||
selectBuilders(features);
|
||||
selectIntersectors(features);
|
||||
}
|
||||
|
||||
void BVHGPUFactory::selectBuilders(int features)
|
||||
{
|
||||
IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT(features,BVHGPUTriangle1vSceneBuilderSAH));
|
||||
IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT(features,BVHGPUQuad1vSceneBuilderSAH));
|
||||
|
||||
IF_ENABLED_TRIS(SELECT_SYMBOL_DEFAULT(features,BVHGPUTriangle1vMBSceneBuilderSAH));
|
||||
IF_ENABLED_QUADS(SELECT_SYMBOL_DEFAULT(features,BVHGPUQuad1vMBSceneBuilderSAH));
|
||||
}
|
||||
|
||||
void BVHGPUFactory::selectIntersectors(int features)
|
||||
{
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUTriangle1vIntersector1);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUTriangle1vIntersector4);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUTriangle1vIntersectorStream);
|
||||
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUTriangle1vMBIntersector1);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUTriangle1vMBIntersector4);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUTriangle1vMBIntersectorStream);
|
||||
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUQuad1vIntersector1);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUQuad1vIntersector4);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUQuad1vIntersectorStream);
|
||||
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUQuad1vMBIntersector1);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUQuad1vMBIntersector4);
|
||||
SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,BVHGPUQuad1vMBIntersectorStream);
|
||||
}
|
||||
|
||||
Accel::Intersectors BVHGPUFactory::BVHGPUTriangle1vIntersectors(BVH4* bvh)
|
||||
{
|
||||
Accel::Intersectors intersectors;
|
||||
intersectors.ptr = bvh;
|
||||
intersectors.intersector1 = BVHGPUTriangle1vIntersector1();
|
||||
#if defined (EMBREE_RAY_PACKETS)
|
||||
intersectors.intersector4 = BVHGPUTriangle1vIntersector4();
|
||||
intersectors.intersector8 = NULL;
|
||||
intersectors.intersector16 = NULL;
|
||||
intersectors.intersectorN = BVHGPUTriangle1vIntersectorStream();
|
||||
#endif
|
||||
return intersectors;
|
||||
}
|
||||
|
||||
Accel::Intersectors BVHGPUFactory::BVHGPUTriangle1vMBIntersectors(BVH4* bvh)
|
||||
{
|
||||
Accel::Intersectors intersectors;
|
||||
intersectors.ptr = bvh;
|
||||
intersectors.intersector1 = BVHGPUTriangle1vMBIntersector1();
|
||||
#if defined (EMBREE_RAY_PACKETS)
|
||||
intersectors.intersector4 = BVHGPUTriangle1vMBIntersector4();
|
||||
intersectors.intersector8 = NULL;
|
||||
intersectors.intersector16 = NULL;
|
||||
intersectors.intersectorN = BVHGPUTriangle1vMBIntersectorStream();
|
||||
#endif
|
||||
return intersectors;
|
||||
}
|
||||
|
||||
Accel::Intersectors BVHGPUFactory::BVHGPUQuad1vIntersectors(BVH4* bvh)
|
||||
{
|
||||
Accel::Intersectors intersectors;
|
||||
intersectors.ptr = bvh;
|
||||
intersectors.intersector1 = BVHGPUQuad1vIntersector1();
|
||||
#if defined (EMBREE_RAY_PACKETS)
|
||||
intersectors.intersector4 = BVHGPUQuad1vIntersector4();
|
||||
intersectors.intersector8 = NULL;
|
||||
intersectors.intersector16 = NULL;
|
||||
intersectors.intersectorN = BVHGPUQuad1vIntersectorStream();
|
||||
#endif
|
||||
return intersectors;
|
||||
}
|
||||
|
||||
Accel::Intersectors BVHGPUFactory::BVHGPUQuad1vMBIntersectors(BVH4* bvh)
|
||||
{
|
||||
Accel::Intersectors intersectors;
|
||||
intersectors.ptr = bvh;
|
||||
intersectors.intersector1 = BVHGPUQuad1vMBIntersector1();
|
||||
#if defined (EMBREE_RAY_PACKETS)
|
||||
intersectors.intersector4 = BVHGPUQuad1vMBIntersector4();
|
||||
intersectors.intersector8 = NULL;
|
||||
intersectors.intersector16 = NULL;
|
||||
intersectors.intersectorN = BVHGPUQuad1vMBIntersectorStream();
|
||||
#endif
|
||||
return intersectors;
|
||||
}
|
||||
|
||||
|
||||
Accel* BVHGPUFactory::BVHGPUTriangle1v(Scene* scene, BuildVariant bvariant)
|
||||
{
|
||||
BVH4* accel = new BVH4(Triangle1v::type,scene);
|
||||
Accel::Intersectors intersectors = BVHGPUTriangle1vIntersectors(accel);
|
||||
Builder* builder = BVHGPUTriangle1vSceneBuilderSAH(accel,scene,(size_t)bvariant);
|
||||
return new AccelInstance(accel,builder,intersectors);
|
||||
}
|
||||
|
||||
Accel* BVHGPUFactory::BVHGPUTriangle1vMB(Scene* scene)
|
||||
{
|
||||
BVH4* accel = new BVH4(Triangle1vMB::type,scene);
|
||||
Accel::Intersectors intersectors = BVHGPUTriangle1vMBIntersectors(accel);
|
||||
Builder* builder = BVHGPUTriangle1vMBSceneBuilderSAH(accel,scene);
|
||||
return new AccelInstance(accel,builder,intersectors);
|
||||
}
|
||||
|
||||
Accel* BVHGPUFactory::BVHGPUQuad1v(Scene* scene, BuildVariant bvariant)
|
||||
{
|
||||
BVH4* accel = new BVH4(Quad1v::type,scene);
|
||||
Accel::Intersectors intersectors = BVHGPUQuad1vIntersectors(accel);
|
||||
Builder* builder = BVHGPUQuad1vSceneBuilderSAH(accel,scene,(size_t)bvariant);
|
||||
return new AccelInstance(accel,builder,intersectors);
|
||||
}
|
||||
|
||||
Accel* BVHGPUFactory::BVHGPUQuad1vMB(Scene* scene)
|
||||
{
|
||||
BVH4* accel = new BVH4(Quad1vMB::type,scene);
|
||||
Accel::Intersectors intersectors = BVHGPUQuad1vMBIntersectors(accel);
|
||||
Builder* builder = BVHGPUQuad1vMBSceneBuilderSAH(accel,scene);
|
||||
return new AccelInstance(accel,builder,intersectors);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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_factory.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
/*! BVHGPU instantiations */
|
||||
class BVHGPUFactory : public BVHFactory
|
||||
{
|
||||
public:
|
||||
BVHGPUFactory();
|
||||
|
||||
public:
|
||||
Accel* BVHGPUTriangle1v (Scene* scene, BuildVariant bvariant);
|
||||
Accel::Intersectors BVHGPUTriangle1vIntersectors(BVH4* bvh);
|
||||
Accel* BVHGPUQuad1v (Scene* scene, BuildVariant bvariant);
|
||||
Accel::Intersectors BVHGPUQuad1vIntersectors(BVH4* bvh);
|
||||
|
||||
Accel* BVHGPUTriangle1vMB (Scene* scene);
|
||||
Accel::Intersectors BVHGPUTriangle1vMBIntersectors(BVH4* bvh);
|
||||
Accel* BVHGPUQuad1vMB (Scene* scene);
|
||||
Accel::Intersectors BVHGPUQuad1vMBIntersectors(BVH4* bvh);
|
||||
|
||||
private:
|
||||
void selectBuilders(int features);
|
||||
void selectIntersectors(int features);
|
||||
|
||||
private:
|
||||
DEFINE_ISA_FUNCTION(Builder*,BVHGPUQuad1vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
|
||||
DEFINE_ISA_FUNCTION(Builder*,BVHGPUTriangle1vSceneBuilderSAH,void* COMMA Scene* COMMA size_t);
|
||||
|
||||
DEFINE_ISA_FUNCTION(Builder*,BVHGPUQuad1vMBSceneBuilderSAH,void* COMMA Scene*);
|
||||
DEFINE_ISA_FUNCTION(Builder*,BVHGPUTriangle1vMBSceneBuilderSAH,void* COMMA Scene*);
|
||||
|
||||
DEFINE_SYMBOL2(Accel::Intersector1,BVHGPUTriangle1vIntersector1);
|
||||
DEFINE_SYMBOL2(Accel::Intersector4,BVHGPUTriangle1vIntersector4);
|
||||
DEFINE_SYMBOL2(Accel::IntersectorN,BVHGPUTriangle1vIntersectorStream);
|
||||
DEFINE_SYMBOL2(Accel::Intersector1,BVHGPUQuad1vIntersector1);
|
||||
DEFINE_SYMBOL2(Accel::Intersector4,BVHGPUQuad1vIntersector4);
|
||||
DEFINE_SYMBOL2(Accel::IntersectorN,BVHGPUQuad1vIntersectorStream);
|
||||
|
||||
DEFINE_SYMBOL2(Accel::Intersector1,BVHGPUTriangle1vMBIntersector1);
|
||||
DEFINE_SYMBOL2(Accel::Intersector4,BVHGPUTriangle1vMBIntersector4);
|
||||
DEFINE_SYMBOL2(Accel::IntersectorN,BVHGPUTriangle1vMBIntersectorStream);
|
||||
DEFINE_SYMBOL2(Accel::Intersector1,BVHGPUQuad1vMBIntersector1);
|
||||
DEFINE_SYMBOL2(Accel::Intersector4,BVHGPUQuad1vMBIntersector4);
|
||||
DEFINE_SYMBOL2(Accel::IntersectorN,BVHGPUQuad1vMBIntersectorStream);
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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. //
|
||||
// ======================================================================== //
|
||||
|
||||
#include "bvh_traverser_stream.h"
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#include "../gpu/bvh.h"
|
||||
#include "../gpu/ray.h"
|
||||
#include "../gpu/geometry.h"
|
||||
#endif
|
||||
|
||||
#define STACK_CULLING 1
|
||||
#define TSTATS(x)
|
||||
|
||||
namespace embree
|
||||
{
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
static const uint max_uint = 0xffffffff;
|
||||
static const uint mask_uint = 0xfffffff0;
|
||||
|
||||
template<typename T>
|
||||
__forceinline T block_align(T x, unsigned int alignment)
|
||||
{
|
||||
return ((x + alignment-1)/alignment)*alignment;
|
||||
}
|
||||
|
||||
|
||||
struct TraversalStats
|
||||
{
|
||||
uint nrays;
|
||||
uint tsteps;
|
||||
uint isteps;
|
||||
|
||||
inline void reset() {
|
||||
nrays = 0;
|
||||
tsteps = 0;
|
||||
isteps = 0;
|
||||
}
|
||||
|
||||
inline void nrays_inc() { gpu::atomic_add<uint,cl::sycl::access::address_space::global_space>(&nrays,1); }
|
||||
inline void tsteps_inc() { gpu::atomic_add<uint,cl::sycl::access::address_space::global_space>(&tsteps,1); }
|
||||
inline void isteps_inc() { gpu::atomic_add<uint,cl::sycl::access::address_space::global_space>(&isteps,1); }
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &cout, const TraversalStats& s) {
|
||||
return cout << "tsteps/ray " << (float)s.tsteps / s.nrays << " isteps/ray " << (float)s.isteps / s.nrays;
|
||||
};
|
||||
|
||||
inline void getClosestChildNode(const cl::sycl::intel::sub_group &sg,
|
||||
const gpu::NodeIntersectionData &isec,
|
||||
gpu::NodeRef &cur,
|
||||
uint &sindex,
|
||||
const float tfar,
|
||||
unsigned int stack_offset[BVH_MAX_STACK_ENTRIES],
|
||||
float stack_dist[BVH_MAX_STACK_ENTRIES])
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const float fnear = isec.dist;
|
||||
const uint valid = isec.valid;
|
||||
uint offset = isec.offset;
|
||||
const uint mask = intel_sub_group_ballot(valid);
|
||||
|
||||
if (mask == 0)
|
||||
{
|
||||
#if STACK_CULLING == 1
|
||||
do {
|
||||
sindex--;
|
||||
} while (stack_dist[sindex] > tfar);
|
||||
#else
|
||||
sindex--;
|
||||
#endif
|
||||
cur = stack_offset[sindex];
|
||||
return;
|
||||
}
|
||||
|
||||
offset += cur; /* relative encoding */
|
||||
const uint popc = cl::sycl::popcount(mask);
|
||||
cur = sg.broadcast<uint>(offset, cl::sycl::intel::ctz(mask));
|
||||
|
||||
if (popc == 1) return; // single hit only
|
||||
int t = (gpu::as_int(fnear) & mask_uint) | subgroupLocalID; // make the integer distance unique by masking off the least significant bits and adding the slotID
|
||||
t = valid ? t : max_uint; // invalid slots set to MIN_INT, as we sort descending;
|
||||
|
||||
for (uint i=0;i<popc-1;i++)
|
||||
{
|
||||
const int t_max = sg.reduce<int>(t, cl::sycl::intel::maximum<int>()); // from larger to smaller distance
|
||||
t = (t == t_max) ? max_uint : t;
|
||||
const uint index = t_max & (~mask_uint);
|
||||
stack_offset[sindex] = sg.broadcast<uint> (offset,index);
|
||||
stack_dist[sindex] = sg.broadcast<float>(fnear,index);
|
||||
sindex++;
|
||||
}
|
||||
const int t_max = sg.reduce<int>(t, cl::sycl::intel::maximum<int>()); // from larger to smaller distance
|
||||
cur = sg.broadcast<uint>(offset,t_max & (~mask_uint));
|
||||
}
|
||||
|
||||
|
||||
template<typename BVHNodeType, typename Primitive>
|
||||
[[cl::intel_reqd_sub_group_size(BVH_NODE_N)]] inline void traceRayBVH16(const cl::sycl::intel::sub_group &sg,
|
||||
const uint m_active,
|
||||
gpu::RTCRayGPU &ray,
|
||||
gpu::RTCHitGPU &hit,
|
||||
void *bvh_mem,
|
||||
TraversalStats *tstats)
|
||||
{
|
||||
unsigned int stack_offset[BVH_MAX_STACK_ENTRIES];
|
||||
float stack_dist[BVH_MAX_STACK_ENTRIES];
|
||||
|
||||
// === init local hit ===
|
||||
gpu::RTCHitGPU local_hit;
|
||||
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
|
||||
/* cannot handle masked control flow yet */
|
||||
uint m_activeLanes = m_active;
|
||||
m_activeLanes = gpu::cselect((uint)(m_activeLanes == (uint)(1<<BVH_NODE_N)-1),m_activeLanes,(uint)0);
|
||||
|
||||
const Vec3f org16 = ray.get_org();
|
||||
const Vec3f dir16 = ray.get_dir();
|
||||
const float tnear16 = ray.tnear();
|
||||
const float tfar16 = ray.tfar;
|
||||
const float time16 = ray.time();
|
||||
#pragma nounroll
|
||||
while(m_activeLanes)
|
||||
{
|
||||
const uint rayID = cl::sycl::intel::ctz(m_activeLanes);
|
||||
m_activeLanes &= m_activeLanes-1;
|
||||
|
||||
local_hit.init();
|
||||
const Vec3f org(sg.broadcast<float>(org16.x,rayID),sg.broadcast<float>(org16.y,rayID),sg.broadcast<float>(org16.z,rayID));
|
||||
const Vec3f dir(sg.broadcast<float>(dir16.x,rayID),sg.broadcast<float>(dir16.y,rayID),sg.broadcast<float>(dir16.z,rayID));
|
||||
|
||||
const float time = sg.broadcast<float>(time16 ,rayID);
|
||||
const float tnear = sg.broadcast<float>(tnear16,rayID);
|
||||
float tfar = sg.broadcast<float>(tfar16 ,rayID);
|
||||
float hit_tfar = tfar;
|
||||
|
||||
const int dir_mask_x = dir.x >= 0.0f ? 0 : 1;
|
||||
const int dir_mask_y = dir.y >= 0.0f ? 0 : 1;
|
||||
const int dir_mask_z = dir.z >= 0.0f ? 0 : 1;
|
||||
const Vec3i dir_mask(dir_mask_x, dir_mask_y, dir_mask_z);
|
||||
//const Vec3f new_dir = gpu::cselect(dir != 0.0f, dir, Vec3f(1E-18f));
|
||||
const float new_dir_x = dir.x != 0.0f ? dir.x : 1E-18f;
|
||||
const float new_dir_y = dir.y != 0.0f ? dir.y : 1E-18f;
|
||||
const float new_dir_z = dir.z != 0.0f ? dir.z : 1E-18f;
|
||||
const Vec3f new_dir(new_dir_x,new_dir_y,new_dir_z);
|
||||
const Vec3f inv_dir = rcp(new_dir);
|
||||
const Vec3f inv_dir_org = -inv_dir * org;
|
||||
|
||||
const char *const bvh_base = (char*)bvh_mem;
|
||||
stack_offset[0] = max_uint; // sentinel
|
||||
stack_dist[0] = -(float)INFINITY;
|
||||
stack_offset[1] = sizeof(struct gpu::BVHBase); // single node after bvh start
|
||||
stack_dist[1] = -(float)INFINITY;
|
||||
|
||||
unsigned int sindex = 2;
|
||||
|
||||
TSTATS(tstats->nrays_inc());
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* stack pop */
|
||||
sindex--;
|
||||
|
||||
#if STACK_CULLING == 1
|
||||
if (stack_dist[sindex] > tfar) continue;
|
||||
#endif
|
||||
|
||||
gpu::NodeRef cur = stack_offset[sindex];
|
||||
|
||||
/* BVH down traversal */
|
||||
while(!cur.isLeaf())
|
||||
{
|
||||
TSTATS(tstats->tsteps_inc());
|
||||
const BVHNodeType &node = *(BVHNodeType*)(bvh_base + cur);
|
||||
const gpu::NodeIntersectionData isec = intersectNode(sg,node,dir_mask,inv_dir,inv_dir_org,time,tnear,tfar);
|
||||
getClosestChildNode(sg,isec,cur,sindex,tfar,stack_offset,stack_dist);
|
||||
}
|
||||
|
||||
/* stack empty */
|
||||
if (cur == max_uint) break; // sentinel reached -> exit
|
||||
|
||||
/* leaf intersection */
|
||||
const uint numPrims = cur.getNumLeafPrims();
|
||||
const uint leafOffset = cur.getLeafOffset();
|
||||
|
||||
const Primitive *const prim = (Primitive *)(bvh_base + leafOffset);
|
||||
TSTATS(tstats->isteps_inc());
|
||||
hit_tfar = intersectPrimitive1v(sg, prim, numPrims, org, dir, time, tnear, hit_tfar, local_hit, subgroupLocalID);
|
||||
|
||||
/* update tfar */
|
||||
tfar = sg.reduce<float>(hit_tfar, cl::sycl::intel::minimum<float>());
|
||||
}
|
||||
|
||||
/* select hit with shortest intersection distance */
|
||||
|
||||
const uint index = cl::sycl::intel::ctz(intel_sub_group_ballot(tfar == hit_tfar));
|
||||
local_hit.broadcast(sg,index);
|
||||
|
||||
if (subgroupLocalID == rayID)
|
||||
if (local_hit.primID != -1)
|
||||
{
|
||||
hit = local_hit;
|
||||
ray.tfar = tfar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -606,7 +606,11 @@ namespace embree
|
||||
|
||||
|
||||
void RayStreamFilter::intersectAOS(Scene* scene, RTCRayHit* _rayN, size_t N, size_t stride, IntersectContext* context) {
|
||||
if (unlikely(context->isCoherent()))
|
||||
if (unlikely(context->traceOnGPU()))
|
||||
{
|
||||
scene->intersectors.intersectN((RTCRayHitN**)_rayN, N, context);
|
||||
}
|
||||
else if (unlikely(context->isCoherent()))
|
||||
filterAOS<VSIZEL, true>(scene, _rayN, N, stride, context);
|
||||
else
|
||||
filterAOS<VSIZEX, true>(scene, _rayN, N, stride, context);
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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. //
|
||||
// ======================================================================== //
|
||||
|
||||
#define EMBREE_SYCL_SIMD_LIBRARY
|
||||
|
||||
#include "bvh_intersector_gpu.h"
|
||||
|
||||
#define DBG(x)
|
||||
#define DBG_PRINT_BUFFER_SIZE 1024*1024
|
||||
//#define DBG_PRINT_BUFFER_SIZE 0
|
||||
#define DBG_PRINT_LINE_SIZE 512
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(16)]] SYCL_EXTERNAL void rtcIntersectSYCL(cl::sycl::intel::sub_group &sg,
|
||||
cl::sycl::global_ptr<RTCSceneTy> scene,
|
||||
cl::sycl::global_ptr<struct RTCRayHit> rayhit)
|
||||
{
|
||||
size_t *scene_data = (size_t*)scene.get();
|
||||
void *bvh_root = (void*)scene_data[2]; // root node is at 16 bytes offset
|
||||
embree::gpu::RTCRayGPU &ray = *(embree::gpu::RTCRayGPU*)&rayhit->ray;
|
||||
embree::gpu::RTCHitGPU &hit = *(embree::gpu::RTCHitGPU*)&rayhit->hit;
|
||||
uint m_active = intel_sub_group_ballot(true);
|
||||
embree::traceRayBVH16<embree::gpu::QBVHNodeN,embree::gpu::Triangle1v>(sg,m_active,ray,hit,bvh_root,nullptr);
|
||||
}
|
||||
|
||||
namespace embree
|
||||
{
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BVH_NODE_N)]] SYCL_EXTERNAL void rtcIntersectGPUTest(cl::sycl::intel::sub_group &sg,
|
||||
cl::sycl::global_ptr<RTCSceneTy> scene,
|
||||
struct RTCRayHit &rtc_rayhit,
|
||||
ulong ext_fct)
|
||||
{
|
||||
size_t *scene_data = (size_t*)scene.get();
|
||||
void *bvh_root = (void*)scene_data[2]; // root node is at 16 bytes offset
|
||||
gpu::RTCRayGPU &ray = *(gpu::RTCRayGPU*)&rtc_rayhit.ray;
|
||||
gpu::RTCHitGPU &hit = *(gpu::RTCHitGPU*)&rtc_rayhit.hit;
|
||||
uint m_active = intel_sub_group_ballot(true);
|
||||
traceRayBVH16<gpu::QBVHNodeN,gpu::Triangle1v>(sg,m_active,ray,hit,bvh_root,nullptr);
|
||||
#if 0
|
||||
uint (*testfct)(uint, uint) = reinterpret_cast<uint (*)(uint, uint)>(ext_fct);
|
||||
hit.primID = testfct(hit.primID,hit.primID);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace isa
|
||||
{
|
||||
/*! BVH ray stream GPU intersector */
|
||||
template<typename Primitive>
|
||||
class BVHNGPUIntersectorStream
|
||||
{
|
||||
typedef BVHN<4> BVH;
|
||||
|
||||
public:
|
||||
static void intersect(Accel::Intersectors* This, RayHitN** inputRays, size_t numRays, IntersectContext* context);
|
||||
static void occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context);
|
||||
|
||||
};
|
||||
|
||||
template<typename Primitive>
|
||||
void BVHNGPUIntersectorStream<Primitive>::intersect(Accel::Intersectors* This, RayHitN** _inputRays, size_t numRays, IntersectContext* context)
|
||||
{
|
||||
BVH* __restrict__ bvh = (BVH*) This->ptr;
|
||||
if (bvh->root == BVH::emptyNode) return;
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
gpu::RTCRayHitGPU* inputRays = (gpu::RTCRayHitGPU*)_inputRays;
|
||||
void *bvh_mem = (void*)(bvh->scene->gpu_bvh_root);
|
||||
assert( sizeof(gpu::RTCRayHitGPU) == sizeof(RTCRayHit) );
|
||||
DBG(numRays = 1);
|
||||
DeviceGPU* deviceGPU = (DeviceGPU*)bvh->device;
|
||||
cl::sycl::queue &gpu_queue = deviceGPU->getGPUQueue();
|
||||
|
||||
TraversalStats *tstats = nullptr;
|
||||
TSTATS(tstats = (TraversalStats *)cl::sycl::aligned_alloc(64,sizeof(TraversalStats),deviceGPU->getGPUDevice(),deviceGPU->getGPUContext(),cl::sycl::usm::alloc::shared));
|
||||
TSTATS(tstats->reset());
|
||||
|
||||
{
|
||||
cl::sycl::event queue_event = gpu_queue.submit([&](cl::sycl::handler &cgh) {
|
||||
//cl::sycl::stream out(DBG_PRINT_BUFFER_SIZE, DBG_PRINT_LINE_SIZE, cgh);
|
||||
const cl::sycl::nd_range<1> nd_range(cl::sycl::range<1>(block_align(numRays,BVH_NODE_N)),cl::sycl::range<1>(BVH_NODE_N));
|
||||
cl::sycl::global_ptr<RTCSceneTy> sycl_scene((RTCSceneTy*)bvh->scene);
|
||||
|
||||
cgh.parallel_for<class trace_ray_stream>(nd_range,[=](cl::sycl::nd_item<1> item) {
|
||||
const uint globalID = item.get_global_id(0);
|
||||
cl::sycl::intel::sub_group sg = item.get_sub_group();
|
||||
|
||||
#if 0
|
||||
RTCRayHit* __inputRays = (RTCRayHit*)_inputRays;
|
||||
rtcIntersectGPUTest(sg,sycl_scene,__inputRays[globalID],0);
|
||||
#else
|
||||
//if (globalID < numRays)
|
||||
{
|
||||
uint m_activeLanes = intel_sub_group_ballot(globalID < numRays);
|
||||
if (m_activeLanes == 0xffff)
|
||||
traceRayBVH16<gpu::QBVHNodeN,Primitive>(sg,m_activeLanes,inputRays[globalID].ray,inputRays[globalID].hit,bvh_mem,tstats);
|
||||
}
|
||||
#endif
|
||||
});
|
||||
});
|
||||
try {
|
||||
gpu_queue.wait_and_throw();
|
||||
} catch (cl::sycl::exception const& e) {
|
||||
std::cout << "Caught synchronous SYCL exception:\n"
|
||||
<< e.what() << std::endl;
|
||||
FATAL("OpenCL Exception");
|
||||
}
|
||||
TSTATS(cl::sycl::free(tstats,deviceGPU->getGPUContext()););
|
||||
TSTATS(std::cout << "RAY TRAVERSAL STATS: " << *tstats << std::endl);
|
||||
}
|
||||
DBG(exit(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Primitive>
|
||||
void BVHNGPUIntersectorStream<Primitive>::occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context)
|
||||
{
|
||||
BVH* __restrict__ bvh = (BVH*) This->ptr;
|
||||
if (bvh->root == BVH::emptyNode) return;
|
||||
|
||||
}
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
typedef BVHNGPUIntersectorStream< gpu::Triangle1v > BVHNGPUTriangle1vIntersectorStream;
|
||||
typedef BVHNGPUIntersectorStream< gpu::Quad1v > BVHNGPUQuad1vIntersectorStream;
|
||||
|
||||
#endif
|
||||
|
||||
/*! BVH ray GPU intersectors */
|
||||
|
||||
class BVHNGPUTriangle1vIntersector1
|
||||
{
|
||||
public:
|
||||
static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context);
|
||||
static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
|
||||
static bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUTriangle1vIntersector1::intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context) {}
|
||||
void BVHNGPUTriangle1vIntersector1::occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context) {}
|
||||
bool BVHNGPUTriangle1vIntersector1::pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
|
||||
|
||||
class BVHNGPUTriangle1vIntersector4
|
||||
{
|
||||
public:
|
||||
static void intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context);
|
||||
static void occluded (vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUTriangle1vIntersector4::intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context) {}
|
||||
void BVHNGPUTriangle1vIntersector4::occluded(vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context) {}
|
||||
|
||||
|
||||
class BVHNGPUQuad1vIntersector1
|
||||
{
|
||||
public:
|
||||
static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context);
|
||||
static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
|
||||
static bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUQuad1vIntersector1::intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context) {}
|
||||
void BVHNGPUQuad1vIntersector1::occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context) {}
|
||||
bool BVHNGPUQuad1vIntersector1::pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
|
||||
|
||||
class BVHNGPUQuad1vIntersector4
|
||||
{
|
||||
public:
|
||||
static void intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context);
|
||||
static void occluded (vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUQuad1vIntersector4::intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context) {}
|
||||
void BVHNGPUQuad1vIntersector4::occluded(vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// General BVHIntersectorStreamPacketFallback Intersector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
DEFINE_INTERSECTORN(BVHGPUTriangle1vIntersectorStream,BVHNGPUTriangle1vIntersectorStream);
|
||||
DEFINE_INTERSECTOR1(BVHGPUTriangle1vIntersector1,BVHNGPUTriangle1vIntersector1);
|
||||
DEFINE_INTERSECTOR4(BVHGPUTriangle1vIntersector4,BVHNGPUTriangle1vIntersector4);
|
||||
|
||||
DEFINE_INTERSECTORN(BVHGPUQuad1vIntersectorStream,BVHNGPUQuad1vIntersectorStream);
|
||||
DEFINE_INTERSECTOR1(BVHGPUQuad1vIntersector1,BVHNGPUQuad1vIntersector1);
|
||||
DEFINE_INTERSECTOR4(BVHGPUQuad1vIntersector4,BVHNGPUQuad1vIntersector4);
|
||||
|
||||
#endif
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,170 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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. //
|
||||
// ======================================================================== //
|
||||
|
||||
#define EMBREE_SYCL_SIMD_LIBRARY
|
||||
|
||||
#include "bvh_intersector_gpu.h"
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
#define DBG_PRINT_BUFFER_SIZE 1024*1024
|
||||
//#define DBG_PRINT_BUFFER_SIZE 0
|
||||
#define DBG_PRINT_LINE_SIZE 512
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace isa
|
||||
{
|
||||
/*! BVH ray stream GPU intersector */
|
||||
template<typename Primitive>
|
||||
class BVHNGPUIntersectorStreamMB
|
||||
{
|
||||
typedef BVHN<4> BVH;
|
||||
|
||||
public:
|
||||
static void intersect(Accel::Intersectors* This, RayHitN** inputRays, size_t numRays, IntersectContext* context);
|
||||
static void occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context);
|
||||
|
||||
};
|
||||
|
||||
template<typename Primitive>
|
||||
void BVHNGPUIntersectorStreamMB<Primitive>::intersect(Accel::Intersectors* This, RayHitN** _inputRays, size_t numRays, IntersectContext* context)
|
||||
{
|
||||
BVH* __restrict__ bvh = (BVH*) This->ptr;
|
||||
if (bvh->root == BVH::emptyNode) return;
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
gpu::RTCRayHitGPU* inputRays = (gpu::RTCRayHitGPU*)_inputRays;
|
||||
void *bvh_mem = (void*)(bvh->scene->gpu_bvh_mb_root);
|
||||
assert( sizeof(gpu::RTCRayHitGPU) == sizeof(RTCRayHit) );
|
||||
//DBG(numRays = 1);
|
||||
DeviceGPU* deviceGPU = (DeviceGPU*)bvh->device;
|
||||
cl::sycl::queue &gpu_queue = deviceGPU->getGPUQueue();
|
||||
|
||||
TraversalStats *tstats = nullptr;
|
||||
TSTATS(tstats = (TraversalStats *)cl::sycl::aligned_alloc(64,sizeof(TraversalStats),deviceGPU->getGPUDevice(),deviceGPU->getGPUContext(),cl::sycl::usm::alloc::shared));
|
||||
TSTATS(tstats->reset());
|
||||
//for (int ID=0;ID<numRays;ID++)
|
||||
{
|
||||
//PRINT(ID);
|
||||
cl::sycl::event queue_event = gpu_queue.submit([&](cl::sycl::handler &cgh) {
|
||||
|
||||
//cl::sycl::stream out(DBG_PRINT_BUFFER_SIZE, DBG_PRINT_LINE_SIZE, cgh);
|
||||
const cl::sycl::nd_range<1> nd_range(cl::sycl::range<1>(block_align(numRays,BVH_NODE_N)),cl::sycl::range<1>(BVH_NODE_N));
|
||||
|
||||
cgh.parallel_for<class trace_ray_stream>(nd_range,[=](cl::sycl::nd_item<1> item) {
|
||||
const uint globalID = item.get_global_id(0);
|
||||
cl::sycl::intel::sub_group sg = item.get_sub_group();
|
||||
{
|
||||
uint m_activeLanes = intel_sub_group_ballot(globalID < numRays);
|
||||
if (m_activeLanes == 0xffff)
|
||||
traceRayBVH16<gpu::QBVHNodeNMB,Primitive>(sg,m_activeLanes,inputRays[globalID].ray,inputRays[globalID].hit,bvh_mem,tstats);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
try {
|
||||
gpu_queue.wait_and_throw();
|
||||
} catch (cl::sycl::exception const& e) {
|
||||
std::cout << "Caught synchronous SYCL exception:\n"
|
||||
<< e.what() << std::endl;
|
||||
FATAL("OpenCL Exception");
|
||||
}
|
||||
TSTATS(cl::sycl::free(tstats,deviceGPU->getGPUContext()););
|
||||
TSTATS(std::cout << "RAY TRAVERSAL STATS: " << *tstats << std::endl);
|
||||
}
|
||||
DBG(exit(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Primitive>
|
||||
void BVHNGPUIntersectorStreamMB<Primitive>::occluded (Accel::Intersectors* This, RayN** inputRays, size_t numRays, IntersectContext* context)
|
||||
{
|
||||
BVH* __restrict__ bvh = (BVH*) This->ptr;
|
||||
if (bvh->root == BVH::emptyNode) return;
|
||||
|
||||
}
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
typedef BVHNGPUIntersectorStreamMB< gpu::Triangle1vMB > BVHNGPUTriangle1vMBIntersectorStream;
|
||||
typedef BVHNGPUIntersectorStreamMB< gpu::Quad1vMB > BVHNGPUQuad1vMBIntersectorStream;
|
||||
|
||||
#endif
|
||||
|
||||
/*! BVH ray GPU intersectors */
|
||||
|
||||
class BVHNGPUTriangle1vMBIntersector1
|
||||
{
|
||||
public:
|
||||
static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context);
|
||||
static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
|
||||
static bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUTriangle1vMBIntersector1::intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context) {}
|
||||
void BVHNGPUTriangle1vMBIntersector1::occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context) {}
|
||||
bool BVHNGPUTriangle1vMBIntersector1::pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
|
||||
|
||||
class BVHNGPUTriangle1vMBIntersector4
|
||||
{
|
||||
public:
|
||||
static void intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context);
|
||||
static void occluded (vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUTriangle1vMBIntersector4::intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context) {}
|
||||
void BVHNGPUTriangle1vMBIntersector4::occluded(vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context) {}
|
||||
|
||||
|
||||
class BVHNGPUQuad1vMBIntersector1
|
||||
{
|
||||
public:
|
||||
static void intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context);
|
||||
static void occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context);
|
||||
static bool pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUQuad1vMBIntersector1::intersect (const Accel::Intersectors* This, RayHit& ray, IntersectContext* context) {}
|
||||
void BVHNGPUQuad1vMBIntersector1::occluded (const Accel::Intersectors* This, Ray& ray, IntersectContext* context) {}
|
||||
bool BVHNGPUQuad1vMBIntersector1::pointQuery(const Accel::Intersectors* This, PointQuery* query, PointQueryContext* context) { return false; }
|
||||
|
||||
class BVHNGPUQuad1vMBIntersector4
|
||||
{
|
||||
public:
|
||||
static void intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context);
|
||||
static void occluded (vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context);
|
||||
};
|
||||
|
||||
void BVHNGPUQuad1vMBIntersector4::intersect(vint<4>* valid, Accel::Intersectors* This, RayHitK<4>& ray, IntersectContext* context) {}
|
||||
void BVHNGPUQuad1vMBIntersector4::occluded(vint<4>* valid, Accel::Intersectors* This, RayK<4>& ray, IntersectContext* context) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// General BVHIntersectorStreamPacketFallback Intersector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
DEFINE_INTERSECTORN(BVHGPUTriangle1vMBIntersectorStream,BVHNGPUTriangle1vMBIntersectorStream);
|
||||
DEFINE_INTERSECTOR1(BVHGPUTriangle1vMBIntersector1,BVHNGPUTriangle1vMBIntersector1);
|
||||
DEFINE_INTERSECTOR4(BVHGPUTriangle1vMBIntersector4,BVHNGPUTriangle1vMBIntersector4);
|
||||
|
||||
DEFINE_INTERSECTORN(BVHGPUQuad1vMBIntersectorStream,BVHNGPUQuad1vMBIntersectorStream);
|
||||
DEFINE_INTERSECTOR1(BVHGPUQuad1vMBIntersector1,BVHNGPUQuad1vMBIntersector1);
|
||||
DEFINE_INTERSECTOR4(BVHGPUQuad1vMBIntersector4,BVHNGPUQuad1vMBIntersector4);
|
||||
|
||||
#endif
|
||||
};
|
||||
};
|
||||
@@ -752,8 +752,15 @@ namespace embree
|
||||
vbool<N> vmask = tNear <= tFar;
|
||||
if (unlikely(ref.isAlignedNodeMB4D())) {
|
||||
const typename BVHN<N>::AlignedNodeMB4D* node1 = (const typename BVHN<N>::AlignedNodeMB4D*) node;
|
||||
//PRINT(*node1);
|
||||
vmask &= (node1->lower_t <= time) & (time < node1->upper_t);
|
||||
}
|
||||
/* else */
|
||||
/* PRINT(*node); */
|
||||
|
||||
/* PRINT(tNear); */
|
||||
/* PRINT(tFar); */
|
||||
/* PRINT(vmask); */
|
||||
const size_t mask = movemask(vmask);
|
||||
dist = tNear;
|
||||
return mask;
|
||||
|
||||
@@ -63,6 +63,12 @@ namespace embree
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
size_t gpu_bvh_root; // 16 bytes offset from scene class
|
||||
size_t gpu_bvh_mb_root; // 24 bytes offset from scene class
|
||||
#endif
|
||||
|
||||
LBBox3fa bounds; // linear bounds
|
||||
Type type;
|
||||
};
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace embree
|
||||
ThreadLocal alloc1;
|
||||
};
|
||||
|
||||
FastAllocator (Device* device, bool osAllocation)
|
||||
FastAllocator (Device* device, bool osAllocation, bool useUSM = false)
|
||||
: device(device), slotMask(0), usedBlocks(nullptr), freeBlocks(nullptr), use_single_mode(false), defaultBlockSize(PAGE_SIZE), estimatedSize(0),
|
||||
growSize(PAGE_SIZE), maxGrowSize(maxAllocationSize), log2_grow_size_scale(0), bytesUsed(0), bytesFree(0), bytesWasted(0), atype(osAllocation ? OS_MALLOC : ALIGNED_MALLOC),
|
||||
primrefarray(device,0)
|
||||
|
||||
@@ -246,6 +246,24 @@ namespace embree
|
||||
public:
|
||||
typedef Vec3fa value_type;
|
||||
|
||||
#if defined(EMBREE_SYCL_SIMD_LIBRARY) && defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
/*! access to the ith element of the buffer */
|
||||
__forceinline const Vec3fa operator [](size_t i) const
|
||||
{
|
||||
assert(i<num);
|
||||
return Vec3fa::loadu(ptr_ofs + i*stride);
|
||||
}
|
||||
|
||||
/*! writes the i'th element */
|
||||
__forceinline void store(size_t i, const Vec3fa& v)
|
||||
{
|
||||
assert(i<num);
|
||||
Vec3fa::storeu(ptr_ofs + i*stride, v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*! access to the ith element of the buffer */
|
||||
__forceinline const Vec3fa operator [](size_t i) const
|
||||
{
|
||||
@@ -259,5 +277,6 @@ namespace embree
|
||||
assert(i<num);
|
||||
vfloat4::storeu((float*)(ptr_ofs + i*stride), (vfloat4)v);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "accel.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
{
|
||||
#define MODE_HIGH_QUALITY (1<<8)
|
||||
|
||||
/*! virtual interface for all hierarchy builders */
|
||||
|
||||
@@ -41,6 +41,10 @@ namespace embree
|
||||
__forceinline bool isIncoherent() const {
|
||||
return embree::isIncoherent(user->flags);
|
||||
}
|
||||
|
||||
__forceinline bool traceOnGPU() const {
|
||||
return embree::traceOnGPU(user->flags);
|
||||
}
|
||||
|
||||
public:
|
||||
Scene* scene;
|
||||
|
||||
@@ -31,10 +31,12 @@
|
||||
|
||||
#include "../bvh/bvh4_factory.h"
|
||||
#include "../bvh/bvh8_factory.h"
|
||||
#include "../bvh/bvh_gpu_factory.h"
|
||||
|
||||
#include "../../common/tasking/taskscheduler.h"
|
||||
#include "../../common/sys/alloc.h"
|
||||
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! some global variables that can be set via rtcSetParameter1i for debugging purposes */
|
||||
@@ -102,6 +104,11 @@ namespace embree
|
||||
bvh8_factory = make_unique(new BVH8Factory(enabled_builder_cpu_features, enabled_cpu_features));
|
||||
#endif
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
/* register GPU algorithms */
|
||||
bvh_gpu_factory = make_unique(new BVHGPUFactory());
|
||||
#endif
|
||||
|
||||
/* setup tasking system */
|
||||
initTaskingSystem(numThreads);
|
||||
|
||||
@@ -516,4 +523,75 @@ namespace embree
|
||||
default: throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown readable property"); break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
class CPUDeviceSelector : public cl::sycl::device_selector {
|
||||
public:
|
||||
int operator()(const cl::sycl::device &Device) const override {
|
||||
return Device.is_cpu() ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
auto exception_handler = [] (cl::sycl::exception_list exceptions) {
|
||||
for (std::exception_ptr const& e : exceptions) {
|
||||
try {
|
||||
std::rethrow_exception(e);
|
||||
} catch(cl::sycl::exception const& e) {
|
||||
std::cout << "Caught asynchronous SYCL exception:\n"
|
||||
<< e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DeviceGPU::DeviceGPU(const char* cfg, void *device, void *queue) : Device(cfg)
|
||||
{
|
||||
assert(device);
|
||||
assert(queue);
|
||||
|
||||
tri_accel = "bvhgpu.triangle1v";
|
||||
quad_accel = "bvhgpu.quad1v";
|
||||
tri_accel_mb = "bvhgpu.triangle1vmb";
|
||||
quad_accel_mb = "bvhgpu.quad1vmb";
|
||||
|
||||
gpu_device = (cl::sycl::device *)device;
|
||||
gpu_queue = (cl::sycl::queue *)queue;
|
||||
gpu_context = gpu_queue->get_context();
|
||||
|
||||
// Printing Device Information
|
||||
gpu_maxWorkGroupSize = getGPUDevice().get_info<cl::sycl::info::device::max_work_group_size>();
|
||||
gpu_maxComputeUnits = getGPUDevice().get_info<cl::sycl::info::device::max_compute_units>();
|
||||
|
||||
std::cout << "GPU Device: " << getGPUDevice().get_info<cl::sycl::info::device::name>() << std::endl;
|
||||
std::cout << "- Max Work Group Size : " << gpu_maxWorkGroupSize << std::endl;
|
||||
std::cout << "- Max Compute Units : " << gpu_maxComputeUnits << std::endl;
|
||||
|
||||
try {
|
||||
cpu_queue = new cl::sycl::queue(CPUDeviceSelector(), exception_handler);
|
||||
cpu_device = new cl::sycl::device(CPUDeviceSelector());
|
||||
assert(cpu_queue);
|
||||
assert(cpu_device);
|
||||
cpu_context = cpu_queue->get_context();
|
||||
|
||||
unsigned int cpu_maxWorkGroupSize = getCPUDevice().get_info<cl::sycl::info::device::max_work_group_size>();
|
||||
unsigned int cpu_maxComputeUnits = getCPUDevice().get_info<cl::sycl::info::device::max_compute_units>();
|
||||
|
||||
std::cout << "CPU Device: " << getCPUDevice().get_info<cl::sycl::info::device::name>() << std::endl;
|
||||
std::cout << "- Max Work Group Size : " << cpu_maxWorkGroupSize << std::endl;
|
||||
std::cout << "- Max Compute Units : " << cpu_maxComputeUnits << std::endl;
|
||||
|
||||
} catch (cl::sycl::runtime_error &E) {
|
||||
std::cout << E.what() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "Houston, we've had a problem. Unhandled exception in DeviceGPU constructor";
|
||||
}
|
||||
}
|
||||
|
||||
DeviceGPU::~DeviceGPU()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -20,10 +20,17 @@
|
||||
#include "state.h"
|
||||
#include "accel.h"
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#include "../gpu/common.h"
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
class BVH4Factory;
|
||||
class BVH8Factory;
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
class BVHGPUFactory;
|
||||
#endif
|
||||
|
||||
class Device : public State, public MemoryMonitorInterface
|
||||
{
|
||||
@@ -87,6 +94,10 @@ namespace embree
|
||||
#if defined(EMBREE_TARGET_SIMD8)
|
||||
std::unique_ptr<BVH8Factory> bvh8_factory;
|
||||
#endif
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
std::unique_ptr<BVHGPUFactory> bvh_gpu_factory;
|
||||
#endif
|
||||
|
||||
#if USE_TASK_ARENA
|
||||
std::unique_ptr<tbb::task_arena> arena;
|
||||
@@ -95,4 +106,42 @@ namespace embree
|
||||
/* ray streams filter */
|
||||
RayStreamFilterFuncs rayStreamFilters;
|
||||
};
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
class DeviceGPU : public Device
|
||||
{
|
||||
public:
|
||||
|
||||
DeviceGPU(const char* cfg, void *device, void *queue);
|
||||
~DeviceGPU();
|
||||
|
||||
private:
|
||||
cl::sycl::queue *gpu_queue;
|
||||
cl::sycl::device *gpu_device;
|
||||
cl::sycl::context gpu_context;
|
||||
|
||||
|
||||
unsigned int gpu_maxWorkGroupSize;
|
||||
unsigned int gpu_maxComputeUnits;
|
||||
|
||||
cl::sycl::queue *cpu_queue;
|
||||
cl::sycl::device *cpu_device;
|
||||
cl::sycl::context cpu_context;
|
||||
|
||||
|
||||
public:
|
||||
inline cl::sycl::queue &getGPUQueue() { return *gpu_queue; }
|
||||
inline cl::sycl::device &getGPUDevice() { return *gpu_device; }
|
||||
inline cl::sycl::context &getGPUContext() { return gpu_context; }
|
||||
|
||||
inline cl::sycl::queue &getCPUQueue() { return *cpu_queue; }
|
||||
inline cl::sycl::device &getCPUDevice() { return *cpu_device; }
|
||||
inline cl::sycl::context &getCPUContext() { return cpu_context; }
|
||||
|
||||
inline unsigned int getGPUMaxWorkGroupSize() { return gpu_maxWorkGroupSize; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -131,7 +131,8 @@ namespace embree
|
||||
std::swap(a,b);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
+47
-15
@@ -23,8 +23,17 @@
|
||||
#include "../../include/embree3/rtcore_ray.h"
|
||||
using namespace embree;
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
namespace embree
|
||||
{
|
||||
extern cl::sycl::queue *global_gpu_queue;
|
||||
extern cl::sycl::device *global_gpu_device;
|
||||
};
|
||||
#endif
|
||||
|
||||
RTC_NAMESPACE_BEGIN;
|
||||
|
||||
|
||||
/* mutex to make API thread safe */
|
||||
static MutexSys g_mutex;
|
||||
|
||||
@@ -33,15 +42,38 @@ RTC_NAMESPACE_BEGIN;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewDevice);
|
||||
Lock<MutexSys> lock(g_mutex);
|
||||
Device* device = new Device(config);
|
||||
embree::Device* device = new embree::Device(config);
|
||||
return (RTCDevice) device->refInc();
|
||||
RTC_CATCH_END(nullptr);
|
||||
return (RTCDevice) nullptr;
|
||||
}
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
RTC_API RTCDevice rtcNewDeviceGPU(const char* config, void *device, void *queue)
|
||||
{
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewDevice);
|
||||
Lock<MutexSys> lock(g_mutex);
|
||||
|
||||
/* === must be done before the first new/delete === */
|
||||
global_gpu_queue = (cl::sycl::queue*)queue;
|
||||
global_gpu_device = (cl::sycl::device*)device;
|
||||
/* ================================================ */
|
||||
|
||||
std::string new_cfg(config);
|
||||
DeviceGPU* gpu_device = new DeviceGPU(new_cfg.c_str(),device,queue);
|
||||
|
||||
return (RTCDevice) gpu_device->refInc();
|
||||
RTC_CATCH_END(nullptr);
|
||||
return (RTCDevice) nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
RTC_API void rtcRetainDevice(RTCDevice hdevice)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcRetainDevice);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
@@ -52,7 +84,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API void rtcReleaseDevice(RTCDevice hdevice)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcReleaseDevice);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
@@ -63,7 +95,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API ssize_t rtcGetDeviceProperty(RTCDevice hdevice, RTCDeviceProperty prop)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcGetDeviceProperty);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
@@ -75,7 +107,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API void rtcSetDeviceProperty(RTCDevice hdevice, const RTCDeviceProperty prop, ssize_t val)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcSetDeviceProperty);
|
||||
const bool internal_prop = (size_t)prop >= 1000000 && (size_t)prop < 1000004;
|
||||
@@ -87,7 +119,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API RTCError rtcGetDeviceError(RTCDevice hdevice)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcGetDeviceError);
|
||||
if (device == nullptr) return Device::getThreadErrorCode();
|
||||
@@ -98,7 +130,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API void rtcSetDeviceErrorFunction(RTCDevice hdevice, RTCErrorFunction error, void* userPtr)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcSetDeviceErrorFunction);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
@@ -108,7 +140,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API void rtcSetDeviceMemoryMonitorFunction(RTCDevice hdevice, RTCMemoryMonitorFunction memoryMonitor, void* userPtr)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcSetDeviceMemoryMonitorFunction);
|
||||
device->setMemoryMonitorFunction(memoryMonitor, userPtr);
|
||||
@@ -120,9 +152,9 @@ RTC_NAMESPACE_BEGIN;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewBuffer);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
Buffer* buffer = new Buffer((Device*)hdevice, byteSize);
|
||||
Buffer* buffer = new Buffer((embree::Device*)hdevice, byteSize);
|
||||
return (RTCBuffer)buffer->refInc();
|
||||
RTC_CATCH_END((Device*)hdevice);
|
||||
RTC_CATCH_END((embree::Device*)hdevice);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -131,9 +163,9 @@ RTC_NAMESPACE_BEGIN;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewSharedBuffer);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
Buffer* buffer = new Buffer((Device*)hdevice, byteSize, ptr);
|
||||
Buffer* buffer = new Buffer((embree::Device*)hdevice, byteSize, ptr);
|
||||
return (RTCBuffer)buffer->refInc();
|
||||
RTC_CATCH_END((Device*)hdevice);
|
||||
RTC_CATCH_END((embree::Device*)hdevice);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -173,9 +205,9 @@ RTC_NAMESPACE_BEGIN;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewScene);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
Scene* scene = new Scene((Device*)hdevice);
|
||||
Scene* scene = new Scene((embree::Device*)hdevice);
|
||||
return (RTCScene) scene->refInc();
|
||||
RTC_CATCH_END((Device*)hdevice);
|
||||
RTC_CATCH_END((embree::Device*)hdevice);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1053,7 +1085,7 @@ RTC_NAMESPACE_BEGIN;
|
||||
|
||||
RTC_API RTCGeometry rtcNewGeometry (RTCDevice hdevice, RTCGeometryType type)
|
||||
{
|
||||
Device* device = (Device*) hdevice;
|
||||
embree::Device* device = (embree::Device*) hdevice;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewGeometry);
|
||||
RTC_VERIFY_HANDLE(hdevice);
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace embree
|
||||
__forceinline bool isCoherent (RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_COHERENT) == RTC_INTERSECT_CONTEXT_FLAG_COHERENT; }
|
||||
__forceinline bool isIncoherent(RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_COHERENT) == RTC_INTERSECT_CONTEXT_FLAG_INCOHERENT; }
|
||||
|
||||
__forceinline bool traceOnGPU(RTCIntersectContextFlags flags) { return (flags & RTC_INTERSECT_CONTEXT_FLAG_GPU) == RTC_INTERSECT_CONTEXT_FLAG_GPU; }
|
||||
|
||||
#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION_MAJOR >= 8)
|
||||
# define USE_TASK_ARENA 1
|
||||
#else
|
||||
@@ -53,16 +55,16 @@ namespace embree
|
||||
|
||||
#define RTC_CATCH_END2(scene) \
|
||||
} catch (std::bad_alloc&) { \
|
||||
Device* device = scene ? scene->device : nullptr; \
|
||||
embree::Device* device = scene ? scene->device : nullptr; \
|
||||
Device::process_error(device,RTC_ERROR_OUT_OF_MEMORY,"out of memory"); \
|
||||
} catch (rtcore_error& e) { \
|
||||
Device* device = scene ? scene->device : nullptr; \
|
||||
embree::Device* device = scene ? scene->device : nullptr; \
|
||||
Device::process_error(device,e.error,e.what()); \
|
||||
} catch (std::exception& e) { \
|
||||
Device* device = scene ? scene->device : nullptr; \
|
||||
embree::Device* device = scene ? scene->device : nullptr; \
|
||||
Device::process_error(device,RTC_ERROR_UNKNOWN,e.what()); \
|
||||
} catch (...) { \
|
||||
Device* device = scene ? scene->device : nullptr; \
|
||||
embree::Device* device = scene ? scene->device : nullptr; \
|
||||
Device::process_error(device,RTC_ERROR_UNKNOWN,"unknown exception caught"); \
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace embree
|
||||
{
|
||||
struct BVH : public RefCount
|
||||
{
|
||||
BVH (Device* device)
|
||||
BVH (embree::Device* device)
|
||||
: device(device), allocator(device,true), morton_src(device,0), morton_tmp(device,0)
|
||||
{
|
||||
device->refInc();
|
||||
@@ -42,7 +42,7 @@ namespace embree
|
||||
}
|
||||
|
||||
public:
|
||||
Device* device;
|
||||
embree::Device* device;
|
||||
FastAllocator allocator;
|
||||
mvector<BVHBuilderMorton::BuildPrim> morton_src;
|
||||
mvector<BVHBuilderMorton::BuildPrim> morton_tmp;
|
||||
@@ -359,9 +359,9 @@ RTC_NAMESPACE_BEGIN
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcNewAllocator);
|
||||
RTC_VERIFY_HANDLE(device);
|
||||
BVH* bvh = new BVH((Device*)device);
|
||||
BVH* bvh = new BVH((embree::Device*)device);
|
||||
return (RTCBVH) bvh->refInc();
|
||||
RTC_CATCH_END((Device*)device);
|
||||
RTC_CATCH_END((embree::Device*)device);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ RTC_NAMESPACE_BEGIN
|
||||
RTC_API void rtcRetainBVH(RTCBVH hbvh)
|
||||
{
|
||||
BVH* bvh = (BVH*) hbvh;
|
||||
Device* device = bvh ? bvh->device : nullptr;
|
||||
embree::Device* device = bvh ? bvh->device : nullptr;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcRetainBVH);
|
||||
RTC_VERIFY_HANDLE(hbvh);
|
||||
@@ -444,7 +444,7 @@ RTC_NAMESPACE_BEGIN
|
||||
RTC_API void rtcReleaseBVH(RTCBVH hbvh)
|
||||
{
|
||||
BVH* bvh = (BVH*) hbvh;
|
||||
Device* device = bvh ? bvh->device : nullptr;
|
||||
embree::Device* device = bvh ? bvh->device : nullptr;
|
||||
RTC_CATCH_BEGIN;
|
||||
RTC_TRACE(rtcReleaseBVH);
|
||||
RTC_VERIFY_HANDLE(hbvh);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "../bvh/bvh4_factory.h"
|
||||
#include "../bvh/bvh8_factory.h"
|
||||
#include "../bvh/bvh_gpu_factory.h"
|
||||
#include "../../common/algorithms/parallel_reduce.h"
|
||||
|
||||
namespace embree
|
||||
@@ -51,7 +52,7 @@ namespace embree
|
||||
#endif
|
||||
|
||||
intersectors = Accel::Intersectors(missing_rtcCommit);
|
||||
|
||||
|
||||
/* one can overwrite flags through device for debugging */
|
||||
if (device->quality_flags != -1)
|
||||
quality_flags = (RTCBuildQuality) device->quality_flags;
|
||||
@@ -124,10 +125,26 @@ namespace embree
|
||||
void Scene::createTriangleAccel()
|
||||
{
|
||||
#if defined(EMBREE_GEOMETRY_TRIANGLE)
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (device->tri_accel == "bvhgpu.triangle1v") {
|
||||
switch(device->quality_flags)
|
||||
{
|
||||
case RTC_BUILD_QUALITY_HIGH:
|
||||
accels_add(device->bvh_gpu_factory->BVHGPUTriangle1v(this,BVHFactory::BuildVariant::HIGH_QUALITY));
|
||||
break;
|
||||
default:
|
||||
accels_add(device->bvh_gpu_factory->BVHGPUTriangle1v(this,BVHFactory::BuildVariant::STATIC));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (device->tri_accel == "default")
|
||||
{
|
||||
if (quality_flags != RTC_BUILD_QUALITY_LOW)
|
||||
{
|
||||
{
|
||||
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
||||
switch (mode) {
|
||||
case /*0b00*/ 0:
|
||||
@@ -202,11 +219,18 @@ namespace embree
|
||||
#endif
|
||||
else throw_RTCError(RTC_ERROR_INVALID_ARGUMENT,"unknown triangle acceleration structure "+device->tri_accel);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void Scene::createTriangleMBAccel()
|
||||
{
|
||||
#if defined(EMBREE_GEOMETRY_TRIANGLE)
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (device->tri_accel_mb == "bvhgpu.triangle1vmb") {
|
||||
accels_add(device->bvh_gpu_factory->BVHGPUTriangle1vMB(this));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (device->tri_accel_mb == "default")
|
||||
{
|
||||
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
||||
@@ -245,6 +269,22 @@ namespace embree
|
||||
void Scene::createQuadAccel()
|
||||
{
|
||||
#if defined(EMBREE_GEOMETRY_QUAD)
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (device->quad_accel == "bvhgpu.quad1v") {
|
||||
switch(device->quality_flags)
|
||||
{
|
||||
case RTC_BUILD_QUALITY_HIGH:
|
||||
accels_add(device->bvh_gpu_factory->BVHGPUQuad1v(this,BVHFactory::BuildVariant::HIGH_QUALITY));
|
||||
break;
|
||||
default:
|
||||
accels_add(device->bvh_gpu_factory->BVHGPUQuad1v(this,BVHFactory::BuildVariant::STATIC));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (device->quad_accel == "default")
|
||||
{
|
||||
if (quality_flags != RTC_BUILD_QUALITY_LOW)
|
||||
@@ -326,6 +366,12 @@ namespace embree
|
||||
void Scene::createQuadMBAccel()
|
||||
{
|
||||
#if defined(EMBREE_GEOMETRY_QUAD)
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (device->tri_accel_mb == "bvhgpu.quad1vmb") {
|
||||
accels_add(device->bvh_gpu_factory->BVHGPUTriangle1vMB(this));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (device->quad_accel_mb == "default")
|
||||
{
|
||||
int mode = 2*(int)isCompactAccel() + 1*(int)isRobustAccel();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace embree
|
||||
/*! Base class all scenes are derived from */
|
||||
class Scene : public AccelN
|
||||
{
|
||||
ALIGNED_CLASS_(16);
|
||||
ALIGNED_CLASS_USM_(16); // FIXME
|
||||
|
||||
public:
|
||||
template<typename Ty, bool mblur = false>
|
||||
@@ -151,8 +151,9 @@ namespace embree
|
||||
|
||||
/*! Scene destruction */
|
||||
~Scene ();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*! class is non-copyable */
|
||||
Scene (const Scene& other) DELETED; // do not implement
|
||||
Scene& operator= (const Scene& other) DELETED; // do not implement
|
||||
|
||||
@@ -164,13 +164,17 @@ namespace embree
|
||||
{
|
||||
const unsigned int index = segment(i);
|
||||
if (index+1 >= numVertices()) return false;
|
||||
|
||||
|
||||
#if !defined(EMBREE_SYCL_SIMD_LIBRARY) && !defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
|
||||
{
|
||||
const Vec3fa v0 = vertex(index+0,itime); if (unlikely(!isvalid((vfloat4)v0))) return false;
|
||||
const Vec3fa v1 = vertex(index+1,itime); if (unlikely(!isvalid((vfloat4)v1))) return false;
|
||||
if (min(v0.w,v1.w) < 0.0f) return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,8 +156,10 @@ namespace embree
|
||||
|
||||
for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) {
|
||||
const Vec3fa v0 = vertex(index + 0, itime);
|
||||
#if !defined(EMBREE_SYCL_SIMD_LIBRARY) && !defined(__SYCL_DEVICE_ONLY__)
|
||||
if (unlikely(!isvalid((vfloat4)v0)))
|
||||
return false;
|
||||
#endif
|
||||
if (v0.w < 0.0f)
|
||||
return false;
|
||||
}
|
||||
|
||||
+55
-5
@@ -16,6 +16,13 @@
|
||||
|
||||
#include "default.h"
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#define CL_TARGET_OPENCL_VERSION 220
|
||||
#define SYCL_SIMPLE_SWIZZLES
|
||||
#include <CL/sycl.hpp>
|
||||
#include <CL/sycl/builtins.hpp>
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! invokes the memory monitor callback */
|
||||
@@ -36,7 +43,7 @@ namespace embree
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
__forceinline aligned_monitored_allocator(MemoryMonitorInterface* device)
|
||||
: device(device), hugepages(false) {}
|
||||
: device(device), hugepages(false), useUSM(false) {}
|
||||
|
||||
__forceinline pointer allocate( size_type n )
|
||||
{
|
||||
@@ -44,6 +51,14 @@ namespace embree
|
||||
assert(device);
|
||||
device->memoryMonitor(n*sizeof(T),false);
|
||||
}
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (useUSM)
|
||||
{
|
||||
pointer p = (pointer)cl::sycl::aligned_alloc(alignment,n*sizeof(value_type),*gpu_device,*gpu_context,cl::sycl::usm::alloc::shared);
|
||||
assert(p);
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
|
||||
{
|
||||
pointer p = (pointer) os_malloc(n*sizeof(value_type),hugepages);
|
||||
@@ -57,10 +72,19 @@ namespace embree
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
|
||||
os_free(p,n*sizeof(value_type),hugepages);
|
||||
else
|
||||
alignedFree(p);
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
if (useUSM)
|
||||
{
|
||||
cl::sycl::free(p,*gpu_context);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (n*sizeof(value_type) >= 14 * PAGE_SIZE_2M)
|
||||
os_free(p,n*sizeof(value_type),hugepages);
|
||||
else
|
||||
alignedFree(p);
|
||||
}
|
||||
}
|
||||
else assert(n == 0);
|
||||
|
||||
@@ -78,9 +102,35 @@ namespace embree
|
||||
p->~T();
|
||||
}
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
__forceinline void enableUSM(cl::sycl::device *gpu_device,
|
||||
cl::sycl::context *gpu_context)
|
||||
{
|
||||
useUSM = true;
|
||||
assert(gpu_device);
|
||||
assert(gpu_context);
|
||||
this->gpu_device = gpu_device;
|
||||
this->gpu_context = gpu_context;
|
||||
}
|
||||
|
||||
__forceinline void disableUSM()
|
||||
{
|
||||
useUSM = false;
|
||||
gpu_device = nullptr;
|
||||
gpu_context = nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
private:
|
||||
MemoryMonitorInterface* device;
|
||||
bool hugepages;
|
||||
bool useUSM;
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
cl::sycl::device *gpu_device;
|
||||
cl::sycl::context *gpu_context;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*! monitored vector */
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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. //
|
||||
// ======================================================================== //
|
||||
|
||||
#include "primitive.h"
|
||||
#include "triangle1v.h"
|
||||
#include "quad1v.h"
|
||||
#include "triangle1vmb.h"
|
||||
#include "quad1vmb.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
|
||||
/********************** Triangle1v **************************/
|
||||
Triangle1v::Type Triangle1v::type;
|
||||
|
||||
const char* Triangle1v::Type::name () const {
|
||||
return "triangle1v";
|
||||
}
|
||||
|
||||
size_t Triangle1v::Type::sizeActive(const char* This) const {
|
||||
return ((Triangle1v*)This)->size();
|
||||
}
|
||||
|
||||
size_t Triangle1v::Type::sizeTotal(const char* This) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t Triangle1v::Type::getBytes(const char* This) const {
|
||||
return sizeof(Triangle1v);
|
||||
}
|
||||
|
||||
/********************** Quad1v **************************/
|
||||
Quad1v::Type Quad1v::type;
|
||||
|
||||
const char* Quad1v::Type::name () const {
|
||||
return "quad1v";
|
||||
}
|
||||
|
||||
size_t Quad1v::Type::sizeActive(const char* This) const {
|
||||
return ((Quad1v*)This)->size();
|
||||
}
|
||||
|
||||
size_t Quad1v::Type::sizeTotal(const char* This) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t Quad1v::Type::getBytes(const char* This) const {
|
||||
return sizeof(Quad1v);
|
||||
}
|
||||
|
||||
|
||||
/********************** Triangle1vMB **************************/
|
||||
Triangle1vMB::Type Triangle1vMB::type;
|
||||
|
||||
const char* Triangle1vMB::Type::name () const {
|
||||
return "triangle1vMB";
|
||||
}
|
||||
|
||||
size_t Triangle1vMB::Type::sizeActive(const char* This) const {
|
||||
return ((Triangle1vMB*)This)->size();
|
||||
}
|
||||
|
||||
size_t Triangle1vMB::Type::sizeTotal(const char* This) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t Triangle1vMB::Type::getBytes(const char* This) const {
|
||||
return sizeof(Triangle1vMB);
|
||||
}
|
||||
|
||||
/********************** Quad1vMB **************************/
|
||||
Quad1vMB::Type Quad1vMB::type;
|
||||
|
||||
const char* Quad1vMB::Type::name () const {
|
||||
return "quad1vMB";
|
||||
}
|
||||
|
||||
size_t Quad1vMB::Type::sizeActive(const char* This) const {
|
||||
return ((Quad1vMB*)This)->size();
|
||||
}
|
||||
|
||||
size_t Quad1vMB::Type::sizeTotal(const char* This) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t Quad1vMB::Type::getBytes(const char* This) const {
|
||||
return sizeof(Quad1vMB);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "primitive.h"
|
||||
#include "../common/scene_quad_mesh.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* Stores the vertices of M quads in struct of array layout */
|
||||
struct Quad1v
|
||||
{
|
||||
public:
|
||||
struct Type : public PrimitiveType
|
||||
{
|
||||
const char* name() const;
|
||||
size_t sizeActive(const char* This) const;
|
||||
size_t sizeTotal(const char* This) const;
|
||||
size_t getBytes(const char* This) const;
|
||||
};
|
||||
static Type type;
|
||||
|
||||
public:
|
||||
|
||||
/* Returns maximum number of stored quads */
|
||||
static __forceinline size_t max_size() { return 1; }
|
||||
|
||||
/* Returns required number of primitive blocks for N primitives */
|
||||
static __forceinline size_t blocks(size_t N) { return 1; }
|
||||
|
||||
public:
|
||||
|
||||
/* Default constructor */
|
||||
__forceinline Quad1v() {}
|
||||
|
||||
/* Construction from vertices and IDs */
|
||||
__forceinline Quad1v(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, const unsigned int geomID, const unsigned int primID)
|
||||
: v0(v0), v2(v2), v1(v1), geomId(geomID), v3(v3), primId(primID) {}
|
||||
|
||||
/* Returns a mask that tells which quads are valid */
|
||||
__forceinline bool valid() const { return geomId != -1; }
|
||||
|
||||
/* Returns true if the specified quad is valid */
|
||||
__forceinline bool valid(const size_t i) const { return geomId != -1; }
|
||||
|
||||
/* Returns the number of stored quads */
|
||||
__forceinline size_t size() const { return 1; }
|
||||
|
||||
/* Returns the geometry ID */
|
||||
__forceinline unsigned int& geomID() { return geomId; }
|
||||
__forceinline const unsigned int& geomID() const { return geomId; }
|
||||
__forceinline unsigned int geomID(const size_t i) const { return geomId; }
|
||||
|
||||
/* Returns the primitive ID0 */
|
||||
__forceinline unsigned int& primID() { return primId; }
|
||||
__forceinline const unsigned int& primID() const { return primId; }
|
||||
__forceinline unsigned int primID(const size_t i) const { return primId; }
|
||||
|
||||
/* Calculate the bounds of the quads */
|
||||
__forceinline BBox3fa bounds() const
|
||||
{
|
||||
Vec3fa lower = (Vec3fa)min(v0,v1,v2,v3);
|
||||
Vec3fa upper = (Vec3fa)max(v0,v1,v2,v3);
|
||||
return BBox3fa(lower,upper);
|
||||
}
|
||||
|
||||
/* Fill quad from quad list */
|
||||
__forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
|
||||
{
|
||||
assert(end-begin==1);
|
||||
const PrimRef& prim = *prims;
|
||||
geomId = prim.geomID();
|
||||
primId = prim.primID();
|
||||
const QuadMesh* __restrict__ const mesh = scene->get<QuadMesh>(geomId);
|
||||
const QuadMesh::Quad& quad = mesh->quad(primId);
|
||||
v0 = mesh->vertex(quad.v[0]);
|
||||
v1 = mesh->vertex(quad.v[1]);
|
||||
v2 = mesh->vertex(quad.v[2]);
|
||||
v3 = mesh->vertex(quad.v[3]);
|
||||
}
|
||||
|
||||
/* Updates the primitive */
|
||||
__forceinline BBox3fa update(QuadMesh* mesh)
|
||||
{
|
||||
const QuadMesh::Quad& quad = mesh->quad(primId);
|
||||
v0 = mesh->vertex(quad.v[0]);
|
||||
v1 = mesh->vertex(quad.v[1]);
|
||||
v2 = mesh->vertex(quad.v[2]);
|
||||
v3 = mesh->vertex(quad.v[3]);
|
||||
return bounds();
|
||||
}
|
||||
|
||||
__forceinline void init(unsigned int geomID,
|
||||
unsigned int primID,
|
||||
const Scene *const scene)
|
||||
{
|
||||
QuadMesh* mesh = (QuadMesh*)scene->get(geomID);
|
||||
const QuadMesh::Quad &q = mesh->quad(primID);
|
||||
v0 = mesh->vertex(q.v[0]);
|
||||
v1 = mesh->vertex(q.v[1]);
|
||||
v2 = mesh->vertex(q.v[2]);
|
||||
v3 = mesh->vertex(q.v[3]);
|
||||
unused0 = 0;
|
||||
unused1 = 0;
|
||||
geomId = geomID;
|
||||
primId = primID;
|
||||
}
|
||||
|
||||
public:
|
||||
Vec3f v0; // 1st vertex of the quad
|
||||
unsigned int unused0; // unused
|
||||
Vec3f v2; // 3rd vertex of the quad
|
||||
unsigned int unused1; // unused
|
||||
Vec3f v1; // 2nd vertex of the quad
|
||||
unsigned int geomId; // geometry ID
|
||||
Vec3f v3; // 4nd vertex of the quad
|
||||
unsigned int primId; // primitive ID
|
||||
};
|
||||
|
||||
//typename Quad1v::Type Quad1v::type;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "primitive.h"
|
||||
#include "../common/scene_quad_mesh.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* Stores the vertices of M quads in struct of array layout */
|
||||
struct Quad1vMB
|
||||
{
|
||||
public:
|
||||
struct Type : public PrimitiveType
|
||||
{
|
||||
const char* name() const;
|
||||
size_t sizeActive(const char* This) const;
|
||||
size_t sizeTotal(const char* This) const;
|
||||
size_t getBytes(const char* This) const;
|
||||
};
|
||||
static Type type;
|
||||
|
||||
public:
|
||||
|
||||
/* Returns maximum number of stored quads */
|
||||
static __forceinline size_t max_size() { return 1; }
|
||||
|
||||
/* Returns required number of primitive blocks for N primitives */
|
||||
static __forceinline size_t blocks(size_t N) { return 1; }
|
||||
|
||||
public:
|
||||
|
||||
/* Default constructor */
|
||||
__forceinline Quad1vMB() {}
|
||||
|
||||
/* Construction from vertices and IDs */
|
||||
__forceinline Quad1vMB(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, const unsigned int geomID, const unsigned int primID)
|
||||
: v0(v0), v2(v2), v1(v1), geomId(geomID), v3(v3), primId(primID) {}
|
||||
|
||||
/* Returns a mask that tells which quads are valid */
|
||||
__forceinline bool valid() const { return geomId != -1; }
|
||||
|
||||
/* Returns true if the specified quad is valid */
|
||||
__forceinline bool valid(const size_t i) const { return geomId != -1; }
|
||||
|
||||
/* Returns the number of stored quads */
|
||||
__forceinline size_t size() const { return 1; }
|
||||
|
||||
/* Returns the geometry ID */
|
||||
__forceinline unsigned int& geomID() { return geomId; }
|
||||
__forceinline const unsigned int& geomID() const { return geomId; }
|
||||
__forceinline unsigned int geomID(const size_t i) const { return geomId; }
|
||||
|
||||
/* Returns the primitive ID0 */
|
||||
__forceinline unsigned int& primID() { return primId; }
|
||||
__forceinline const unsigned int& primID() const { return primId; }
|
||||
__forceinline unsigned int primID(const size_t i) const { return primId; }
|
||||
|
||||
/* Calculate the bounds of the quads */
|
||||
__forceinline BBox3fa bounds() const
|
||||
{
|
||||
Vec3fa lower = (Vec3fa)min(v0,v1,v2,v3);
|
||||
Vec3fa upper = (Vec3fa)max(v0,v1,v2,v3);
|
||||
return BBox3fa(lower,upper);
|
||||
}
|
||||
|
||||
/* Fill quad from quad list */
|
||||
__forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
|
||||
{
|
||||
assert(end-begin==1);
|
||||
const PrimRef& prim = *prims;
|
||||
geomId = prim.geomID();
|
||||
primId = prim.primID();
|
||||
const QuadMesh* __restrict__ const mesh = scene->get<QuadMesh>(geomId);
|
||||
const QuadMesh::Quad& quad = mesh->quad(primId);
|
||||
v0 = mesh->vertex(quad.v[0]);
|
||||
v1 = mesh->vertex(quad.v[1]);
|
||||
v2 = mesh->vertex(quad.v[2]);
|
||||
v3 = mesh->vertex(quad.v[3]);
|
||||
}
|
||||
|
||||
/* Updates the primitive */
|
||||
__forceinline BBox3fa update(QuadMesh* mesh)
|
||||
{
|
||||
const QuadMesh::Quad& quad = mesh->quad(primId);
|
||||
v0 = mesh->vertex(quad.v[0]);
|
||||
v1 = mesh->vertex(quad.v[1]);
|
||||
v2 = mesh->vertex(quad.v[2]);
|
||||
v3 = mesh->vertex(quad.v[3]);
|
||||
return bounds();
|
||||
}
|
||||
|
||||
__forceinline void init(unsigned int geomID,
|
||||
unsigned int primID,
|
||||
const Scene *const scene)
|
||||
{
|
||||
QuadMesh* mesh = (QuadMesh*)scene->get(geomID);
|
||||
const QuadMesh::Quad &q = mesh->quad(primID);
|
||||
v0 = mesh->vertex(q.v[0]);
|
||||
v1 = mesh->vertex(q.v[1]);
|
||||
v2 = mesh->vertex(q.v[2]);
|
||||
v3 = mesh->vertex(q.v[3]);
|
||||
unused0 = 0;
|
||||
unused1 = 0;
|
||||
geomId = geomID;
|
||||
primId = primID;
|
||||
}
|
||||
|
||||
public:
|
||||
Vec3f v0; // 1st vertex of the quad
|
||||
unsigned int unused0; // unused
|
||||
Vec3f v2; // 3rd vertex of the quad
|
||||
unsigned int unused1; // unused
|
||||
Vec3f v1; // 2nd vertex of the quad
|
||||
unsigned int geomId; // geometry ID
|
||||
Vec3f v3; // 4nd vertex of the quad
|
||||
unsigned int primId; // primitive ID
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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 "primitive.h"
|
||||
#include "../common/scene_triangle_mesh.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* Stores the vertices of M triangles in struct of array layout */
|
||||
struct Triangle1v
|
||||
{
|
||||
public:
|
||||
struct Type : public PrimitiveType
|
||||
{
|
||||
const char* name() const;
|
||||
size_t sizeActive(const char* This) const;
|
||||
size_t sizeTotal(const char* This) const;
|
||||
size_t getBytes(const char* This) const;
|
||||
};
|
||||
static Type type;
|
||||
|
||||
public:
|
||||
|
||||
/* Returns maximum number of stored triangles */
|
||||
static __forceinline size_t max_size() { return 1; }
|
||||
|
||||
/* Returns required number of primitive blocks for N primitives */
|
||||
static __forceinline size_t blocks(size_t N) { return 1; }
|
||||
|
||||
public:
|
||||
|
||||
/* Default constructor */
|
||||
__forceinline Triangle1v() {}
|
||||
|
||||
/* Construction from vertices and IDs */
|
||||
__forceinline Triangle1v(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const unsigned int geomID, const unsigned int primID)
|
||||
: v0(v0), v1(v1), v2(v2), geomId(geomID), primId(primID) {}
|
||||
|
||||
/* Returns a mask that tells which triangles are valid */
|
||||
__forceinline bool valid() const { return geomId != -1; }
|
||||
|
||||
/* Returns true if the specified triangle is valid */
|
||||
__forceinline bool valid(const size_t i) const { return geomId != -1; }
|
||||
|
||||
/* Returns the number of stored triangles */
|
||||
__forceinline size_t size() const { return 1; }
|
||||
|
||||
/* Returns the geometry ID */
|
||||
__forceinline unsigned int& geomID() { return geomId; }
|
||||
__forceinline const unsigned int& geomID() const { return geomId; }
|
||||
__forceinline unsigned int geomID(const size_t i) const { return geomId; }
|
||||
|
||||
/* Returns the primitive ID */
|
||||
__forceinline unsigned int& primID() { return primId; }
|
||||
__forceinline const unsigned int& primID() const { return primId; }
|
||||
__forceinline unsigned int primID(const size_t i) const { return primId; }
|
||||
|
||||
/* Calculate the bounds of the triangles */
|
||||
__forceinline BBox3fa bounds() const
|
||||
{
|
||||
Vec3fa lower = (Vec3fa)min(v0,v1,v2);
|
||||
Vec3fa upper = (Vec3fa)max(v0,v1,v2);
|
||||
return BBox3fa(lower,upper);
|
||||
}
|
||||
|
||||
/* Fill triangle from triangle list */
|
||||
__forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
|
||||
{
|
||||
assert(end-begin==1);
|
||||
const PrimRef& prim = *prims;
|
||||
geomId = prim.geomID();
|
||||
primId = prim.primID();
|
||||
const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomId);
|
||||
const TriangleMesh::Triangle& tri = mesh->triangle(primId);
|
||||
v0 = mesh->vertex(tri.v[0]);
|
||||
v1 = mesh->vertex(tri.v[1]);
|
||||
v2 = mesh->vertex(tri.v[2]);
|
||||
}
|
||||
|
||||
/* Updates the primitive */
|
||||
__forceinline BBox3fa update(TriangleMesh* mesh)
|
||||
{
|
||||
const TriangleMesh::Triangle& tri = mesh->triangle(primId);
|
||||
v0 = mesh->vertex(tri.v[0]);
|
||||
v1 = mesh->vertex(tri.v[1]);
|
||||
v2 = mesh->vertex(tri.v[2]);
|
||||
return bounds();
|
||||
}
|
||||
|
||||
__forceinline void init(unsigned int geomID,
|
||||
unsigned int primID,
|
||||
const Scene *const scene)
|
||||
{
|
||||
TriangleMesh* mesh = (TriangleMesh*)scene->get(geomID);
|
||||
const TriangleMesh::Triangle &tri = mesh->triangle(primID);
|
||||
v0 = mesh->vertex(tri.v[0]);
|
||||
v1 = mesh->vertex(tri.v[1]);
|
||||
v2 = mesh->vertex(tri.v[2]);
|
||||
unused = 0;
|
||||
geomId = geomID;
|
||||
primId = primID;
|
||||
}
|
||||
|
||||
public:
|
||||
Vec3f v0; // 1st vertex of the triangle
|
||||
unsigned int unused; // unused
|
||||
Vec3f v1; // 2nd vertex of the triangle
|
||||
unsigned int geomId; // geometry ID
|
||||
Vec3f v2; // 3rd vertex of the triangle
|
||||
unsigned int primId; // primitive ID
|
||||
};
|
||||
|
||||
//typename Triangle1v::Type Triangle1v::type;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2018 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 "primitive.h"
|
||||
#include "../common/scene_triangle_mesh.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* Stores the vertices of M triangles in struct of array layout */
|
||||
struct Triangle1vMB
|
||||
{
|
||||
public:
|
||||
struct Type : public PrimitiveType
|
||||
{
|
||||
const char* name() const;
|
||||
size_t sizeActive(const char* This) const;
|
||||
size_t sizeTotal(const char* This) const;
|
||||
size_t getBytes(const char* This) const;
|
||||
};
|
||||
static Type type;
|
||||
|
||||
public:
|
||||
|
||||
/* Returns maximum number of stored triangles */
|
||||
static __forceinline size_t max_size() { return 1; }
|
||||
|
||||
/* Returns required number of primitive blocks for N primitives */
|
||||
static __forceinline size_t blocks(size_t N) { return 1; }
|
||||
|
||||
public:
|
||||
|
||||
/* Default constructor */
|
||||
__forceinline Triangle1vMB() {}
|
||||
|
||||
/* Construction from vertices and IDs */
|
||||
__forceinline Triangle1vMB(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const unsigned int geomID, const unsigned int primID)
|
||||
: v0(v0), v1(v1), v2(v2), geomId(geomID), primId(primID) {}
|
||||
|
||||
/* Returns a mask that tells which triangles are valid */
|
||||
__forceinline bool valid() const { return geomId != -1; }
|
||||
|
||||
/* Returns true if the specified triangle is valid */
|
||||
__forceinline bool valid(const size_t i) const { return geomId != -1; }
|
||||
|
||||
/* Returns the number of stored triangles */
|
||||
__forceinline size_t size() const { return 1; }
|
||||
|
||||
/* Returns the geometry ID */
|
||||
__forceinline unsigned int& geomID() { return geomId; }
|
||||
__forceinline const unsigned int& geomID() const { return geomId; }
|
||||
__forceinline unsigned int geomID(const size_t i) const { return geomId; }
|
||||
|
||||
/* Returns the primitive ID */
|
||||
__forceinline unsigned int& primID() { return primId; }
|
||||
__forceinline const unsigned int& primID() const { return primId; }
|
||||
__forceinline unsigned int primID(const size_t i) const { return primId; }
|
||||
|
||||
/* Calculate the bounds of the triangles */
|
||||
__forceinline BBox3fa bounds() const
|
||||
{
|
||||
Vec3fa lower = (Vec3fa)min(v0,v1,v2);
|
||||
Vec3fa upper = (Vec3fa)max(v0,v1,v2);
|
||||
return BBox3fa(lower,upper);
|
||||
}
|
||||
|
||||
/* Fill triangle from triangle list */
|
||||
__forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene)
|
||||
{
|
||||
assert(end-begin==1);
|
||||
const PrimRef& prim = *prims;
|
||||
geomId = prim.geomID();
|
||||
primId = prim.primID();
|
||||
const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(geomId);
|
||||
const TriangleMesh::Triangle& tri = mesh->triangle(primId);
|
||||
v0 = mesh->vertex(tri.v[0]);
|
||||
v1 = mesh->vertex(tri.v[1]);
|
||||
v2 = mesh->vertex(tri.v[2]);
|
||||
}
|
||||
|
||||
/* Updates the primitive */
|
||||
__forceinline BBox3fa update(TriangleMesh* mesh)
|
||||
{
|
||||
const TriangleMesh::Triangle& tri = mesh->triangle(primId);
|
||||
v0 = mesh->vertex(tri.v[0]);
|
||||
v1 = mesh->vertex(tri.v[1]);
|
||||
v2 = mesh->vertex(tri.v[2]);
|
||||
return bounds();
|
||||
}
|
||||
|
||||
__forceinline void init(unsigned int geomID,
|
||||
unsigned int primID,
|
||||
const Scene *const scene)
|
||||
{
|
||||
TriangleMesh* mesh = (TriangleMesh*)scene->get(geomID);
|
||||
const TriangleMesh::Triangle &tri = mesh->triangle(primID);
|
||||
v0 = mesh->vertex(tri.v[0]);
|
||||
v1 = mesh->vertex(tri.v[1]);
|
||||
v2 = mesh->vertex(tri.v[2]);
|
||||
unused = 0;
|
||||
geomId = geomID;
|
||||
primId = primID;
|
||||
}
|
||||
|
||||
public:
|
||||
Vec3f v0; // 1st vertex of the triangle
|
||||
unsigned int unused; // unused
|
||||
Vec3f v1; // 2nd vertex of the triangle
|
||||
unsigned int geomId; // geometry ID
|
||||
Vec3f v2; // 3rd vertex of the triangle
|
||||
unsigned int primId; // primitive ID
|
||||
Vec3f v0_delta;
|
||||
float time0;
|
||||
Vec3f v1_delta;
|
||||
float time1;
|
||||
Vec3f v2_delta;
|
||||
float reserved;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -206,6 +206,18 @@ namespace embree
|
||||
const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
|
||||
const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
|
||||
const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
|
||||
PRINT(tri.v0);
|
||||
PRINT(tri.v1);
|
||||
PRINT(tri.v2);
|
||||
|
||||
PRINT(tri.dv0);
|
||||
PRINT(tri.dv1);
|
||||
PRINT(tri.dv2);
|
||||
|
||||
PRINT(v0);
|
||||
PRINT(v1);
|
||||
PRINT(v2);
|
||||
|
||||
pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Intersect1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
|
||||
}
|
||||
|
||||
@@ -216,7 +228,7 @@ namespace embree
|
||||
const Vec3vf<Mx> time(ray.time()[k]);
|
||||
const Vec3vf<Mx> v0 = madd(time,Vec3vf<Mx>(tri.dv0),Vec3vf<Mx>(tri.v0));
|
||||
const Vec3vf<Mx> v1 = madd(time,Vec3vf<Mx>(tri.dv1),Vec3vf<Mx>(tri.v1));
|
||||
const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
|
||||
const Vec3vf<Mx> v2 = madd(time,Vec3vf<Mx>(tri.dv2),Vec3vf<Mx>(tri.v2));
|
||||
return pre.intersect(ray,k,v0,v1,v2,UVIdentity<Mx>(),Occluded1KEpilogM<M,Mx,K,filter>(ray,k,context,tri.geomID(),tri.primID()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
#include "../gpu/common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
class __aligned(16) AABB {
|
||||
public:
|
||||
float4 lower;
|
||||
float4 upper;
|
||||
|
||||
AABB() = default;
|
||||
|
||||
AABB(const AABB &aabb) : lower(aabb.lower),upper(aabb.upper) {}
|
||||
|
||||
AABB(const float4 &v) : lower(v),upper(v) {}
|
||||
|
||||
__forceinline AABB(const float4 &lower, const float4 &upper) : lower(lower),upper(upper) {}
|
||||
|
||||
__forceinline void init()
|
||||
{
|
||||
const float pos_inf = INFINITY;
|
||||
const float neg_inf = -INFINITY;
|
||||
lower = float4(pos_inf,pos_inf,pos_inf,0.0f);
|
||||
upper = float4(neg_inf,neg_inf,neg_inf,0.0f);
|
||||
}
|
||||
|
||||
__forceinline void extend(const AABB &aabb)
|
||||
{
|
||||
lower = min(lower,aabb.lower);
|
||||
upper = max(upper,aabb.upper);
|
||||
}
|
||||
|
||||
__forceinline void extend(const float4 &v)
|
||||
{
|
||||
lower = min(lower,v);
|
||||
upper = max(upper,v);
|
||||
}
|
||||
|
||||
__forceinline void enlarge(const float4 &v)
|
||||
{
|
||||
lower -= v;
|
||||
upper += v;
|
||||
}
|
||||
|
||||
__forceinline float4 size() const
|
||||
{
|
||||
return upper - lower;
|
||||
}
|
||||
|
||||
__forceinline float4 centroid2() const
|
||||
{
|
||||
return upper + lower;
|
||||
}
|
||||
|
||||
__forceinline void atomic_merge_global(AABB &dest) const
|
||||
{
|
||||
atomic_min(((volatile GLOBAL float *)&dest) + 0,lower.x());
|
||||
atomic_min(((volatile GLOBAL float *)&dest) + 1,lower.y());
|
||||
atomic_min(((volatile GLOBAL float *)&dest) + 2,lower.z());
|
||||
|
||||
atomic_max(((volatile GLOBAL float *)&dest) + 4,upper.x());
|
||||
atomic_max(((volatile GLOBAL float *)&dest) + 5,upper.y());
|
||||
atomic_max(((volatile GLOBAL float *)&dest) + 6,upper.z());
|
||||
}
|
||||
|
||||
__forceinline void atomic_merge_local(AABB &dest) const
|
||||
{
|
||||
atomic_min(((volatile LOCAL float *)&dest) + 0,lower.x());
|
||||
atomic_min(((volatile LOCAL float *)&dest) + 1,lower.y());
|
||||
atomic_min(((volatile LOCAL float *)&dest) + 2,lower.z());
|
||||
|
||||
atomic_max(((volatile LOCAL float *)&dest) + 4,upper.x());
|
||||
atomic_max(((volatile LOCAL float *)&dest) + 5,upper.y());
|
||||
atomic_max(((volatile LOCAL float *)&dest) + 6,upper.z());
|
||||
}
|
||||
|
||||
__forceinline AABB sub_group_reduce(const cl::sycl::intel::sub_group& sg) const
|
||||
{
|
||||
AABB result;
|
||||
result.lower.x() = sg.reduce<float>(lower.x(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.y() = sg.reduce<float>(lower.y(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.z() = sg.reduce<float>(lower.z(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.w() = 0.0f;
|
||||
result.upper.x() = sg.reduce<float>(upper.x(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.y() = sg.reduce<float>(upper.y(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.z() = sg.reduce<float>(upper.z(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.w() = 0.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB sub_group_shuffle(const cl::sycl::intel::sub_group& sg, const cl::sycl::id<1> &localID) const
|
||||
{
|
||||
AABB result;
|
||||
result.lower.x() = sg.shuffle<float>(lower.x(),localID);
|
||||
result.lower.y() = sg.shuffle<float>(lower.y(),localID);
|
||||
result.lower.z() = sg.shuffle<float>(lower.z(),localID);
|
||||
result.lower.w() = 0.0f;
|
||||
result.upper.x() = sg.shuffle<float>(upper.x(),localID);
|
||||
result.upper.y() = sg.shuffle<float>(upper.y(),localID);
|
||||
result.upper.z() = sg.shuffle<float>(upper.z(),localID);
|
||||
result.upper.w() = 0.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB sub_group_scan_exclusive_min_max(const cl::sycl::intel::sub_group& sg) const
|
||||
{
|
||||
AABB result;
|
||||
result.lower.x() = sg.exclusive_scan<float>(lower.x(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.y() = sg.exclusive_scan<float>(lower.y(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.z() = sg.exclusive_scan<float>(lower.z(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.w() = 0.0f;
|
||||
result.upper.x() = sg.exclusive_scan<float>(upper.x(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.y() = sg.exclusive_scan<float>(upper.y(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.z() = sg.exclusive_scan<float>(upper.z(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.w() = 0.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB sub_group_scan_inclusive_min_max(const cl::sycl::intel::sub_group& sg) const
|
||||
{
|
||||
AABB result;
|
||||
result.lower.x() = sg.inclusive_scan<float>(lower.x(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.y() = sg.inclusive_scan<float>(lower.y(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.z() = sg.inclusive_scan<float>(lower.z(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.w() = 0.0f;
|
||||
result.upper.x() = sg.inclusive_scan<float>(upper.x(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.y() = sg.inclusive_scan<float>(upper.y(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.z() = sg.inclusive_scan<float>(upper.z(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.w() = 0.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB work_group_reduce() const
|
||||
{
|
||||
AABB result;
|
||||
result.lower.x() = work_group_reduce_min(lower.x());
|
||||
result.lower.y() = work_group_reduce_min(lower.y());
|
||||
result.lower.z() = work_group_reduce_min(lower.z());
|
||||
result.lower.w() = 0.0f;
|
||||
result.upper.x() = work_group_reduce_max(upper.x());
|
||||
result.upper.y() = work_group_reduce_max(upper.y());
|
||||
result.upper.z() = work_group_reduce_max(upper.z());
|
||||
result.upper.w() = 0.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline float area() { return gpu::area(size()); }
|
||||
__forceinline float halfArea() { return gpu::halfarea(size()); }
|
||||
|
||||
};
|
||||
|
||||
__forceinline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const AABB& aabb) {
|
||||
return out << "lower " << (float3)aabb.lower.xyz() << " " << as_int((float)aabb.lower.w()) << " upper " << (float3)aabb.upper.xyz() << " " << as_int((float)aabb.upper.w());
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
|
||||
#include "../gpu/common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
class AABB3f {
|
||||
public:
|
||||
float3 lower; // very careful here, as sizeof(float3) == 16 in SYCL...
|
||||
float3 upper;
|
||||
|
||||
__forceinline AABB3f() = default;
|
||||
|
||||
__forceinline AABB3f(const AABB3f &aabb) : lower(aabb.lower),upper(aabb.upper) {}
|
||||
|
||||
__forceinline AABB3f(const float3 &v) : lower(v),upper(v) {}
|
||||
|
||||
__forceinline AABB3f(const float3 &lower, const float3 &upper) : lower(lower),upper(upper) {}
|
||||
|
||||
__forceinline void init()
|
||||
{
|
||||
const float pos_inf = INFINITY;
|
||||
const float neg_inf = -INFINITY;
|
||||
lower = (float3)(pos_inf);
|
||||
upper = (float3)(neg_inf);
|
||||
}
|
||||
|
||||
__forceinline void extend(const class AABB3f &aabb)
|
||||
{
|
||||
lower = min(lower,aabb.lower);
|
||||
upper = max(upper,aabb.upper);
|
||||
}
|
||||
|
||||
__forceinline void extend(const float3 &v)
|
||||
{
|
||||
lower = min(lower,v);
|
||||
upper = max(upper,v);
|
||||
}
|
||||
|
||||
__forceinline void enlarge(const float3 &v)
|
||||
{
|
||||
lower -= v;
|
||||
upper += v;
|
||||
}
|
||||
|
||||
__forceinline float3 size() const
|
||||
{
|
||||
return upper - lower;
|
||||
}
|
||||
|
||||
__forceinline float3 centroid2() const
|
||||
{
|
||||
return upper + lower;
|
||||
}
|
||||
|
||||
__forceinline void atomic_merge_global(AABB3f &dest) const
|
||||
{
|
||||
atomic_min(((volatile GLOBAL float *)&dest.lower) + 0,lower.x());
|
||||
atomic_min(((volatile GLOBAL float *)&dest.lower) + 1,lower.y());
|
||||
atomic_min(((volatile GLOBAL float *)&dest.lower) + 2,lower.z());
|
||||
|
||||
atomic_max(((volatile GLOBAL float *)&dest.upper) + 0,upper.x());
|
||||
atomic_max(((volatile GLOBAL float *)&dest.upper) + 1,upper.y());
|
||||
atomic_max(((volatile GLOBAL float *)&dest.upper) + 2,upper.z());
|
||||
}
|
||||
|
||||
__forceinline void atomic_merge_local(AABB3f &dest) const
|
||||
{
|
||||
atomic_min(((volatile LOCAL float *)&dest.lower) + 0,lower.x());
|
||||
atomic_min(((volatile LOCAL float *)&dest.lower) + 1,lower.y());
|
||||
atomic_min(((volatile LOCAL float *)&dest.lower) + 2,lower.z());
|
||||
|
||||
atomic_max(((volatile LOCAL float *)&dest.upper) + 0,upper.x());
|
||||
atomic_max(((volatile LOCAL float *)&dest.upper) + 1,upper.y());
|
||||
atomic_max(((volatile LOCAL float *)&dest.upper) + 2,upper.z());
|
||||
}
|
||||
|
||||
__forceinline AABB3f sub_group_reduce(const cl::sycl::intel::sub_group& sg) const
|
||||
{
|
||||
AABB3f result;
|
||||
result.lower.x() = sg.reduce<float>(lower.x(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.y() = sg.reduce<float>(lower.y(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.z() = sg.reduce<float>(lower.z(), cl::sycl::intel::minimum<float>());
|
||||
result.upper.x() = sg.reduce<float>(upper.x(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.y() = sg.reduce<float>(upper.y(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.z() = sg.reduce<float>(upper.z(), cl::sycl::intel::maximum<float>());
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB3f sub_group_shuffle(const cl::sycl::intel::sub_group& sg, const cl::sycl::id<1> &localID) const
|
||||
{
|
||||
AABB3f result;
|
||||
result.lower.x() = sg.shuffle<float>(lower.x(),localID);
|
||||
result.lower.y() = sg.shuffle<float>(lower.y(),localID);
|
||||
result.lower.z() = sg.shuffle<float>(lower.z(),localID);
|
||||
result.upper.x() = sg.shuffle<float>(upper.x(),localID);
|
||||
result.upper.y() = sg.shuffle<float>(upper.y(),localID);
|
||||
result.upper.z() = sg.shuffle<float>(upper.z(),localID);
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB3f sub_group_scan_exclusive_min_max(const cl::sycl::intel::sub_group& sg) const
|
||||
{
|
||||
AABB3f result;
|
||||
result.lower.x() = sg.exclusive_scan<float>(lower.x(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.y() = sg.exclusive_scan<float>(lower.y(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.z() = sg.exclusive_scan<float>(lower.z(), cl::sycl::intel::minimum<float>());
|
||||
result.upper.x() = sg.exclusive_scan<float>(upper.x(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.y() = sg.exclusive_scan<float>(upper.y(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.z() = sg.exclusive_scan<float>(upper.z(), cl::sycl::intel::maximum<float>());
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB3f sub_group_scan_inclusive_min_max(const cl::sycl::intel::sub_group& sg) const
|
||||
|
||||
{
|
||||
AABB3f result;
|
||||
result.lower.x() = sg.inclusive_scan<float>(lower.x(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.y() = sg.inclusive_scan<float>(lower.y(), cl::sycl::intel::minimum<float>());
|
||||
result.lower.z() = sg.inclusive_scan<float>(lower.z(), cl::sycl::intel::minimum<float>());
|
||||
result.upper.x() = sg.inclusive_scan<float>(upper.x(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.y() = sg.inclusive_scan<float>(upper.y(), cl::sycl::intel::maximum<float>());
|
||||
result.upper.z() = sg.inclusive_scan<float>(upper.z(), cl::sycl::intel::maximum<float>());
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline AABB3f work_group_reduce() const
|
||||
{
|
||||
AABB3f result;
|
||||
result.lower.x() = work_group_reduce_min(lower.x());
|
||||
result.lower.y() = work_group_reduce_min(lower.y());
|
||||
result.lower.z() = work_group_reduce_min(lower.z());
|
||||
result.upper.x() = work_group_reduce_max(upper.x());
|
||||
result.upper.y() = work_group_reduce_max(upper.y());
|
||||
result.upper.z() = work_group_reduce_max(upper.z());
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline float halfArea() const
|
||||
{
|
||||
const float3 d = size();
|
||||
return halfarea(d);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
__forceinline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const AABB3f& aabb) {
|
||||
return out << "lower " << aabb.lower << " upper " << aabb.upper;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,688 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#include "common.h"
|
||||
#include "AABB.h"
|
||||
#include "AABB3f.h"
|
||||
#include "bvh.h"
|
||||
#include "geometry.h"
|
||||
|
||||
|
||||
#define BUILDRECORD_STACK_SIZE 96
|
||||
#define SAH_LOG_BLOCK_SHIFT 2
|
||||
#define BVH_LEAF_N_MIN 4
|
||||
#define BVH_LEAF_N_MAX 4
|
||||
|
||||
#define DBG_BUILD(x)
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
|
||||
struct Globals
|
||||
{
|
||||
/* 1. cacheline */
|
||||
struct AABB geometryBounds;
|
||||
struct AABB centroidBounds;
|
||||
|
||||
/* 2. cacheline */
|
||||
unsigned int node_mem_allocator_start;
|
||||
unsigned int node_mem_allocator_cur;
|
||||
unsigned int node_mem_allocator_pad[14];
|
||||
|
||||
/* 3. cacheline */
|
||||
unsigned int leaf_mem_allocator_start;
|
||||
unsigned int leaf_mem_allocator_cur;
|
||||
unsigned int leaf_mem_pad[14];
|
||||
|
||||
/* 4. cacheline */
|
||||
unsigned int numPrimitives;
|
||||
unsigned int numOriginalPrimitives;
|
||||
unsigned int numSplittedPrimitives;
|
||||
unsigned int init_numPrimitives;
|
||||
unsigned int leafPrimType;
|
||||
unsigned int leafSize;
|
||||
unsigned int numBuildRecords;
|
||||
unsigned int numBuildRecords_extended;
|
||||
unsigned int totalAllocatedMem;
|
||||
float presplitPrioritySum;
|
||||
|
||||
unsigned int sync;
|
||||
float probThreshold;
|
||||
unsigned int numGlobalBuildRecords;
|
||||
unsigned int counter;
|
||||
unsigned int unused[2];
|
||||
|
||||
inline void init(char *bvh_mem,
|
||||
unsigned int _numPrimitives,
|
||||
unsigned int _node_data_start,
|
||||
unsigned int _leaf_data_start,
|
||||
unsigned int _totalBytes,
|
||||
unsigned int _leafPrimType,
|
||||
unsigned int _leafSize)
|
||||
{
|
||||
struct BVHBase *base = (struct BVHBase*)bvh_mem;
|
||||
base->nodeDataStart = _node_data_start/64;
|
||||
base->nodeDataCur = _node_data_start/64;
|
||||
base->leafDataStart = _leaf_data_start/64;
|
||||
base->leafDataCur = _leaf_data_start/64;
|
||||
base->rootNodeOffset = _node_data_start; // FIXME: should be set by builder
|
||||
|
||||
geometryBounds.init();
|
||||
centroidBounds.init();
|
||||
|
||||
node_mem_allocator_cur = _node_data_start;
|
||||
node_mem_allocator_start = _node_data_start;
|
||||
leaf_mem_allocator_cur = _leaf_data_start;
|
||||
leaf_mem_allocator_start = _leaf_data_start;
|
||||
|
||||
numBuildRecords = 0;
|
||||
numBuildRecords_extended = 0;
|
||||
numPrimitives = _numPrimitives;
|
||||
init_numPrimitives = 0;
|
||||
numSplittedPrimitives = 0;
|
||||
totalAllocatedMem = _totalBytes;
|
||||
sync = 0;
|
||||
probThreshold = 0.0f;
|
||||
leafPrimType = _leafPrimType;
|
||||
leafSize = _leafSize;
|
||||
numGlobalBuildRecords = 0;
|
||||
}
|
||||
|
||||
|
||||
inline void resetGlobalCounters()
|
||||
{
|
||||
node_mem_allocator_cur = node_mem_allocator_start;
|
||||
leaf_mem_allocator_cur = leaf_mem_allocator_start;
|
||||
numBuildRecords = 0;
|
||||
}
|
||||
|
||||
inline uint alloc_node_mem(const uint size)
|
||||
{
|
||||
const uint aligned_size = ((size+63)/64)*64; /* allocate in 64 bytes blocks */
|
||||
cl::sycl::multi_ptr<unsigned int,cl::sycl::access::address_space::global_space> ptr(&node_mem_allocator_cur);
|
||||
cl::sycl::atomic<unsigned int> counter(ptr);
|
||||
return atomic_fetch_add(counter,aligned_size);
|
||||
}
|
||||
|
||||
inline uint alloc_leaf_mem(const uint size)
|
||||
{
|
||||
const uint aligned_size = ((size+15)/16)*16; /* allocate in 16 bytes blocks */
|
||||
cl::sycl::multi_ptr<unsigned int,cl::sycl::access::address_space::global_space> ptr(&leaf_mem_allocator_cur);
|
||||
cl::sycl::atomic<unsigned int> counter(ptr);
|
||||
return atomic_fetch_add(counter,aligned_size);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Range {
|
||||
unsigned int start, end;
|
||||
};
|
||||
|
||||
struct MortonCodePrimitive
|
||||
{
|
||||
uint64_t index_code; // 64bit code + index combo
|
||||
};
|
||||
|
||||
struct BuildRecord
|
||||
{
|
||||
struct AABB centroidBounds;
|
||||
unsigned int start, end;
|
||||
uint *parent;
|
||||
|
||||
inline void init(unsigned int _start, unsigned int _end, AABB &bounds)
|
||||
{
|
||||
centroidBounds = bounds;
|
||||
start = _start;
|
||||
end = _end;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
inline void init(unsigned int _start, unsigned int _end)
|
||||
{
|
||||
centroidBounds.init();
|
||||
start = _start;
|
||||
end = _end;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
|
||||
inline void extend(const AABB &primref)
|
||||
{
|
||||
centroidBounds.extend(primref.centroid2());
|
||||
}
|
||||
|
||||
inline unsigned int size() const { return end - start; }
|
||||
};
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const BuildRecord& r) {
|
||||
return out << " start " << r.start << " end " << r.end << " size " << r.size() << " parent " << r.parent << " bounds " << r.centroidBounds;
|
||||
}
|
||||
|
||||
|
||||
struct BinaryMortonCodeHierarchy
|
||||
{
|
||||
struct Range range;
|
||||
unsigned int leftChild;
|
||||
unsigned int rightChild;
|
||||
unsigned int flag;
|
||||
};
|
||||
|
||||
struct StatStackEntry
|
||||
{
|
||||
struct AABB aabb;
|
||||
unsigned int node;
|
||||
unsigned int type;
|
||||
unsigned int depth;
|
||||
float area;
|
||||
};
|
||||
|
||||
struct BuildRecordMorton {
|
||||
unsigned int nodeID;
|
||||
unsigned int items;
|
||||
unsigned int current_index;
|
||||
unsigned int parent_index;
|
||||
};
|
||||
|
||||
struct Split
|
||||
{
|
||||
float sah;
|
||||
uint dim;
|
||||
uint pos;
|
||||
|
||||
Split() {}
|
||||
|
||||
Split(const float sah, const uint dim, const uint pos) : sah(sah), dim(dim), pos(pos) {}
|
||||
};
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const Split& s) {
|
||||
return out << " sah " << s.sah << " dim " << s.dim << " pos " << s.pos;
|
||||
}
|
||||
|
||||
|
||||
struct BinMapping
|
||||
{
|
||||
float4 ofs, scale;
|
||||
|
||||
inline void init(const AABB ¢Bounds, const uint bins)
|
||||
{
|
||||
const float4 eps(1E-34f);
|
||||
const float4 diag = max(eps, centBounds.upper - centBounds.lower);
|
||||
scale = (float4)(0.99f*(float)bins)/diag;
|
||||
scale = cselect(diag > eps, scale, (float4)(0.0f));
|
||||
ofs = centBounds.lower;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const BinMapping& bm) {
|
||||
return out << "ofs " << bm.ofs.xyz() << " scale " << bm.scale.xyz();
|
||||
}
|
||||
|
||||
|
||||
inline AABB3f convert_AABB3f(const AABB &aabb)
|
||||
{
|
||||
AABB3f aabb3f;
|
||||
aabb3f.lower = aabb.lower.xyz();
|
||||
aabb3f.upper = aabb.upper.xyz();
|
||||
return aabb3f;
|
||||
}
|
||||
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline float left_to_right_area16(const cl::sycl::intel::sub_group &sg, const AABB3f &low)
|
||||
{
|
||||
struct AABB3f low_prefix = low.sub_group_scan_exclusive_min_max(sg);
|
||||
return low_prefix.halfArea();
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline uint left_to_right_counts16(const cl::sycl::intel::sub_group &sg, uint low)
|
||||
{
|
||||
return sg.exclusive_scan<uint>(low, cl::sycl::intel::plus<uint>());
|
||||
}
|
||||
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline float right_to_left_area16(const cl::sycl::intel::sub_group &sg, const AABB3f &low)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const uint subgroupSize = sg.get_local_range().size();
|
||||
const uint ID = subgroupSize - 1 - subgroupLocalID;
|
||||
AABB3f low_reverse = low.sub_group_shuffle(sg,ID);
|
||||
AABB3f low_prefix = low_reverse.sub_group_scan_inclusive_min_max(sg);
|
||||
const float low_area = sg.shuffle<float>(low_prefix.halfArea(),ID);
|
||||
return low_area;
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline uint right_to_left_counts16(const cl::sycl::intel::sub_group &sg, uint low)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const uint subgroupSize = sg.get_local_range().size();
|
||||
const uint ID = subgroupSize - 1 - subgroupLocalID;
|
||||
const uint low_reverse = sg.shuffle<uint>(low,ID);
|
||||
const uint low_prefix = sg.inclusive_scan<float>(low_reverse, cl::sycl::intel::plus<float>());
|
||||
return sg.shuffle<uint>(low_prefix,ID);
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline float2 left_to_right_area32(const cl::sycl::intel::sub_group &sg, const AABB3f &low, const AABB3f &high)
|
||||
{
|
||||
AABB3f low_prefix = low.sub_group_scan_exclusive_min_max(sg);
|
||||
AABB3f low_reduce = low.sub_group_reduce(sg);
|
||||
AABB3f high_prefix = high.sub_group_scan_exclusive_min_max(sg);
|
||||
high_prefix.extend(low_reduce);
|
||||
const float low_area = low_prefix.halfArea();
|
||||
const float high_area = high_prefix.halfArea();
|
||||
return float2(low_area,high_area);
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline uint2 left_to_right_counts32(const cl::sycl::intel::sub_group &sg, uint low, uint high)
|
||||
{
|
||||
const uint low_prefix = sg.exclusive_scan<uint>(low, cl::sycl::intel::plus<uint>());
|
||||
const uint low_reduce = sg.reduce<uint>(low, cl::sycl::intel::plus<uint>());
|
||||
const uint high_prefix = sg.exclusive_scan<uint>(high, cl::sycl::intel::plus<uint>());
|
||||
return uint2(low_prefix,low_reduce+high_prefix);
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline float2 right_to_left_area32(const cl::sycl::intel::sub_group &sg, const AABB3f &low, const AABB3f &high)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const uint subgroupSize = sg.get_local_range().size();
|
||||
const uint ID = subgroupSize - 1 - subgroupLocalID;
|
||||
AABB3f low_reverse = high.sub_group_shuffle(sg,ID);
|
||||
AABB3f high_reverse = low.sub_group_shuffle(sg,ID);
|
||||
AABB3f low_prefix = low_reverse.sub_group_scan_inclusive_min_max(sg);
|
||||
AABB3f low_reduce = low_reverse.sub_group_reduce(sg);
|
||||
AABB3f high_prefix = high_reverse.sub_group_scan_inclusive_min_max(sg);
|
||||
high_prefix.extend(low_reduce);
|
||||
const float low_area = sg.shuffle<float>(high_prefix.halfArea(),ID);
|
||||
const float high_area = sg.shuffle<float>( low_prefix.halfArea(),ID);
|
||||
return float2(low_area,high_area);
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline uint2 right_to_left_counts32(const cl::sycl::intel::sub_group &sg, uint low, uint high)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const uint subgroupSize = sg.get_local_range().size();
|
||||
const uint ID = subgroupSize - 1 - subgroupLocalID;
|
||||
const uint low_reverse = sg.shuffle<uint>(high,ID);
|
||||
const uint high_reverse = sg.shuffle<uint>(low,ID);
|
||||
const uint low_prefix = sg.inclusive_scan<uint>(low_reverse, cl::sycl::intel::plus<uint>());
|
||||
const uint low_reduce = sg.reduce<uint>(low_reverse, cl::sycl::intel::plus<uint>());
|
||||
const uint high_prefix = sg.inclusive_scan<uint>(high_reverse, cl::sycl::intel::plus<uint>()) + low_reduce;
|
||||
return uint2(sg.shuffle<uint>(high_prefix,ID),sg.shuffle<uint>(low_prefix,ID));
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline ulong getBestSplit(cl::sycl::intel::sub_group &sg, const float3 sah, uint ID, const float4 scale, const ulong defaultSplit)
|
||||
{
|
||||
ulong splitX = (((ulong)as_uint((float)sah.x())) << 32) | ((uint)ID << 2) | 0;
|
||||
ulong splitY = (((ulong)as_uint((float)sah.y())) << 32) | ((uint)ID << 2) | 1;
|
||||
ulong splitZ = (((ulong)as_uint((float)sah.z())) << 32) | ((uint)ID << 2) | 2;
|
||||
|
||||
|
||||
/* ignore zero sized dimensions */
|
||||
splitX = cselect( (ulong)(scale.x() == 0), defaultSplit, splitX);
|
||||
splitY = cselect( (ulong)(scale.y() == 0), defaultSplit, splitY);
|
||||
splitZ = cselect( (ulong)(scale.z() == 0), defaultSplit, splitZ);
|
||||
ulong bestSplit = min(min(splitX,splitY),splitZ);
|
||||
bestSplit = sg.reduce<ulong>(bestSplit, cl::sycl::intel::minimum<ulong>());
|
||||
return bestSplit;
|
||||
}
|
||||
|
||||
|
||||
struct BinInfo {
|
||||
AABB3f boundsX[BINS];
|
||||
AABB3f boundsY[BINS];
|
||||
AABB3f boundsZ[BINS];
|
||||
uint3 counts[BINS];
|
||||
|
||||
inline void init()
|
||||
{
|
||||
for (uint i=0;i<BINS;i++)
|
||||
{
|
||||
boundsX[i].init();
|
||||
boundsY[i].init();
|
||||
boundsZ[i].init();
|
||||
counts[i] = (uint3)(0);
|
||||
}
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline void init(const cl::sycl::intel::sub_group &subgroup)
|
||||
{
|
||||
for (uint i=subgroup.get_local_id()[0];i<BINS;i+=subgroup.get_local_range().size())
|
||||
{
|
||||
boundsX[i].init();
|
||||
boundsY[i].init();
|
||||
boundsZ[i].init();
|
||||
counts[i] = (uint3)(0);
|
||||
}
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline void atomicUpdate( const gpu::BinMapping &binMapping, const gpu::AABB &primref)
|
||||
{
|
||||
const float4 p = primref.centroid2();
|
||||
const float4 bin4 = (p-binMapping.ofs)*binMapping.scale;
|
||||
const cl::sycl::uint4 i = bin4.convert<cl::sycl::uint,cl::sycl::rounding_mode::rtz>();
|
||||
|
||||
gpu::AABB3f bounds = convert_AABB3f(primref);
|
||||
|
||||
bounds.atomic_merge_local(boundsX[i.x()]);
|
||||
bounds.atomic_merge_local(boundsY[i.y()]);
|
||||
bounds.atomic_merge_local(boundsZ[i.z()]);
|
||||
|
||||
gpu::atomic_add<uint,cl::sycl::access::address_space::local_space>((uint *)&counts[i.x()].x(),1);
|
||||
gpu::atomic_add<uint,cl::sycl::access::address_space::local_space>((uint *)&counts[i.y()].y(),1);
|
||||
gpu::atomic_add<uint,cl::sycl::access::address_space::local_space>((uint *)&counts[i.z()].z(),1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline gpu::Split reduceBinsAndComputeBestSplit16(cl::sycl::intel::sub_group &sg, const float4 scale, const uint startID, const uint endID)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const AABB3f &bX = boundsX[subgroupLocalID];
|
||||
const float lr_areaX = left_to_right_area16(sg,bX);
|
||||
const float rl_areaX = right_to_left_area16(sg,bX);
|
||||
const AABB3f &bY = boundsY[subgroupLocalID];
|
||||
const float lr_areaY = left_to_right_area16(sg,bY);
|
||||
const float rl_areaY = right_to_left_area16(sg,bY);
|
||||
const AABB3f &bZ = boundsZ[subgroupLocalID];
|
||||
const float lr_areaZ = left_to_right_area16(sg,bZ);
|
||||
const float rl_areaZ = right_to_left_area16(sg,bZ);
|
||||
const uint3 &c = counts[subgroupLocalID];
|
||||
const uint lr_countsX = left_to_right_counts16(sg,c.x());
|
||||
const uint rl_countsX = right_to_left_counts16(sg,c.x());
|
||||
const uint lr_countsY = left_to_right_counts16(sg,c.y());
|
||||
const uint rl_countsY = right_to_left_counts16(sg,c.y());
|
||||
const uint lr_countsZ = left_to_right_counts16(sg,c.z());
|
||||
const uint rl_countsZ = right_to_left_counts16(sg,c.z());
|
||||
|
||||
const uint blocks_shift = SAH_LOG_BLOCK_SHIFT;
|
||||
const uint blocks_add = ((1 << blocks_shift)-1);
|
||||
const uint3 lr_count( (lr_countsX+blocks_add)>>blocks_shift , (lr_countsY+blocks_add)>>blocks_shift, (lr_countsZ+blocks_add)>>blocks_shift );
|
||||
const float3 lr_area(lr_areaX,lr_areaY,lr_areaZ);
|
||||
const float3 rl_area(rl_areaX,rl_areaY,rl_areaZ);
|
||||
const uint3 rl_count( (rl_countsX+blocks_add)>>blocks_shift , (rl_countsY+blocks_add)>>blocks_shift, (rl_countsZ+blocks_add)>>blocks_shift );
|
||||
const float3 lr_count_f ( (float)lr_count.x(),(float)lr_count.y(),(float)lr_count.z() );
|
||||
const float3 rl_count_f ( (float)rl_count.x(),(float)rl_count.y(),(float)rl_count.z() );
|
||||
|
||||
/* first bin is invalid */
|
||||
const float pos_inf = (float)INFINITY;
|
||||
// workaround for compiler bug
|
||||
const int m_subgroup = subgroupLocalID != 0 ? -1 : 0;
|
||||
const float3 cost = cl::sycl::fma(lr_area,lr_count_f,rl_area*rl_count_f);
|
||||
const float3 sah = cselect( int3(m_subgroup), cost , float3(pos_inf));
|
||||
|
||||
/* select best split */
|
||||
const uint mid = (startID+endID)/2;
|
||||
const uint maxSAH = as_uint(pos_inf);
|
||||
const ulong defaultSplit = (((ulong)maxSAH) << 32) | ((uint)mid << 2) | 0;
|
||||
const ulong bestSplit = getBestSplit(sg, sah, subgroupLocalID, scale, defaultSplit);
|
||||
const uint bestSplit32 = (uint)(bestSplit >> 32);
|
||||
const float split_sah = as_float(bestSplit32);
|
||||
return gpu::Split(split_sah,(uint)bestSplit & 3,(uint)bestSplit >> 2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct BinInfo2 {
|
||||
AABB3f boundsX[BINS*2];
|
||||
AABB3f boundsY[BINS*2];
|
||||
AABB3f boundsZ[BINS*2];
|
||||
uint3 counts[BINS*2];
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline void init(const cl::sycl::intel::sub_group &subgroup)
|
||||
{
|
||||
for (uint i=subgroup.get_local_id()[0];i<BINS*2;i+=subgroup.get_local_range().size())
|
||||
{
|
||||
boundsX[i].init();
|
||||
boundsY[i].init();
|
||||
boundsZ[i].init();
|
||||
counts[i] = (uint3)(0);
|
||||
}
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline void atomicUpdate( const gpu::BinMapping &binMapping, const gpu::AABB &primref)
|
||||
{
|
||||
const float4 p = primref.centroid2();
|
||||
const float4 bin4 = (p-binMapping.ofs)*binMapping.scale;
|
||||
const cl::sycl::uint4 i = bin4.convert<cl::sycl::uint,cl::sycl::rounding_mode::rtz>();
|
||||
|
||||
gpu::AABB3f bounds = convert_AABB3f(primref);
|
||||
|
||||
bounds.atomic_merge_local(boundsX[i.x()]);
|
||||
bounds.atomic_merge_local(boundsY[i.y()]);
|
||||
bounds.atomic_merge_local(boundsZ[i.z()]);
|
||||
|
||||
gpu::atomic_add<uint,cl::sycl::access::address_space::local_space>((uint *)&counts[i.x()].x(),1);
|
||||
gpu::atomic_add<uint,cl::sycl::access::address_space::local_space>((uint *)&counts[i.y()].y(),1);
|
||||
gpu::atomic_add<uint,cl::sycl::access::address_space::local_space>((uint *)&counts[i.z()].z(),1);
|
||||
}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(BINS)]] inline gpu::Split reduceBinsAndComputeBestSplit32(cl::sycl::intel::sub_group &sg, const float4 scale, const uint startID, const uint endID)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const uint subgroup_size = BINS;
|
||||
|
||||
AABB3f boundsX_low = boundsX[subgroupLocalID ];
|
||||
AABB3f boundsX_high = boundsX[subgroupLocalID+subgroup_size];
|
||||
|
||||
const float2 lr_areaX = left_to_right_area32(sg,boundsX_low,boundsX_high);
|
||||
const float2 rl_areaX = right_to_left_area32(sg,boundsX_low,boundsX_high);
|
||||
|
||||
AABB3f boundsY_low = boundsY[subgroupLocalID ];
|
||||
AABB3f boundsY_high = boundsY[subgroupLocalID+subgroup_size];
|
||||
|
||||
const float2 lr_areaY = left_to_right_area32(sg,boundsY_low,boundsY_high);
|
||||
const float2 rl_areaY = right_to_left_area32(sg,boundsY_low,boundsY_high);
|
||||
|
||||
AABB3f boundsZ_low = boundsZ[subgroupLocalID ];
|
||||
AABB3f boundsZ_high = boundsZ[subgroupLocalID+subgroup_size];
|
||||
|
||||
const float2 lr_areaZ = left_to_right_area32(sg,boundsZ_low,boundsZ_high);
|
||||
const float2 rl_areaZ = right_to_left_area32(sg,boundsZ_low,boundsZ_high);
|
||||
|
||||
const uint3 counts_low = counts[subgroupLocalID ];
|
||||
const uint3 counts_high = counts[subgroupLocalID+subgroup_size];
|
||||
|
||||
const uint2 lr_countsX = left_to_right_counts32(sg,counts_low.x(),counts_high.x());
|
||||
const uint2 rl_countsX = right_to_left_counts32(sg,counts_low.x(),counts_high.x());
|
||||
const uint2 lr_countsY = left_to_right_counts32(sg,counts_low.y(),counts_high.y());
|
||||
const uint2 rl_countsY = right_to_left_counts32(sg,counts_low.y(),counts_high.y());
|
||||
const uint2 lr_countsZ = left_to_right_counts32(sg,counts_low.z(),counts_high.z());
|
||||
const uint2 rl_countsZ = right_to_left_counts32(sg,counts_low.z(),counts_high.z());
|
||||
|
||||
const uint blocks_shift = SAH_LOG_BLOCK_SHIFT;
|
||||
uint3 blocks_add = (uint3)((1 << blocks_shift)-1);
|
||||
const float pos_inf = (float)INFINITY;
|
||||
|
||||
/* low part: bins 0..15 */
|
||||
const float3 lr_area_low(lr_areaX.x(),lr_areaY.x(),lr_areaZ.x());
|
||||
const float3 rl_area_low(rl_areaX.x(),rl_areaY.x(),rl_areaZ.x());
|
||||
const uint3 lr_count_low = (uint3(lr_countsX.x(),lr_countsY.x(),lr_countsZ.x())+blocks_add) >> blocks_shift;
|
||||
const uint3 rl_count_low = (uint3(rl_countsX.x(),rl_countsY.x(),rl_countsZ.x())+blocks_add) >> blocks_shift;
|
||||
|
||||
const float3 lr_count_low_f = float3( (float)lr_count_low.x(),(float)lr_count_low.y(),(float)lr_count_low.z() );
|
||||
const float3 rl_count_low_f = float3( (float)rl_count_low.x(),(float)rl_count_low.y(),(float)rl_count_low.z() );
|
||||
|
||||
float3 sah_low = cl::sycl::fma(lr_area_low,lr_count_low_f,rl_area_low*rl_count_low_f);
|
||||
|
||||
/* first bin is invalid */
|
||||
// workaround for compiler bug
|
||||
const int m_subgroup = subgroupLocalID != 0 ? -1 : 0;
|
||||
sah_low = cselect( int3(m_subgroup), sah_low, float3(pos_inf));
|
||||
|
||||
/* high part: bins 16..31 */
|
||||
const float3 lr_area_high(lr_areaX.y(),lr_areaY.y(),lr_areaZ.y());
|
||||
const float3 rl_area_high(rl_areaX.y(),rl_areaY.y(),rl_areaZ.y());
|
||||
const uint3 lr_count_high = (uint3(lr_countsX.y(),lr_countsY.y(),lr_countsZ.y())+blocks_add) >> blocks_shift;
|
||||
const uint3 rl_count_high = (uint3(rl_countsX.y(),rl_countsY.y(),rl_countsZ.y())+blocks_add) >> blocks_shift;
|
||||
const float3 lr_count_high_f = float3( (float)lr_count_high.x(),(float)lr_count_high.y(),(float)lr_count_high.z() );
|
||||
const float3 rl_count_high_f = float3( (float)rl_count_high.x(),(float)rl_count_high.y(),(float)rl_count_high.z() );
|
||||
const float3 sah_high = fma(lr_area_high,lr_count_high_f,rl_area_high*rl_count_high_f);
|
||||
|
||||
const uint mid = (startID+endID)/2;
|
||||
const ulong defaultSplit = (((ulong)as_uint((float)(INFINITY))) << 32) | ((uint)mid << 2) | 0;
|
||||
|
||||
const ulong bestSplit_low = getBestSplit(sg, sah_low ,subgroupLocalID,scale,defaultSplit);
|
||||
const ulong bestSplit_high = getBestSplit(sg, sah_high,subgroupLocalID+subgroup_size,scale,defaultSplit);
|
||||
const ulong bestSplit = min(bestSplit_low,bestSplit_high);
|
||||
const uint bestSplit32 = (uint)(bestSplit >> 32);
|
||||
const float split_sah = as_float(bestSplit32);
|
||||
return gpu::Split(split_sah,(uint)bestSplit & 3,(uint)bestSplit >> 2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline uint encodeOffset(char *bvh_mem, uint *parent, uint global_child_offset)
|
||||
{
|
||||
ulong global_parent_offset = (ulong)parent - (ulong)bvh_mem;
|
||||
// parent node address starts at least on 64 bytes boundary
|
||||
global_parent_offset = global_parent_offset & (~63);
|
||||
uint relative_offset = global_child_offset - global_parent_offset;
|
||||
return relative_offset;
|
||||
}
|
||||
|
||||
inline uint createLeaf(const Globals &globals,
|
||||
char *bvh_mem,
|
||||
uint *parent,
|
||||
const uint start,
|
||||
const uint items)
|
||||
{
|
||||
ulong global_parent_offset = (ulong)parent - (ulong)bvh_mem;
|
||||
// parent node address starts at least on 64 bytes boundary
|
||||
global_parent_offset = global_parent_offset & (~63);
|
||||
const uint global_child_offset = globals.leaf_mem_allocator_start + start * globals.leafSize;
|
||||
const uint offset = global_child_offset - (uint)global_parent_offset;
|
||||
/* if (offset & BVH_LOWER_BITS_MASK) */
|
||||
/* out << "offset & BVH_LOWER_BITS_MASK " << (offset&BVH_LOWER_BITS_MASK) << cl::sycl::endl; */
|
||||
const unsigned int final = offset | BVH_LEAF_MASK | (items-1);
|
||||
return final;
|
||||
}
|
||||
|
||||
inline uint createNode(cl::sycl::intel::sub_group &subgroup, Globals &globals, const uint ID, struct AABB *childrenAABB, uint numChildren, char *bvh_mem)
|
||||
{
|
||||
const uint subgroupLocalID = subgroup.get_local_id()[0];
|
||||
uint node_offset = 0;
|
||||
if (subgroupLocalID == 0)
|
||||
{
|
||||
node_offset = globals.alloc_node_mem(sizeof(gpu::QBVHNodeN));
|
||||
}
|
||||
node_offset = subgroup.broadcast<uint>(node_offset,0);
|
||||
gpu::QBVHNodeN &node = *(gpu::QBVHNodeN*)(bvh_mem + node_offset);
|
||||
gpu::QBVHNodeN::init(subgroup,node,childrenAABB,numChildren,ID);
|
||||
return node_offset;
|
||||
}
|
||||
|
||||
|
||||
inline bool checkPrimRefBounds(const BuildRecord &record, const AABB &geometryBounds, const AABB &primref)
|
||||
{
|
||||
const float4 centroid2 = primref.lower+primref.upper;
|
||||
|
||||
if (centroid2.x() < record.centroidBounds.lower.x()) return false;
|
||||
if (centroid2.y() < record.centroidBounds.lower.y()) return false;
|
||||
if (centroid2.z() < record.centroidBounds.lower.z()) return false;
|
||||
|
||||
if (centroid2.x() > record.centroidBounds.upper.x()) return false;
|
||||
if (centroid2.y() > record.centroidBounds.upper.y()) return false;
|
||||
if (centroid2.z() > record.centroidBounds.upper.z()) return false;
|
||||
|
||||
if (primref.lower.x() < geometryBounds.lower.x()) return false;
|
||||
if (primref.lower.y() < geometryBounds.lower.y()) return false;
|
||||
if (primref.lower.z() < geometryBounds.lower.z()) return false;
|
||||
|
||||
if (primref.upper.x() > geometryBounds.upper.x()) return false;
|
||||
if (primref.upper.y() > geometryBounds.upper.y()) return false;
|
||||
if (primref.upper.z() > geometryBounds.upper.z()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const uint shuffle2mirror[16] = { 1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14 };
|
||||
const uint shuffle4mirror[16] = { 3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12 };
|
||||
const uint shuffle4rotate[16] = { 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13 };
|
||||
const uint shuffle8mirror[16] = { 7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8 };
|
||||
const uint shuffle8rotate[16] = { 4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11 };
|
||||
const uint shuffle16mirror[16] = { 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 };
|
||||
|
||||
const uint selGo2[16] = { 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 };
|
||||
const uint selGo4[16] = { 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1 };
|
||||
const uint selGo8[16] = { 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1 };
|
||||
const uint selGo16[16] = { 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1 };
|
||||
|
||||
inline uint compare_exchange(const cl::sycl::intel::sub_group &sg, const uint a0, const uint shuffleMask, const uint selectMask, const bool ascending)
|
||||
{
|
||||
const uint a1 = sg.shuffle(a0,shuffleMask);
|
||||
const uint a_min = min(a0,a1);
|
||||
const uint a_max = max(a0,a1);
|
||||
return cl::sycl::select(ascending ? a_min : a_max,ascending ? a_max : a_min,selectMask);
|
||||
}
|
||||
|
||||
inline uint sort16(const cl::sycl::intel::sub_group &sg, const uint aa, const bool ascending)
|
||||
{
|
||||
const uint slotID = sg.get_local_id()[0];
|
||||
const uint bb = compare_exchange(sg,aa,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
const uint cc = compare_exchange(sg,bb,shuffle4mirror[slotID],selGo4[slotID],ascending);
|
||||
const uint dd = compare_exchange(sg,cc,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
const uint ee = compare_exchange(sg,dd,shuffle8mirror[slotID],selGo8[slotID],ascending);
|
||||
const uint ff = compare_exchange(sg,ee,shuffle4rotate[slotID],selGo4[slotID],ascending);
|
||||
const uint gg = compare_exchange(sg,ff,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
const uint hh = compare_exchange(sg,gg,shuffle16mirror[slotID],selGo16[slotID],ascending);
|
||||
const uint ii = compare_exchange(sg,hh,shuffle8rotate[slotID],selGo8[slotID],ascending);
|
||||
const uint jj = compare_exchange(sg,ii,shuffle4rotate[slotID],selGo4[slotID],ascending);
|
||||
const uint kk = compare_exchange(sg,jj,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
return kk;
|
||||
|
||||
}
|
||||
|
||||
inline uint sort8(const cl::sycl::intel::sub_group &sg, const uint aa, const bool ascending)
|
||||
{
|
||||
const uint slotID = sg.get_local_id()[0];
|
||||
const uint bb = compare_exchange(sg,aa,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
const uint cc = compare_exchange(sg,bb,shuffle4mirror[slotID],selGo4[slotID],ascending);
|
||||
const uint dd = compare_exchange(sg,cc,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
const uint ee = compare_exchange(sg,dd,shuffle8mirror[slotID],selGo8[slotID],ascending);
|
||||
const uint ff = compare_exchange(sg,ee,shuffle4rotate[slotID],selGo4[slotID],ascending);
|
||||
const uint gg = compare_exchange(sg,ff,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
return gg;
|
||||
}
|
||||
|
||||
inline uint sort4(const cl::sycl::intel::sub_group &sg, const uint aa, const bool ascending)
|
||||
{
|
||||
const uint slotID = sg.get_local_id()[0];
|
||||
const uint bb = compare_exchange(sg,aa,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
const uint cc = compare_exchange(sg,bb,shuffle4mirror[slotID],selGo4[slotID],ascending);
|
||||
const uint dd = compare_exchange(sg,cc,shuffle2mirror[slotID],selGo2[slotID],ascending);
|
||||
return dd;
|
||||
}
|
||||
|
||||
inline uint sortBVHChildrenIDs(const cl::sycl::intel::sub_group &sg, uint input)
|
||||
{
|
||||
#if BVH_NODE_N == 16
|
||||
return sort16(sg, input,false);
|
||||
#elif BVH_NODE_N == 8
|
||||
return sort8(sg, input,false);
|
||||
#else
|
||||
return sort4(sg, input,false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,695 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#include "common.h"
|
||||
#include "AABB.h"
|
||||
#include "AABB3f.h"
|
||||
|
||||
/* ====== BVH16 config ====== */
|
||||
|
||||
#define BVH_LEAF_MASK_SHIFT 31
|
||||
#define BVH_LEAF_MASK (1<<BVH_LEAF_MASK_SHIFT)
|
||||
#define BVH_NUM_ITEMS_SHIFT 4
|
||||
#define BVH_LOWER_BITS_MASK ((1<<(BVH_NUM_ITEMS_SHIFT))-1)
|
||||
#define BVH_MAX_NUM_ITEMS (BVH_LOWER_BITS_MASK+1)
|
||||
#define BVH_NODE_N 16
|
||||
#define BVH_NODE_N_LOG 4
|
||||
#define BVH_MAX_STACK_ENTRIES 64
|
||||
#define BVH_INVALID_NODE_REF -1
|
||||
|
||||
|
||||
/* ====== BVH Builder and Quantization config ====== */
|
||||
|
||||
#define BINS 16
|
||||
#define QUANT_BITS 8
|
||||
#define QUANT_MIN 0
|
||||
#define QUANT_MAX 255
|
||||
#define QUANT_MAX_MANT (255.0f/256.0f)
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
|
||||
/* ======================================================================= */
|
||||
/* ============================== BVH BASE =============================== */
|
||||
/* ======================================================================= */
|
||||
|
||||
struct BVHBase
|
||||
{
|
||||
AABB3f bounds;
|
||||
unsigned long rootNodeOffset;
|
||||
uint nodeDataStart;
|
||||
uint nodeDataCur;
|
||||
uint leafDataStart;
|
||||
uint leafDataCur;
|
||||
uint proceduralDataStart;
|
||||
uint proceduralDataCur;
|
||||
/* uint backPointerDataStart; */
|
||||
/* uint backPointerDataEnd; */
|
||||
};
|
||||
|
||||
/* ========================================================================== */
|
||||
/* ============================== BVH NODEREF =============================== */
|
||||
/* ========================================================================== */
|
||||
|
||||
struct NodeRef
|
||||
{
|
||||
__forceinline NodeRef () {}
|
||||
|
||||
__forceinline NodeRef (uint offset) : offset(offset) {}
|
||||
|
||||
__forceinline operator uint() const { return offset; }
|
||||
|
||||
__forceinline size_t isLeaf() const { return offset & BVH_LEAF_MASK; }
|
||||
|
||||
__forceinline uint getNumLeafPrims() const { return (offset & BVH_LOWER_BITS_MASK)+1; }
|
||||
__forceinline uint getLeafOffset() const { return offset & (~(BVH_LOWER_BITS_MASK|BVH_LEAF_MASK)); }
|
||||
|
||||
|
||||
private:
|
||||
uint offset;
|
||||
};
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== QBVH NODE =============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
struct QBVHNodeN
|
||||
{
|
||||
/* special layout requires just two subgroup block loads for entire node */
|
||||
|
||||
uint offset[BVH_NODE_N];
|
||||
float4 org;
|
||||
float4 scale;
|
||||
|
||||
struct {
|
||||
uchar lower;
|
||||
uchar upper;
|
||||
} bounds_x[BVH_NODE_N];
|
||||
|
||||
struct {
|
||||
uchar lower;
|
||||
uchar upper;
|
||||
} bounds_y[BVH_NODE_N];
|
||||
|
||||
struct {
|
||||
uchar lower;
|
||||
uchar upper;
|
||||
} bounds_z[BVH_NODE_N];
|
||||
|
||||
__forceinline AABB getBounds(const uint i)
|
||||
{
|
||||
const uchar4 ilower(bounds_x[i].lower,bounds_y[i].lower,bounds_z[i].lower,0);
|
||||
const uchar4 iupper(bounds_x[i].upper,bounds_y[i].upper,bounds_z[i].upper,0);
|
||||
const float4 lowerf = ilower.convert<float,cl::sycl::rounding_mode::rtn>();
|
||||
const float4 upperf = iupper.convert<float,cl::sycl::rounding_mode::rtp>();
|
||||
AABB aabb;
|
||||
aabb.lower = cl::sycl::fma(lowerf,scale,org);
|
||||
aabb.upper = cl::sycl::fma(upperf,scale,org);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
__forceinline AABB getBounds()
|
||||
{
|
||||
AABB aabb;
|
||||
aabb.init();
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
{
|
||||
if (offset[i] == BVH_INVALID_NODE_REF) break;
|
||||
aabb.extend(getBounds(i));
|
||||
}
|
||||
return aabb;
|
||||
}
|
||||
|
||||
|
||||
__forceinline static void init(cl::sycl::intel::sub_group &sg,
|
||||
QBVHNodeN &node,
|
||||
AABB *childrenAABB,
|
||||
uint numChildren,
|
||||
const uint ID)
|
||||
{
|
||||
AABB child;
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
if (subgroupLocalID < numChildren)
|
||||
child = childrenAABB[ID];
|
||||
else
|
||||
child.init();
|
||||
AABB aabb = child.sub_group_reduce(sg);
|
||||
|
||||
const float4 minF = aabb.lower;
|
||||
const float4 diff = aabb.size()*(1.0f+2.0f*FLT_MIN);
|
||||
float4 decode_scale = diff / (float4)((float)QUANT_MAX);
|
||||
decode_scale = cselect(decode_scale != 0.0f, decode_scale, float4(2.0f*FLT_MIN));
|
||||
float4 encode_scale = (float4)((float)QUANT_MAX) / diff;
|
||||
encode_scale = cselect(diff > 0.0f, encode_scale, float4(0.0f));
|
||||
|
||||
if (subgroupLocalID < BVH_NODE_N)
|
||||
{
|
||||
// workaround for compiler bug
|
||||
int m_valid = subgroupLocalID < numChildren ? -1 : 0;
|
||||
|
||||
const float4 lower = child.lower;
|
||||
const float4 upper = child.upper;
|
||||
|
||||
float4 lowerf = floor((lower - minF)*encode_scale);
|
||||
float4 upperf = ceil((upper - minF)*encode_scale);
|
||||
|
||||
int4 ilower = max(lowerf.convert<int,cl::sycl::rounding_mode::rtn>(),int4(QUANT_MIN));
|
||||
int4 iupper = min(upperf.convert<int,cl::sycl::rounding_mode::rtp>(),int4(QUANT_MAX));
|
||||
|
||||
/* lower/upper correction */
|
||||
int4 m_lower_correction = (cl::sycl::fma(ilower.convert<float,cl::sycl::rounding_mode::rtn>(),decode_scale,minF)) > lower;
|
||||
int4 m_upper_correction = (cl::sycl::fma(iupper.convert<float,cl::sycl::rounding_mode::rtp>(),decode_scale,minF)) < upper;
|
||||
|
||||
ilower = max(cselect(m_lower_correction,ilower-1,ilower),QUANT_MIN);
|
||||
iupper = min(cselect(m_upper_correction,iupper+1,iupper),QUANT_MAX);
|
||||
|
||||
/* disable invalid lanes */
|
||||
|
||||
ilower = cselect(int4(m_valid),ilower,int4(QUANT_MAX));
|
||||
iupper = cselect(int4(m_valid),iupper,int4(QUANT_MIN));
|
||||
|
||||
node.offset[subgroupLocalID] = BVH_INVALID_NODE_REF;
|
||||
node.bounds_x[subgroupLocalID].lower = ilower.x();
|
||||
node.bounds_y[subgroupLocalID].lower = ilower.y();
|
||||
node.bounds_z[subgroupLocalID].lower = ilower.z();
|
||||
node.bounds_x[subgroupLocalID].upper = iupper.x();
|
||||
node.bounds_y[subgroupLocalID].upper = iupper.y();
|
||||
node.bounds_z[subgroupLocalID].upper = iupper.z();
|
||||
node.org = minF;
|
||||
node.scale = decode_scale;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
__forceinline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const QBVHNodeN& node) {
|
||||
out << " org " << node.org
|
||||
<< " scale " << node.scale
|
||||
<< cl::sycl::endl;
|
||||
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
{
|
||||
out << " offset " << node.offset[i]
|
||||
<< " {("
|
||||
<< (int)node.bounds_x[i].lower << ","
|
||||
<< (int)node.bounds_y[i].lower << ","
|
||||
<< (int)node.bounds_z[i].lower
|
||||
<< "),("
|
||||
<< (int)node.bounds_x[i].upper << ","
|
||||
<< (int)node.bounds_y[i].upper << ","
|
||||
<< (int)node.bounds_z[i].upper
|
||||
<< ")}"
|
||||
<< cl::sycl::endl;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================================================== */
|
||||
/* ============================== QBVH NODE MB =============================== */
|
||||
/* =========================================================================== */
|
||||
|
||||
struct QBVHNodeNMB
|
||||
{
|
||||
|
||||
NodeRef offset[BVH_NODE_N];
|
||||
float lower_t[BVH_NODE_N];
|
||||
float upper_t[BVH_NODE_N];
|
||||
float4 org0, scale0;
|
||||
float4 org1, scale1;
|
||||
|
||||
uchar lower_x0[BVH_NODE_N];
|
||||
uchar upper_x0[BVH_NODE_N];
|
||||
uchar lower_y0[BVH_NODE_N];
|
||||
uchar upper_y0[BVH_NODE_N];
|
||||
uchar lower_z0[BVH_NODE_N];
|
||||
uchar upper_z0[BVH_NODE_N];
|
||||
uchar lower_x1[BVH_NODE_N];
|
||||
uchar upper_x1[BVH_NODE_N];
|
||||
uchar lower_y1[BVH_NODE_N];
|
||||
uchar upper_y1[BVH_NODE_N];
|
||||
uchar lower_z1[BVH_NODE_N];
|
||||
uchar upper_z1[BVH_NODE_N];
|
||||
|
||||
|
||||
__forceinline AABB getBounds0(const uint i) const
|
||||
{
|
||||
const uchar4 ilower(lower_x0[i],lower_y0[i],lower_z0[i],0);
|
||||
const uchar4 iupper(upper_x0[i],upper_y0[i],upper_z0[i],0);
|
||||
const float4 lowerf = ilower.convert<float,cl::sycl::rounding_mode::rtn>();
|
||||
const float4 upperf = iupper.convert<float,cl::sycl::rounding_mode::rtp>();
|
||||
AABB aabb;
|
||||
aabb.lower = cl::sycl::fma(lowerf,scale0,org0);
|
||||
aabb.upper = cl::sycl::fma(upperf,scale0,org0);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
__forceinline AABB getBounds1(const uint i) const
|
||||
{
|
||||
const uchar4 ilower(lower_x1[i],lower_y1[i],lower_z1[i],0);
|
||||
const uchar4 iupper(upper_x1[i],upper_y1[i],upper_z1[i],0);
|
||||
const float4 lowerf = ilower.convert<float,cl::sycl::rounding_mode::rtn>();
|
||||
const float4 upperf = iupper.convert<float,cl::sycl::rounding_mode::rtp>();
|
||||
AABB aabb;
|
||||
aabb.lower = cl::sycl::fma(lowerf,scale1,org1);
|
||||
aabb.upper = cl::sycl::fma(upperf,scale1,org1);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
__forceinline AABB getBounds0() const
|
||||
{
|
||||
AABB aabb;
|
||||
aabb.init();
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
if (offset[i] != BVH_INVALID_NODE_REF)
|
||||
aabb.extend(getBounds0(i));
|
||||
return aabb;
|
||||
}
|
||||
|
||||
__forceinline AABB getBounds1() const
|
||||
{
|
||||
AABB aabb;
|
||||
aabb.init();
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
if (offset[i] != BVH_INVALID_NODE_REF)
|
||||
aabb.extend(getBounds1(i));
|
||||
return aabb;
|
||||
}
|
||||
|
||||
|
||||
__forceinline AABB bounds_lower(size_t i) const {
|
||||
const AABB b0 = getBounds0(i);
|
||||
const AABB b1 = getBounds1(i);
|
||||
const float t = lower_t[i];
|
||||
const float4 lower = gpu::lerp<float4>(b0.lower,b1.lower,t);
|
||||
const float4 upper = gpu::lerp<float4>(b0.upper,b1.upper,t);
|
||||
return AABB( lower, upper );
|
||||
}
|
||||
|
||||
__forceinline AABB bounds_upper(size_t i) const {
|
||||
const AABB b0 = getBounds0(i);
|
||||
const AABB b1 = getBounds1(i);
|
||||
const float t = upper_t[i];
|
||||
const float4 lower = gpu::lerp<float4>(b0.lower,b1.lower,t);
|
||||
const float4 upper = gpu::lerp<float4>(b0.upper,b1.upper,t);
|
||||
return AABB( lower, upper );
|
||||
}
|
||||
|
||||
__forceinline void clear()
|
||||
{
|
||||
for (size_t i=0;i<BVH_NODE_N;i++)
|
||||
{
|
||||
offset[i] = BVH_INVALID_NODE_REF;
|
||||
lower_t[i] = 1.0f;
|
||||
upper_t[i] = 0.0f;
|
||||
lower_x0[i] = lower_y0[i] = lower_z0[i] = QUANT_MAX;
|
||||
upper_x0[i] = upper_y0[i] = upper_z0[i] = QUANT_MIN;
|
||||
lower_x1[i] = lower_y1[i] = lower_z1[i] = QUANT_MAX;
|
||||
upper_x1[i] = upper_y1[i] = upper_z1[i] = QUANT_MIN;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
__forceinline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const QBVHNodeNMB& node) {
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
{
|
||||
out << " i " << i
|
||||
<< " offset " << (uint)node.offset[i] << " offset " << node.offset[i].getLeafOffset() << " numPrims " << node.offset[i].getNumLeafPrims()
|
||||
<< " time (" << node.lower_t[i] << "," << node.upper_t[i] << ") "
|
||||
<< "bounds0 " << node.getBounds0(i) << " bounds1 " << node.getBounds1(i) << cl::sycl::endl;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* =========================================================================== */
|
||||
/* ============================== BVH NODE MB =============================== */
|
||||
/* =========================================================================== */
|
||||
|
||||
struct BVHNodeNMB
|
||||
{
|
||||
NodeRef offset[BVH_NODE_N];
|
||||
float lower_t[BVH_NODE_N];
|
||||
float upper_t[BVH_NODE_N];
|
||||
float lower_x[BVH_NODE_N];
|
||||
float upper_x[BVH_NODE_N];
|
||||
float lower_y[BVH_NODE_N];
|
||||
float upper_y[BVH_NODE_N];
|
||||
float lower_z[BVH_NODE_N];
|
||||
float upper_z[BVH_NODE_N];
|
||||
float lower_dx[BVH_NODE_N];
|
||||
float upper_dx[BVH_NODE_N];
|
||||
float lower_dy[BVH_NODE_N];
|
||||
float upper_dy[BVH_NODE_N];
|
||||
float lower_dz[BVH_NODE_N];
|
||||
float upper_dz[BVH_NODE_N];
|
||||
|
||||
__forceinline AABB3f getBounds0(size_t i) const {
|
||||
AABB3f b( float3(lower_x[i],lower_y[i],lower_z[i]),
|
||||
float3(upper_x[i],upper_y[i],upper_z[i]) );
|
||||
return b;
|
||||
}
|
||||
|
||||
__forceinline AABB3f getBounds1(size_t i) const {
|
||||
AABB3f b( float3(lower_x[i]+lower_dx[i],lower_y[i]+lower_dy[i],lower_z[i]+lower_dz[i]),
|
||||
float3(upper_x[i]+upper_dx[i],upper_y[i]+upper_dy[i],upper_z[i]+upper_dz[i]) );
|
||||
return b;
|
||||
}
|
||||
|
||||
__forceinline AABB3f bounds0() const {
|
||||
AABB3f b;
|
||||
b.init();
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
b.extend(getBounds0(i));
|
||||
return b;
|
||||
}
|
||||
|
||||
__forceinline AABB3f bounds1() const {
|
||||
AABB3f b;
|
||||
b.init();
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
b.extend(getBounds1(i));
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__forceinline AABB3f bounds_lower(size_t i) const {
|
||||
const AABB3f b0 = getBounds0(i);
|
||||
const AABB3f b1 = getBounds1(i);
|
||||
const float t = lower_t[i];
|
||||
const float3 lower = gpu::lerp<float3>(b0.lower,b1.lower,t);
|
||||
const float3 upper = gpu::lerp<float3>(b0.upper,b1.upper,t);
|
||||
return AABB3f( lower, upper );
|
||||
}
|
||||
|
||||
__forceinline AABB3f bounds_upper(size_t i) const {
|
||||
const AABB3f b0 = getBounds0(i);
|
||||
const AABB3f b1 = getBounds1(i);
|
||||
const float t = upper_t[i];
|
||||
const float3 lower = gpu::lerp<float3>(b0.lower,b1.lower,t);
|
||||
const float3 upper = gpu::lerp<float3>(b0.upper,b1.upper,t);
|
||||
return AABB3f( lower, upper );
|
||||
}
|
||||
|
||||
__forceinline void clear()
|
||||
{
|
||||
for (size_t i=0;i<BVH_NODE_N;i++)
|
||||
{
|
||||
offset[i] = BVH_INVALID_NODE_REF;
|
||||
lower_t[i] = 1.0f;
|
||||
upper_t[i] = 0.0f;
|
||||
lower_x[i] = lower_y[i] = lower_z[i] = pos_inf;
|
||||
upper_x[i] = upper_y[i] = upper_z[i] = neg_inf;
|
||||
lower_dx[i] = lower_dy[i] = lower_dz[i] = pos_inf;
|
||||
upper_dx[i] = upper_dy[i] = upper_dz[i] = neg_inf;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline QBVHNodeNMB convert()
|
||||
{
|
||||
QBVHNodeNMB res;
|
||||
res.clear();
|
||||
|
||||
const AABB3f aabb0 = bounds0();
|
||||
const AABB3f aabb1 = bounds1();
|
||||
const float3 minF0 = aabb0.lower;
|
||||
const float3 minF1 = aabb1.lower;
|
||||
const float3 diff0 = aabb0.size()*(1.0f+2.0f*FLT_MIN);
|
||||
const float3 diff1 = aabb1.size()*(1.0f+2.0f*FLT_MIN);
|
||||
float3 decode_scale0 = diff0 / (float3)((float)QUANT_MAX);
|
||||
float3 decode_scale1 = diff1 / (float3)((float)QUANT_MAX);
|
||||
|
||||
decode_scale0 = cselect( decode_scale0 != 0.0f, decode_scale0, float3(2.0f*FLT_MIN) );
|
||||
decode_scale1 = cselect( decode_scale1 != 0.0f, decode_scale1, float3(2.0f*FLT_MIN) );
|
||||
|
||||
float3 encode_scale0 = (float3)((float)QUANT_MAX) / diff0;
|
||||
float3 encode_scale1 = (float3)((float)QUANT_MAX) / diff1;
|
||||
|
||||
encode_scale0 = cselect( diff0 > 0.0f, encode_scale0, float3(0.0f));
|
||||
encode_scale1 = cselect( diff1 > 0.0f, encode_scale1, float3(0.0f));
|
||||
|
||||
res.org0 = float4(minF0.x(),minF0.y(),minF0.z(),0.0f);
|
||||
res.org1 = float4(minF1.x(),minF1.y(),minF1.z(),0.0f);
|
||||
|
||||
res.scale0 = float4(decode_scale0.x(),decode_scale0.y(),decode_scale0.z(),0.0f);
|
||||
res.scale1 = float4(decode_scale1.x(),decode_scale1.y(),decode_scale1.z(),0.0f);
|
||||
|
||||
for (uint i=0;i<BVH_NODE_N;i++)
|
||||
{
|
||||
res.offset[i] = offset[i];
|
||||
res.lower_t[i] = lower_t[i];
|
||||
res.upper_t[i] = upper_t[i];
|
||||
|
||||
if (offset[i] == BVH_INVALID_NODE_REF) continue;
|
||||
|
||||
|
||||
const AABB3f child0 = getBounds0(i);
|
||||
const AABB3f child1 = getBounds1(i);
|
||||
|
||||
float3 lowerf0 = floor((child0.lower - minF0)*encode_scale0);
|
||||
float3 lowerf1 = floor((child1.lower - minF1)*encode_scale1);
|
||||
|
||||
float3 upperf0 = ceil((child0.upper - minF0)*encode_scale0);
|
||||
float3 upperf1 = ceil((child1.upper - minF1)*encode_scale1);
|
||||
|
||||
int3 ilower0 = max(lowerf0.convert<int,cl::sycl::rounding_mode::rtn>(),int3(QUANT_MIN));
|
||||
int3 ilower1 = max(lowerf1.convert<int,cl::sycl::rounding_mode::rtn>(),int3(QUANT_MIN));
|
||||
|
||||
int3 iupper0 = min(upperf0.convert<int,cl::sycl::rounding_mode::rtp>(),int3(QUANT_MAX));
|
||||
int3 iupper1 = min(upperf1.convert<int,cl::sycl::rounding_mode::rtp>(),int3(QUANT_MAX));
|
||||
|
||||
/* lower/upper correction */
|
||||
int3 m_lower_correction0 = (cl::sycl::fma(ilower0.convert<float,cl::sycl::rounding_mode::rtn>(),decode_scale0,minF0)) > child0.lower;
|
||||
int3 m_lower_correction1 = (cl::sycl::fma(ilower1.convert<float,cl::sycl::rounding_mode::rtn>(),decode_scale1,minF1)) > child1.lower;
|
||||
int3 m_upper_correction0 = (cl::sycl::fma(iupper0.convert<float,cl::sycl::rounding_mode::rtp>(),decode_scale0,minF0)) < child0.upper;
|
||||
int3 m_upper_correction1 = (cl::sycl::fma(iupper1.convert<float,cl::sycl::rounding_mode::rtp>(),decode_scale1,minF0)) < child1.upper;
|
||||
|
||||
ilower0 = max(cselect(m_lower_correction0,ilower0-1,ilower0),QUANT_MIN);
|
||||
ilower1 = max(cselect(m_lower_correction1,ilower1-1,ilower1),QUANT_MIN);
|
||||
|
||||
iupper0 = min(cselect(m_upper_correction0,iupper0+1,iupper0),QUANT_MAX);
|
||||
iupper1 = min(cselect(m_upper_correction1,iupper1+1,iupper1),QUANT_MAX);
|
||||
|
||||
/* disable invalid lanes */
|
||||
|
||||
/* ilower0 = cselect(int3(m_valid),ilower0,int3(QUANT_MAX)); */
|
||||
/* ilower1 = cselect(int3(m_valid),ilower1,int3(QUANT_MAX)); */
|
||||
|
||||
/* iupper0 = cselect(int3(m_valid),iupper0,int3(QUANT_MIN)); */
|
||||
/* iupper1 = cselect(int3(m_valid),iupper1,int3(QUANT_MIN)); */
|
||||
|
||||
assert( (float)ilower0.x() * res.scale0.x() + res.org0.x() <= child0.lower.x() );
|
||||
assert( (float)ilower0.y() * res.scale0.y() + res.org0.y() <= child0.lower.y() );
|
||||
assert( (float)ilower0.z() * res.scale0.z() + res.org0.z() <= child0.lower.z() );
|
||||
|
||||
assert( (float)iupper0.x() * res.scale0.x() + res.org0.x() >= child0.upper.x() );
|
||||
assert( (float)iupper0.y() * res.scale0.y() + res.org0.y() >= child0.upper.y() );
|
||||
assert( (float)iupper0.z() * res.scale0.z() + res.org0.z() >= child0.upper.z() );
|
||||
|
||||
assert( (float)ilower1.x() * res.scale1.x() + res.org1.x() <= child1.lower.x() );
|
||||
assert( (float)ilower1.y() * res.scale1.y() + res.org1.y() <= child1.lower.y() );
|
||||
assert( (float)ilower1.z() * res.scale1.z() + res.org1.z() <= child1.lower.z() );
|
||||
|
||||
assert( (float)iupper1.x() * res.scale1.x() + res.org1.x() >= child1.upper.x() );
|
||||
assert( (float)iupper1.y() * res.scale1.y() + res.org1.y() >= child1.upper.y() );
|
||||
assert( (float)iupper1.z() * res.scale1.z() + res.org1.z() >= child1.upper.z() );
|
||||
|
||||
|
||||
res.lower_x0[i] = ilower0.x();
|
||||
res.lower_y0[i] = ilower0.y();
|
||||
res.lower_z0[i] = ilower0.z();
|
||||
|
||||
res.lower_x1[i] = ilower1.x();
|
||||
res.lower_y1[i] = ilower1.y();
|
||||
res.lower_z1[i] = ilower1.z();
|
||||
|
||||
res.upper_x0[i] = iupper0.x();
|
||||
res.upper_y0[i] = iupper0.y();
|
||||
res.upper_z0[i] = iupper0.z();
|
||||
|
||||
res.upper_x1[i] = iupper1.x();
|
||||
res.upper_y1[i] = iupper1.y();
|
||||
res.upper_z1[i] = iupper1.z();
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/* =============================================================================== */
|
||||
/* ============================== NODE INTERSECTION =============================== */
|
||||
/* =============================================================================== */
|
||||
|
||||
struct NodeIntersectionData {
|
||||
__forceinline NodeIntersectionData(float dist, uint valid, uint offset) : dist(dist), valid(valid), offset(offset) {}
|
||||
float dist;
|
||||
uint valid;
|
||||
uint offset;
|
||||
};
|
||||
|
||||
__forceinline NodeIntersectionData intersectNode(const cl::sycl::intel::sub_group &sg,
|
||||
const QBVHNodeN &node,
|
||||
const Vec3i &dir_mask,
|
||||
const Vec3f &inv_dir,
|
||||
const Vec3f &inv_dir_org,
|
||||
const float time,
|
||||
const float tnear,
|
||||
const float tfar)
|
||||
{
|
||||
#if 0
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const gpu::QBVHNodeN &node = *(gpu::QBVHNodeN*)(bvh_base + cur);
|
||||
const uint offset = node.offset[subgroupLocalID];
|
||||
const Vec3f org = node.org.xyz();
|
||||
const Vec3f scale = node.scale.xyz();
|
||||
#else
|
||||
cl::sycl::multi_ptr<uint,cl::sycl::access::address_space::global_space> node_ptr((uint*)&node);
|
||||
const uint2 block0 = sg.load<2,uint>(node_ptr);
|
||||
const uint offset = (uint)block0.x();
|
||||
const Vec3f org(gpu::as_float(sg.broadcast<uint>((uint)block0.y(), 0)),
|
||||
gpu::as_float(sg.broadcast<uint>((uint)block0.y(), 1)),
|
||||
gpu::as_float(sg.broadcast<uint>((uint)block0.y(), 2)));
|
||||
const Vec3f scale(gpu::as_float(sg.broadcast<uint>((uint)block0.y(), 4)),
|
||||
gpu::as_float(sg.broadcast<uint>((uint)block0.y(), 5)),
|
||||
gpu::as_float(sg.broadcast<uint>((uint)block0.y(), 6)));
|
||||
#endif
|
||||
|
||||
cl::sycl::multi_ptr<ushort,cl::sycl::access::address_space::global_space> quant_ptr((ushort*)&node + 32); // + 64 bytes
|
||||
const ushort4 block1 = sg.load<4,ushort>(quant_ptr);
|
||||
const cl::sycl::uchar8 block2 = block1.as<cl::sycl::uchar8>();
|
||||
|
||||
const uchar3 ilower(block2.s2(),block2.s4(),block2.s6());
|
||||
const uchar3 iupper(block2.s3(),block2.s5(),block2.s7());
|
||||
const float3 lowerf_ = ilower.convert<float,cl::sycl::rounding_mode::rtn>();
|
||||
const float3 upperf_ = iupper.convert<float,cl::sycl::rounding_mode::rtp>();
|
||||
|
||||
const Vec3f lowerf(lowerf_.x(),lowerf_.y(),lowerf_.z());
|
||||
const Vec3f upperf(upperf_.x(),upperf_.y(),upperf_.z());
|
||||
const Vec3f _lower = madd(lowerf,scale,org);
|
||||
const Vec3f _upper = madd(upperf,scale,org);
|
||||
|
||||
const float lower_x = cselect((uint)dir_mask.x,(float)_upper.x,(float)_lower.x);
|
||||
const float upper_x = cselect((uint)dir_mask.x,(float)_lower.x,(float)_upper.x);
|
||||
const float lower_y = cselect((uint)dir_mask.y,(float)_upper.y,(float)_lower.y);
|
||||
const float upper_y = cselect((uint)dir_mask.y,(float)_lower.y,(float)_upper.y);
|
||||
const float lower_z = cselect((uint)dir_mask.z,(float)_upper.z,(float)_lower.z);
|
||||
const float upper_z = cselect((uint)dir_mask.z,(float)_lower.z,(float)_upper.z);
|
||||
|
||||
const float lowerX = madd((float)inv_dir.x, lower_x, (float)inv_dir_org.x);
|
||||
const float upperX = madd((float)inv_dir.x, upper_x, (float)inv_dir_org.x);
|
||||
const float lowerY = madd((float)inv_dir.y, lower_y, (float)inv_dir_org.y);
|
||||
const float upperY = madd((float)inv_dir.y, upper_y, (float)inv_dir_org.y);
|
||||
const float lowerZ = madd((float)inv_dir.z, lower_z, (float)inv_dir_org.z);
|
||||
const float upperZ = madd((float)inv_dir.z, upper_z, (float)inv_dir_org.z);
|
||||
|
||||
const float fnear = cl::sycl::fmax( cl::sycl::fmax(lowerX,lowerY), cl::sycl::fmax(lowerZ,tnear) );
|
||||
const float ffar = cl::sycl::fmin( cl::sycl::fmin(upperX,upperY), cl::sycl::fmin(upperZ,tfar) );
|
||||
const uint valid = (fnear <= ffar) & (offset != BVH_INVALID_NODE_REF); //((uchar)ilower.x() <= (uchar)iupper.x());
|
||||
return NodeIntersectionData(fnear, valid, offset);
|
||||
}
|
||||
|
||||
|
||||
__forceinline NodeIntersectionData intersectNode(const cl::sycl::intel::sub_group &sg,
|
||||
const QBVHNodeNMB &node,
|
||||
const Vec3i &dir_mask,
|
||||
const Vec3f &inv_dir,
|
||||
const Vec3f &inv_dir_org,
|
||||
const float time,
|
||||
const float tnear,
|
||||
const float tfar)
|
||||
{
|
||||
const uint subgroupLocalID = sg.get_local_id()[0];
|
||||
const uint offset = node.offset[subgroupLocalID];
|
||||
|
||||
const float time0 = node.lower_t[subgroupLocalID];
|
||||
const float time1 = node.upper_t[subgroupLocalID];
|
||||
|
||||
const Vec3f org0(node.org0.x(),node.org0.y(),node.org0.z());
|
||||
const Vec3f org1(node.org1.x(),node.org1.y(),node.org1.z());
|
||||
const Vec3f scale0(node.scale0.x(),node.scale0.y(),node.scale0.z());
|
||||
const Vec3f scale1(node.scale1.x(),node.scale1.y(),node.scale1.z());
|
||||
|
||||
|
||||
const uchar3 ilower0(node.lower_x0[subgroupLocalID],node.lower_y0[subgroupLocalID],node.lower_z0[subgroupLocalID]);
|
||||
const uchar3 ilower1(node.lower_x1[subgroupLocalID],node.lower_y1[subgroupLocalID],node.lower_z1[subgroupLocalID]);
|
||||
|
||||
const uchar3 iupper0(node.upper_x0[subgroupLocalID],node.upper_y0[subgroupLocalID],node.upper_z0[subgroupLocalID]);
|
||||
const uchar3 iupper1(node.upper_x1[subgroupLocalID],node.upper_y1[subgroupLocalID],node.upper_z1[subgroupLocalID]);
|
||||
|
||||
|
||||
const float3 lowerf0_ = ilower0.convert<float,cl::sycl::rounding_mode::rtn>();
|
||||
const float3 upperf0_ = iupper0.convert<float,cl::sycl::rounding_mode::rtp>();
|
||||
const float3 lowerf1_ = ilower1.convert<float,cl::sycl::rounding_mode::rtn>();
|
||||
const float3 upperf1_ = iupper1.convert<float,cl::sycl::rounding_mode::rtp>();
|
||||
|
||||
const Vec3f lowerf0(lowerf0_.x(),lowerf0_.y(),lowerf0_.z());
|
||||
const Vec3f upperf0(upperf0_.x(),upperf0_.y(),upperf0_.z());
|
||||
const Vec3f lowerf1(lowerf1_.x(),lowerf1_.y(),lowerf1_.z());
|
||||
const Vec3f upperf1(upperf1_.x(),upperf1_.y(),upperf1_.z());
|
||||
|
||||
const Vec3f lower0 = madd(lowerf0,scale0,org0);
|
||||
const Vec3f lower1 = madd(lowerf1,scale1,org1);
|
||||
const Vec3f upper0 = madd(upperf0,scale0,org0);
|
||||
const Vec3f upper1 = madd(upperf1,scale1,org1);
|
||||
|
||||
const float lower0_x = cselect((uint)dir_mask.x,(float)upper0.x,(float)lower0.x);
|
||||
const float upper0_x = cselect((uint)dir_mask.x,(float)lower0.x,(float)upper0.x);
|
||||
const float lower1_x = cselect((uint)dir_mask.x,(float)upper1.x,(float)lower1.x);
|
||||
const float upper1_x = cselect((uint)dir_mask.x,(float)lower1.x,(float)upper1.x);
|
||||
|
||||
const float lower0_y = cselect((uint)dir_mask.y,(float)upper0.y,(float)lower0.y);
|
||||
const float upper0_y = cselect((uint)dir_mask.y,(float)lower0.y,(float)upper0.y);
|
||||
const float lower1_y = cselect((uint)dir_mask.y,(float)upper1.y,(float)lower1.y);
|
||||
const float upper1_y = cselect((uint)dir_mask.y,(float)lower1.y,(float)upper1.y);
|
||||
|
||||
const float lower0_z = cselect((uint)dir_mask.z,(float)upper0.z,(float)lower0.z);
|
||||
const float upper0_z = cselect((uint)dir_mask.z,(float)lower0.z,(float)upper0.z);
|
||||
const float lower1_z = cselect((uint)dir_mask.z,(float)upper1.z,(float)lower1.z);
|
||||
const float upper1_z = cselect((uint)dir_mask.z,(float)lower1.z,(float)upper1.z);
|
||||
|
||||
const float lower_x = lerp(lower0_x,lower1_x,time);
|
||||
const float upper_x = lerp(upper0_x,upper1_x,time);
|
||||
const float lower_y = lerp(lower0_y,lower1_y,time);
|
||||
const float upper_y = lerp(upper0_y,upper1_y,time);
|
||||
const float lower_z = lerp(lower0_z,lower1_z,time);
|
||||
const float upper_z = lerp(upper0_z,upper1_z,time);
|
||||
|
||||
const float lowerX = madd((float)inv_dir.x, lower_x, (float)inv_dir_org.x);
|
||||
const float upperX = madd((float)inv_dir.x, upper_x, (float)inv_dir_org.x);
|
||||
const float lowerY = madd((float)inv_dir.y, lower_y, (float)inv_dir_org.y);
|
||||
const float upperY = madd((float)inv_dir.y, upper_y, (float)inv_dir_org.y);
|
||||
const float lowerZ = madd((float)inv_dir.z, lower_z, (float)inv_dir_org.z);
|
||||
const float upperZ = madd((float)inv_dir.z, upper_z, (float)inv_dir_org.z);
|
||||
|
||||
const float fnear = cl::sycl::fmax( cl::sycl::fmax(lowerX,lowerY), cl::sycl::fmax(lowerZ,tnear) );
|
||||
const float ffar = cl::sycl::fmin( cl::sycl::fmin(upperX,upperY), cl::sycl::fmin(upperZ,tfar) );
|
||||
const uint valid = (fnear <= ffar) & (offset != BVH_INVALID_NODE_REF) & (time0 <= time) & (time < time1);
|
||||
|
||||
return NodeIntersectionData(fnear, valid, offset);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#define CL_TARGET_OPENCL_VERSION 220
|
||||
#define SYCL_SIMPLE_SWIZZLES
|
||||
#include <CL/sycl.hpp>
|
||||
#include <CL/sycl/builtins.hpp>
|
||||
|
||||
|
||||
#ifdef __SYCL_DEVICE_ONLY__
|
||||
#define GLOBAL __attribute__((opencl_global))
|
||||
#define LOCAL __attribute__((opencl_local))
|
||||
|
||||
extern int work_group_reduce_add(int x);
|
||||
extern float work_group_reduce_min(float x);
|
||||
extern float work_group_reduce_max(float x);
|
||||
|
||||
//extern uint cl_intel_sub_group_ballot(bool valid);
|
||||
|
||||
extern float atomic_min(volatile GLOBAL float *p, float val);
|
||||
extern float atomic_min(volatile LOCAL float *p, float val);
|
||||
extern float atomic_max(volatile GLOBAL float *p, float val);
|
||||
extern float atomic_max(volatile LOCAL float *p, float val);
|
||||
|
||||
extern "C" uint intel_sub_group_ballot(bool valid);
|
||||
|
||||
#else
|
||||
#define GLOBAL
|
||||
#define LOCAL
|
||||
|
||||
/* dummy functions for host */
|
||||
inline int work_group_reduce_add(int x) { return x; }
|
||||
inline float work_group_reduce_min(float x) { return x; }
|
||||
inline float work_group_reduce_max(float x) { return x; }
|
||||
|
||||
inline float atomic_min(volatile float *p, float val) { return val; };
|
||||
inline float atomic_max(volatile float *p, float val) { return val; };
|
||||
|
||||
inline uint intel_sub_group_ballot(bool valid) { return 0; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
constexpr cl::sycl::access::target sycl_local = cl::sycl::access::target::local;
|
||||
constexpr cl::sycl::access::mode sycl_read_write = cl::sycl::access::mode::read_write;
|
||||
constexpr cl::sycl::access::mode sycl_read = cl::sycl::access::mode::read;
|
||||
constexpr cl::sycl::access::mode sycl_write = cl::sycl::access::mode::write;
|
||||
|
||||
using cl::sycl::float16;
|
||||
using cl::sycl::float8;
|
||||
using cl::sycl::float4;
|
||||
using cl::sycl::float3;
|
||||
using cl::sycl::float2;
|
||||
using cl::sycl::int16;
|
||||
using cl::sycl::int8;
|
||||
using cl::sycl::int4;
|
||||
using cl::sycl::int3;
|
||||
using cl::sycl::int2;
|
||||
using cl::sycl::uint16;
|
||||
using cl::sycl::uint8;
|
||||
using cl::sycl::uint4;
|
||||
using cl::sycl::uint3;
|
||||
using cl::sycl::uint2;
|
||||
using cl::sycl::uchar16;
|
||||
using cl::sycl::uchar8;
|
||||
using cl::sycl::uchar4;
|
||||
using cl::sycl::uchar3;
|
||||
using cl::sycl::uchar2;
|
||||
using cl::sycl::uchar;
|
||||
using cl::sycl::ushort16;
|
||||
using cl::sycl::ushort8;
|
||||
using cl::sycl::ushort4;
|
||||
using cl::sycl::ushort3;
|
||||
using cl::sycl::ushort2;
|
||||
|
||||
using cl::sycl::fmax;
|
||||
using cl::sycl::fmin;
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
template<typename T, typename M>
|
||||
__forceinline T cselect(const M &mask, const T &a, const T &b)
|
||||
{
|
||||
return cl::sycl::select(b,a,mask);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline T cfma(const T &a, const T &b, const T &c)
|
||||
{
|
||||
return cl::sycl::fma(a,b,c);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline T lerp(const T &a, const T &b, const float t) {
|
||||
return cl::sycl::fma(T(1.0f-t),a,T(t)*b);
|
||||
}
|
||||
|
||||
|
||||
__forceinline float halfarea(const cl::sycl::float3 &d)
|
||||
{
|
||||
return cl::sycl::fma((float)d.x(),((float)d.y()+(float)d.z()),(float)d.y()*(float)d.z());
|
||||
}
|
||||
|
||||
__forceinline float halfarea(const cl::sycl::float4 &d)
|
||||
{
|
||||
return cl::sycl::fma((float)d.x(),((float)d.y()+(float)d.z()),(float)d.y()*(float)d.z());
|
||||
}
|
||||
|
||||
__forceinline float area(const cl::sycl::float3 &d)
|
||||
{
|
||||
return halfarea(d) * 2.0f;
|
||||
}
|
||||
|
||||
__forceinline float area(const cl::sycl::float4 &d)
|
||||
{
|
||||
return halfarea(d) * 2.0f;
|
||||
}
|
||||
|
||||
__forceinline float dot3(const float3 &a,
|
||||
const float3 &b)
|
||||
{
|
||||
return cl::sycl::dot(a,b);
|
||||
}
|
||||
|
||||
template<typename T, cl::sycl::access::address_space space>
|
||||
static __forceinline uint atomic_add(T *dest, const T count=1)
|
||||
{
|
||||
cl::sycl::multi_ptr<T,space> ptr(dest);
|
||||
cl::sycl::atomic<T,space> counter(ptr);
|
||||
return atomic_fetch_add(counter,count);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static __forceinline uint as_uint(T t)
|
||||
{
|
||||
return __builtin_bit_cast(uint,t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static __forceinline uint as_int(T t)
|
||||
{
|
||||
return __builtin_bit_cast(int,t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static __forceinline float as_float(T t)
|
||||
{
|
||||
return __builtin_bit_cast(float,t);
|
||||
}
|
||||
|
||||
__forceinline uint bitInterleave(const uint4 in)
|
||||
{
|
||||
uint x = in.x(), y = in.y(), z = in.z();
|
||||
x = (x | (x << 16)) & 0x030000FF;
|
||||
x = (x | (x << 8)) & 0x0300F00F;
|
||||
x = (x | (x << 4)) & 0x030C30C3;
|
||||
x = (x | (x << 2)) & 0x09249249;
|
||||
|
||||
y = (y | (y << 16)) & 0x030000FF;
|
||||
y = (y | (y << 8)) & 0x0300F00F;
|
||||
y = (y | (y << 4)) & 0x030C30C3;
|
||||
y = (y | (y << 2)) & 0x09249249;
|
||||
|
||||
z = (z | (z << 16)) & 0x030000FF;
|
||||
z = (z | (z << 8)) & 0x0300F00F;
|
||||
z = (z | (z << 4)) & 0x030C30C3;
|
||||
z = (z | (z << 2)) & 0x09249249;
|
||||
|
||||
return x | (y << 1) | (z << 2);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,337 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#include "common.h"
|
||||
#include "AABB.h"
|
||||
#include "ray.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
|
||||
struct __aligned(16) Quad1v
|
||||
{
|
||||
float4 v0,v2,v1,v3; //special optimized layout
|
||||
|
||||
inline void init(const float4 &_v0,
|
||||
const float4 &_v1,
|
||||
const float4 &_v2,
|
||||
const float4 &_v3,
|
||||
const uint geomID,
|
||||
const uint primID)
|
||||
{
|
||||
v0 = _v0;
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
v3 = _v3;
|
||||
v0.w() = 0.0f;
|
||||
v2.w() = 0.0f;
|
||||
v1.w() = as_float(geomID);
|
||||
v3.w() = as_float(primID);
|
||||
}
|
||||
|
||||
inline AABB getBounds()
|
||||
{
|
||||
AABB aabb;
|
||||
aabb.init();
|
||||
aabb.extend(v0);
|
||||
aabb.extend(v1);
|
||||
aabb.extend(v2);
|
||||
aabb.extend(v3);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const Quad1v& quad) {
|
||||
return out << "v0 " << quad.v0
|
||||
<< "v1 " << quad.v1
|
||||
<< "v2 " << quad.v2
|
||||
<< "v3 " << quad.v3
|
||||
<< "geomID " << gpu::as_int((float)quad.v1.w())
|
||||
<< "primID0 " << gpu::as_int((float)quad.v0.w())
|
||||
<< "primID1 " << gpu::as_int((float)quad.v2.w());
|
||||
}
|
||||
|
||||
struct __aligned(16) Triangle1v
|
||||
{
|
||||
float4 v0,v1,v2;
|
||||
|
||||
inline void init(const float4 &_v0,
|
||||
const float4 &_v1,
|
||||
const float4 &_v2,
|
||||
const uint geomID,
|
||||
const uint primID)
|
||||
{
|
||||
v0 = _v0;
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
v0.w() = as_float(primID);
|
||||
v1.w() = as_float(geomID);
|
||||
v2.w() = 0.0f;
|
||||
}
|
||||
|
||||
inline AABB getBounds()
|
||||
{
|
||||
AABB aabb;
|
||||
aabb.init();
|
||||
aabb.extend(v0);
|
||||
aabb.extend(v1);
|
||||
aabb.extend(v2);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const Triangle1v& tri) {
|
||||
return out << "v0 " << tri.v0
|
||||
<< "v1 " << tri.v1
|
||||
<< "v2 " << tri.v2
|
||||
<< "geomID " << gpu::as_int((float)tri.v1.w())
|
||||
<< "primID " << gpu::as_int((float)tri.v0.w());
|
||||
}
|
||||
|
||||
inline float intersectPrimitive1v(const cl::sycl::intel::sub_group &sg,
|
||||
const gpu::Quad1v *const quad1v,
|
||||
const uint numQuads,
|
||||
const Vec3f &org,
|
||||
const Vec3f &dir,
|
||||
const float time,
|
||||
const float tnear,
|
||||
const float tfar,
|
||||
gpu::RTCHitGPU &hit,
|
||||
const unsigned int slotID)
|
||||
{
|
||||
float new_tfar = tfar;
|
||||
const uint quadID = slotID >> 1;
|
||||
|
||||
if (slotID < numQuads*2)
|
||||
{
|
||||
#if 0
|
||||
const float4 _v0 = cselect((int)((slotID % 2) == 0),quad1v[quadID].v0,quad1v[quadID].v2);
|
||||
#else
|
||||
const float4 *const _v0_ptr = (float4*)&quad1v[quadID];
|
||||
const float4 _v0 = _v0_ptr[slotID & 1];
|
||||
#endif
|
||||
const float4 _v1 = quad1v[quadID].v1;
|
||||
const float4 _v2 = quad1v[quadID].v3;
|
||||
const uint geomID = gpu::as_uint((float)_v1.w());
|
||||
const uint primID = gpu::as_uint((float)_v2.w());
|
||||
const Vec3f v0(_v0.x(), _v0.y(), _v0.z());
|
||||
const Vec3f v1(_v1.x(), _v1.y(), _v1.z());
|
||||
const Vec3f v2(_v2.x(), _v2.y(), _v2.z());
|
||||
|
||||
/* moeller-trumbore test */
|
||||
const Vec3f e1 = v0 - v1;
|
||||
const Vec3f e2 = v2 - v0;
|
||||
const Vec3f tri_Ng = cross(e1,e2);
|
||||
const float den = dot(tri_Ng,dir);
|
||||
const float inv_den = rcp(den);
|
||||
const Vec3f tri_v0_org = v0 - org;
|
||||
const Vec3f R = cross(dir,tri_v0_org);
|
||||
const float u = dot(R,e2) * inv_den;
|
||||
const float v = dot(R,e1) * inv_den;
|
||||
float t = dot(tri_v0_org,tri_Ng) * inv_den;
|
||||
int m_hit = (u >= 0.0f) & (v >= 0.0f) & (u+v <= 1.0f);
|
||||
//if (m_hit == 0) return; // early out
|
||||
m_hit &= (tnear <= t) & (t <= tfar); // den != 0.0f &&
|
||||
if (m_hit)
|
||||
{
|
||||
new_tfar = t;
|
||||
hit.Ng.x = tri_Ng.x;
|
||||
hit.Ng.y = tri_Ng.y;
|
||||
hit.Ng.z = tri_Ng.z;
|
||||
hit.u = u;
|
||||
hit.v = v;
|
||||
hit.primID = primID;
|
||||
hit.geomID = geomID;
|
||||
}
|
||||
}
|
||||
return new_tfar;
|
||||
}
|
||||
|
||||
|
||||
inline float intersectPrimitive1v(const cl::sycl::intel::sub_group &sg,
|
||||
const gpu::Triangle1v *const tri1v,
|
||||
const uint numTris,
|
||||
const Vec3f &org,
|
||||
const Vec3f &dir,
|
||||
const float time,
|
||||
const float tnear,
|
||||
const float tfar,
|
||||
gpu::RTCHitGPU &hit,
|
||||
const unsigned int slotID)
|
||||
{
|
||||
float new_tfar = tfar;
|
||||
if (slotID < numTris)
|
||||
{
|
||||
const float4 _v0 = tri1v[slotID].v0;
|
||||
const float4 _v1 = tri1v[slotID].v1;
|
||||
const float4 _v2 = tri1v[slotID].v2;
|
||||
const uint geomID = gpu::as_uint(_v1.w());
|
||||
const uint primID = gpu::as_uint(_v2.w());
|
||||
const Vec3f v0(_v0.x(), _v0.y(), _v0.z());
|
||||
const Vec3f v1(_v1.x(), _v1.y(), _v1.z());
|
||||
const Vec3f v2(_v2.x(), _v2.y(), _v2.z());
|
||||
|
||||
/* moeller-trumbore test */
|
||||
const Vec3f e1 = v0 - v1;
|
||||
const Vec3f e2 = v2 - v0;
|
||||
const Vec3f tri_Ng = cross(e1,e2);
|
||||
const float den = dot(tri_Ng,dir);
|
||||
const float inv_den = rcp(den);
|
||||
const Vec3f tri_v0_org = v0 - org;
|
||||
const Vec3f R = cross(dir,tri_v0_org);
|
||||
const float u = dot(R,e2) * inv_den;
|
||||
const float v = dot(R,e1) * inv_den;
|
||||
float t = dot(tri_v0_org,tri_Ng) * inv_den;
|
||||
int m_hit = (u >= 0.0f) & (v >= 0.0f) & (u+v <= 1.0f);
|
||||
//if (m_hit == 0) return; // early out
|
||||
m_hit &= (tnear <= t) & (t <= tfar); // den != 0.0f &&
|
||||
if (m_hit)
|
||||
{
|
||||
new_tfar = t;
|
||||
hit.Ng.x = tri_Ng.x;
|
||||
hit.Ng.y = tri_Ng.y;
|
||||
hit.Ng.z = tri_Ng.z;
|
||||
hit.u = u;
|
||||
hit.v = v;
|
||||
hit.primID = primID;
|
||||
hit.geomID = geomID;
|
||||
}
|
||||
}
|
||||
return new_tfar;
|
||||
}
|
||||
|
||||
struct __aligned(16) Triangle1vMB
|
||||
{
|
||||
float4 v0,v1,v2; //special optimized layout
|
||||
float4 d0,d1,d2;
|
||||
};
|
||||
|
||||
|
||||
struct __aligned(16) Quad1vMB
|
||||
{
|
||||
float4 v0,v2,v1,v3; //special optimized layout
|
||||
float4 d0,d2,d1,d3;
|
||||
};
|
||||
|
||||
inline float intersectPrimitive1v(const cl::sycl::intel::sub_group &sg,
|
||||
const gpu::Triangle1vMB *const tri1v,
|
||||
const uint numTris,
|
||||
const Vec3f &org,
|
||||
const Vec3f &dir,
|
||||
const float time,
|
||||
const float tnear,
|
||||
const float tfar,
|
||||
gpu::RTCHitGPU &hit,
|
||||
const unsigned int slotID)
|
||||
{
|
||||
float new_tfar = tfar;
|
||||
if (slotID < numTris)
|
||||
{
|
||||
const float4 time0_v0 = tri1v[slotID].v0;
|
||||
const float4 time0_v1 = tri1v[slotID].v1;
|
||||
const float4 time0_v2 = tri1v[slotID].v2;
|
||||
|
||||
const uint geomID = gpu::as_uint(time0_v1.w());
|
||||
const uint primID = gpu::as_uint(time0_v2.w());
|
||||
|
||||
const float4 time1_v0 = tri1v[slotID].d0;
|
||||
const float4 time1_v1 = tri1v[slotID].d1;
|
||||
const float4 time1_v2 = tri1v[slotID].d2;
|
||||
|
||||
const float4 _v0 = cl::sycl::fma(time1_v0,float4(time),time0_v0);
|
||||
const float4 _v1 = cl::sycl::fma(time1_v1,float4(time),time0_v1);
|
||||
const float4 _v2 = cl::sycl::fma(time1_v2,float4(time),time0_v2);
|
||||
|
||||
#if 0
|
||||
if (slotID == 0)
|
||||
{
|
||||
out << "time0_v0 " << time0_v0 << cl::sycl::endl;
|
||||
out << "time0_v1 " << time0_v1 << cl::sycl::endl;
|
||||
out << "time0_v2 " << time0_v2 << cl::sycl::endl;
|
||||
|
||||
out << "time1_v0 " << time1_v0 << cl::sycl::endl;
|
||||
out << "time1_v1 " << time1_v1 << cl::sycl::endl;
|
||||
out << "time1_v2 " << time1_v2 << cl::sycl::endl;
|
||||
|
||||
out << "_v0 " << _v0 << cl::sycl::endl;
|
||||
out << "_v1 " << _v1 << cl::sycl::endl;
|
||||
out << "_v2 " << _v2 << cl::sycl::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Vec3f v0(_v0.x(), _v0.y(), _v0.z());
|
||||
const Vec3f v1(_v1.x(), _v1.y(), _v1.z());
|
||||
const Vec3f v2(_v2.x(), _v2.y(), _v2.z());
|
||||
|
||||
/* moeller-trumbore test */
|
||||
const Vec3f e1 = v0 - v1;
|
||||
const Vec3f e2 = v2 - v0;
|
||||
const Vec3f tri_Ng = cross(e1,e2);
|
||||
const float den = dot(tri_Ng,dir);
|
||||
const float inv_den = rcp(den);
|
||||
const Vec3f tri_v0_org = v0 - org;
|
||||
const Vec3f R = cross(dir,tri_v0_org);
|
||||
const float u = dot(R,e2) * inv_den;
|
||||
const float v = dot(R,e1) * inv_den;
|
||||
float t = dot(tri_v0_org,tri_Ng) * inv_den;
|
||||
int m_hit = (u >= 0.0f) & (v >= 0.0f) & (u+v <= 1.0f);
|
||||
//if (m_hit == 0) return; // early out
|
||||
m_hit &= (tnear <= t) & (t <= tfar); // den != 0.0f &&
|
||||
if (m_hit)
|
||||
{
|
||||
new_tfar = t;
|
||||
hit.Ng.x = tri_Ng.x;
|
||||
hit.Ng.y = tri_Ng.y;
|
||||
hit.Ng.z = tri_Ng.z;
|
||||
hit.u = u;
|
||||
hit.v = v;
|
||||
hit.primID = primID;
|
||||
hit.geomID = geomID;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return new_tfar;
|
||||
}
|
||||
|
||||
inline float intersectPrimitive1v(const cl::sycl::intel::sub_group &sg,
|
||||
const gpu::Quad1vMB *const quad1v,
|
||||
const uint numTris,
|
||||
const Vec3f &org,
|
||||
const Vec3f &dir,
|
||||
const float time,
|
||||
const float tnear,
|
||||
const float tfar,
|
||||
gpu::RTCHitGPU &hit,
|
||||
const unsigned int slotID)
|
||||
{
|
||||
float new_tfar = tfar;
|
||||
/* not yet implemented */
|
||||
return new_tfar;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2019 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 "../common/ray.h"
|
||||
|
||||
#if defined(EMBREE_DPCPP_SUPPORT)
|
||||
#include "common.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
// FIXME: can't use float3 here due to stupid size/alignment restriction
|
||||
|
||||
/* Ray structure for a single ray */
|
||||
struct RTCRayGPU : public Ray
|
||||
{
|
||||
inline Vec3f get_org() {
|
||||
return Vec3f(org.x,org.y,org.z);
|
||||
}
|
||||
|
||||
inline Vec3f get_dir() {
|
||||
return Vec3f(dir.x,dir.y,dir.z);
|
||||
}
|
||||
|
||||
inline Vec3f broadcast_org(const cl::sycl::intel::sub_group &subgroup, const uint index) {
|
||||
return Vec3f(subgroup.broadcast<float>(org.x,index),
|
||||
subgroup.broadcast<float>(org.y,index),
|
||||
subgroup.broadcast<float>(org.z,index));
|
||||
}
|
||||
|
||||
inline Vec3f broadcast_dir(const cl::sycl::intel::sub_group &subgroup, const uint index) {
|
||||
return Vec3f(subgroup.broadcast<float>(dir.x,index),
|
||||
subgroup.broadcast<float>(dir.y,index),
|
||||
subgroup.broadcast<float>(dir.z,index));
|
||||
}
|
||||
|
||||
inline float broadcast_tnear(const cl::sycl::intel::sub_group &subgroup, const uint index) { return subgroup.broadcast<float>(tnear(),index); }
|
||||
inline float broadcast_tfar (const cl::sycl::intel::sub_group &subgroup, const uint index) { return subgroup.broadcast<float>(tfar ,index); }
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* Hit structure for a single ray */
|
||||
struct RTCHitGPU : public Hit
|
||||
{
|
||||
inline void init()
|
||||
{
|
||||
primID = -1;
|
||||
geomID = -1;
|
||||
}
|
||||
|
||||
inline void broadcast(const cl::sycl::intel::sub_group &subgroup, const uint index)
|
||||
{
|
||||
Ng.x = subgroup.broadcast<float>(Ng.x,index);
|
||||
Ng.y = subgroup.broadcast<float>(Ng.y,index);
|
||||
Ng.z = subgroup.broadcast<float>(Ng.z,index);
|
||||
u = subgroup.broadcast<float>(u,index);
|
||||
v = subgroup.broadcast<float>(v,index);
|
||||
primID = subgroup.broadcast<unsigned int>(primID,index);
|
||||
geomID = subgroup.broadcast<unsigned int>(geomID,index);
|
||||
//instID = subgroup.broadcast<unsigned int>(instID,index);
|
||||
}
|
||||
|
||||
inline void store(RTCHit &dest)
|
||||
{
|
||||
dest.Ng_x = Ng.x;
|
||||
dest.Ng_y = Ng.y;
|
||||
dest.Ng_z = Ng.z;
|
||||
dest.u = u;
|
||||
dest.v = v;
|
||||
dest.primID = primID;
|
||||
dest.geomID = geomID;
|
||||
//dest.instID[0] = instID[0];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/* Combined ray/hit structure for a single ray */
|
||||
struct RTCRayHitGPU
|
||||
{
|
||||
struct RTCRayGPU ray;
|
||||
struct RTCHitGPU hit;
|
||||
};
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const RTCHitGPU& hit) {
|
||||
return out << " Ng " << float3(hit.Ng.x,hit.Ng.y,hit.Ng.z)
|
||||
<< " u " << hit.u
|
||||
<< " v " << hit.v
|
||||
<< " primID " << hit.primID
|
||||
<< " geomID " << hit.geomID
|
||||
<< " instID " << hit.instID;
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline const cl::sycl::stream &operator<<(const cl::sycl::stream &out, const RTCRayGPU& ray) {
|
||||
return out << " org " << float3(ray.org.x,ray.org.y,ray.org.z)
|
||||
<< " tnear " << ray.tnear()
|
||||
<< " dir " << float3(ray.dir.x,ray.dir.y,ray.dir.z)
|
||||
<< " tnear " << ray.tfar;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -81,10 +81,11 @@ ADD_SUBDIRECTORY(bvh_access)
|
||||
ADD_SUBDIRECTORY(minimal)
|
||||
ADD_SUBDIRECTORY(motion_blur_geometry)
|
||||
ADD_SUBDIRECTORY(interpolation)
|
||||
ADD_SUBDIRECTORY(convert)
|
||||
ADD_SUBDIRECTORY(curve_geometry)
|
||||
ADD_SUBDIRECTORY(point_geometry)
|
||||
ADD_SUBDIRECTORY(buildbench)
|
||||
ADD_SUBDIRECTORY(convert)
|
||||
ADD_SUBDIRECTORY(viewer_gpu)
|
||||
ADD_SUBDIRECTORY(closest_point)
|
||||
ADD_SUBDIRECTORY(voronoi)
|
||||
ADD_SUBDIRECTORY(next_hit)
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ISPC_UINT_IS_DEFINED
|
||||
typedef unsigned int64 uint64;
|
||||
typedef unsigned int32 uint32;
|
||||
typedef unsigned int16 uint16;
|
||||
typedef unsigned int8 uint8;
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace embree
|
||||
start_time(getSeconds()),
|
||||
last_time(start_time),
|
||||
last_virtual_memory(0),
|
||||
last_resident_memory(0)
|
||||
last_resident_memory(0),
|
||||
features((Features)features)
|
||||
{
|
||||
if (instance)
|
||||
throw std::runtime_error("internal error: applicaton already created");
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace embree
|
||||
class Application
|
||||
{
|
||||
public:
|
||||
enum Features { FEATURE_RTCORE = 1, FEATURE_STREAM = 2 };
|
||||
enum Features { FEATURE_RTCORE = 1, FEATURE_STREAM = 2, FEATURE_SYCL = 4 };
|
||||
|
||||
Application (int features);
|
||||
virtual ~Application();
|
||||
@@ -93,6 +93,7 @@ namespace embree
|
||||
public:
|
||||
std::string rtcore; // embree configuration
|
||||
int verbosity; // verbosity of output
|
||||
Features features;
|
||||
|
||||
public:
|
||||
bool log_delta; // whether to print delta stats
|
||||
|
||||
@@ -35,12 +35,17 @@
|
||||
#include "../scenegraph/xml_loader.h"
|
||||
#include "../image/image.h"
|
||||
|
||||
#include <CL/sycl.hpp>
|
||||
|
||||
namespace embree
|
||||
{
|
||||
extern cl::sycl::queue *global_gpu_queue;
|
||||
extern cl::sycl::device *global_gpu_device;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
RTCDevice g_device = nullptr;
|
||||
|
||||
|
||||
float g_debug = 0.0f;
|
||||
Mode g_mode = MODE_NORMAL;
|
||||
ISPCScene* g_ispc_scene = nullptr;
|
||||
@@ -94,8 +99,8 @@ namespace embree
|
||||
|
||||
shader(SHADER_DEFAULT),
|
||||
|
||||
width(512),
|
||||
height(512),
|
||||
width(1024),
|
||||
height(1024),
|
||||
pixels(nullptr),
|
||||
|
||||
outputImageFilename(""),
|
||||
@@ -108,8 +113,8 @@ namespace embree
|
||||
interactive(true),
|
||||
fullscreen(false),
|
||||
|
||||
window_width(512),
|
||||
window_height(512),
|
||||
window_width(1024),
|
||||
window_height(1024),
|
||||
window(nullptr),
|
||||
|
||||
time0(getSeconds()),
|
||||
@@ -1122,6 +1127,36 @@ namespace embree
|
||||
}
|
||||
}
|
||||
|
||||
class NEOGPUDeviceSelector : public cl::sycl::device_selector {
|
||||
public:
|
||||
int operator()(const cl::sycl::device &Device) const override {
|
||||
using namespace cl::sycl::info;
|
||||
|
||||
const std::string DeviceName = Device.get_info<device::name>();
|
||||
const std::string DeviceVendor = Device.get_info<device::vendor>();
|
||||
return Device.is_gpu() && DeviceName.find("HD Graphics NEO") ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
class CPUDeviceSelector : public cl::sycl::device_selector {
|
||||
public:
|
||||
int operator()(const cl::sycl::device &Device) const override {
|
||||
return Device.is_cpu() ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
auto exception_handler = [] (cl::sycl::exception_list exceptions) {
|
||||
for (std::exception_ptr const& e : exceptions) {
|
||||
try {
|
||||
std::rethrow_exception(e);
|
||||
} catch(cl::sycl::exception const& e) {
|
||||
std::cout << "Caught asynchronous SYCL exception:\n"
|
||||
<< e.what() << std::endl;
|
||||
FATAL("OpenCL Exception");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int TutorialApplication::main(int argc, char** argv) try
|
||||
{
|
||||
/* parse command line options */
|
||||
@@ -1130,10 +1165,19 @@ namespace embree
|
||||
/* callback */
|
||||
postParseCommandLine();
|
||||
|
||||
/* create device */
|
||||
g_device = rtcNewDevice(rtcore.c_str());
|
||||
error_handler(nullptr,rtcGetDeviceError(g_device));
|
||||
|
||||
if (features & FEATURE_SYCL)
|
||||
{
|
||||
global_gpu_device = new cl::sycl::device(NEOGPUDeviceSelector());
|
||||
global_gpu_queue = new cl::sycl::queue(NEOGPUDeviceSelector(), exception_handler);
|
||||
g_device = rtcNewDeviceGPU(rtcore.c_str(),global_gpu_device,global_gpu_queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create device */
|
||||
g_device = rtcNewDevice(rtcore.c_str());
|
||||
error_handler(nullptr,rtcGetDeviceError(g_device));
|
||||
}
|
||||
|
||||
/* set error handler */
|
||||
rtcSetDeviceErrorFunction(g_device,error_handler,nullptr);
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
ADD_LIBRARY(sycl_test_static_lib STATIC sycl_test_static_lib.cpp)
|
||||
|
||||
ADD_EXECUTABLE(sycl_test sycl_test.cpp)
|
||||
TARGET_LINK_LIBRARIES(sycl_test sycl_test_static_lib)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -foffload-static-lib=../../libsycl_test_static_lib.a")
|
||||
#SET_TARGET_PROPERTIES(sycl_test PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}")
|
||||
@@ -0,0 +1 @@
|
||||
build/
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
project("Test SYCL with shared libraries" CXX)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsycl")
|
||||
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_FLAGS} -lsycl")
|
||||
|
||||
add_library(mylib SHARED lib.cpp)
|
||||
|
||||
add_executable(myapp main.cpp)
|
||||
|
||||
target_link_libraries(myapp mylib)
|
||||
@@ -0,0 +1,100 @@
|
||||
# sycl-library
|
||||
|
||||
This simple project provides an example how to create a shared library that
|
||||
contains SYCL device code which can be used by another SYCL device code from an
|
||||
application which is linked with this shared library.
|
||||
|
||||
Basically, I was able to create such app and library and everything is even
|
||||
works correctly on CPU (haven't tested on GPU yet), but strictly speaking, SYCL
|
||||
spec doesn't guarantee that this code will work correctly. See section with
|
||||
issues below.
|
||||
|
||||
Project structure:
|
||||
|
||||
* `main.cpp` contains application host code and one SYCL kernel that calls two
|
||||
payload functions: one is defined in the same translation unit and another one
|
||||
is expected to be linked from shared library containing some device code
|
||||
* `lib.cpp` contains library host code and function marked with `SYCL_EXTERNAL`
|
||||
|
||||
Host application compiles a program, then extracts another compiled program from
|
||||
a shared library, links them together and launches kernel which calls function
|
||||
defined in the shared library.
|
||||
|
||||
### How to build
|
||||
|
||||
```
|
||||
mkdir build && cd build/
|
||||
cmake -DCMAKE_CXX_COMPILER=/path/to/sycl/clang++ ..
|
||||
make
|
||||
```
|
||||
|
||||
### How to launch
|
||||
|
||||
```
|
||||
./myapp
|
||||
```
|
||||
|
||||
Expected output is:
|
||||
|
||||
```
|
||||
Result: 0
|
||||
```
|
||||
|
||||
## Issues
|
||||
|
||||
### It is unclear how to compile a device code without kernels
|
||||
|
||||
For example, there is `lib_calculate` function in `lib.cpp` which is marked as
|
||||
`SYCL_EXTERNAL` and intended to be the only thing which is available in device
|
||||
code of shared library.
|
||||
|
||||
The question is how to get `cl::sycl::program` object in
|
||||
`program_state::compiled` state which contains `lib_calculate` function?
|
||||
|
||||
Note: compiled state is required for subsequent linkage with device code from
|
||||
an application.
|
||||
|
||||
How can we do that?
|
||||
|
||||
1. Create SYCL program from compiled OpenCL program.
|
||||
|
||||
**Not applicable**. We are using SYCL, not OpenCL, right?
|
||||
|
||||
2. Compile SYCL program from OpenCL C string using `compile_with_source`
|
||||
|
||||
**Not applicable**. We are using SYCL, not OpenCL, right?
|
||||
|
||||
3. Use `compile_with_kernel_type` method on SYCL program.
|
||||
|
||||
According to the spec, this method will compiler SYCL kernel function which
|
||||
name is provided as template argument. I guess if this kernel function calls
|
||||
something else then this something else will also be compiled.
|
||||
|
||||
Having that said, to get all helper functions compiled we need to call them
|
||||
all from some dummy kernel.
|
||||
|
||||
**Ugly**
|
||||
|
||||
4. Anything else?
|
||||
|
||||
Right now in this example, helper function is not even called from the kernel
|
||||
which is being compiled, but everything works due to implementation details of
|
||||
our compiler.
|
||||
|
||||
### Is there an easy way to get program object containing several kernels?
|
||||
|
||||
The problem here is that by default, `parallel_for` uses program instance which
|
||||
was implicitly created and compiled by SYCL RT with some default options.
|
||||
|
||||
In cases, where user wants to change this options, or if the program object is
|
||||
required to do some additional stuff (for example, to request function pointer),
|
||||
user need to pass `cl::sycl::kernel` object explicitly to each `parallel_for` to
|
||||
enforce using specific program object instead of implicitly created one.
|
||||
|
||||
SYCL spec doesn't allow to do this easily: `compile_with_kernel_type` method
|
||||
mentioned above only guarantees that specified kernel will be included into a
|
||||
program object and nothing is said about the rest.
|
||||
|
||||
This means that to get SYCL program with several kernels, we basically need to
|
||||
create several program objects, compile all of them for each kernel and then
|
||||
link them together to get executable device binary: not very user-friendly.
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "lib.hpp"
|
||||
|
||||
SYCL_EXTERNAL int lib_calculate(cl::sycl::global_ptr<int> A,
|
||||
cl::sycl::global_ptr<int> B, int Size) {
|
||||
int Sum = 0;
|
||||
|
||||
for (int I = 0; I < Size; ++I) {
|
||||
Sum += A[I] + B[I];
|
||||
}
|
||||
|
||||
return Sum;
|
||||
}
|
||||
|
||||
cl::sycl::program lib_get_program(cl::sycl::context &C) {
|
||||
auto Devices = C.get_devices();
|
||||
assert(Devices.size() == 1);
|
||||
|
||||
auto EH = [](cl::sycl::exception_list EL) {
|
||||
for (std::exception_ptr const &E : EL) {
|
||||
try {
|
||||
std::rethrow_exception(E);
|
||||
} catch (cl::sycl::exception const &E) {
|
||||
std::cout << "Caught asynchronous SYCL exception: \n"
|
||||
<< E.what() << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cl::sycl::queue Q(Devices.front(), EH);
|
||||
Q.submit([&](cl::sycl::handler &CGH) {
|
||||
CGH.single_task<class dummy>([=]() { });
|
||||
});
|
||||
|
||||
Q.wait_and_throw(); // to get build logs
|
||||
|
||||
cl::sycl::program P(C);
|
||||
// FIXME: there is not guarantee (according to the SYCL spec), that
|
||||
// 'lib_calculate' will be included into 'P'
|
||||
P.compile_with_kernel_type<class dummy>();
|
||||
|
||||
return P;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <CL/sycl.hpp>
|
||||
|
||||
#ifndef SYCL_EXTERNAL
|
||||
#error "This application requires SYCL_EXTERNAL support
|
||||
#endif
|
||||
|
||||
SYCL_EXTERNAL int lib_calculate(cl::sycl::global_ptr<int>,
|
||||
cl::sycl::global_ptr<int>, int);
|
||||
|
||||
cl::sycl::program lib_get_program(cl::sycl::context&);
|
||||
@@ -0,0 +1,133 @@
|
||||
#include <CL/sycl.hpp>
|
||||
|
||||
#include "lib.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
// Uncomment line below to enable some output from kernel
|
||||
// #define DEBUG_OUTPUT
|
||||
|
||||
int app_calculate(cl::sycl::global_ptr<int> A, cl::sycl::global_ptr<int> B,
|
||||
int Size) {
|
||||
int Sum = 0;
|
||||
|
||||
for (int I = 0; I < Size; ++I) {
|
||||
Sum += A[I] + B[I];
|
||||
}
|
||||
|
||||
return Sum;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto EH = [](cl::sycl::exception_list EL) {
|
||||
for (std::exception_ptr const &E : EL) {
|
||||
try {
|
||||
std::rethrow_exception(E);
|
||||
} catch (cl::sycl::exception const &E) {
|
||||
std::cout << "Caught asynchronous SYCL exception: \n"
|
||||
<< E.what() << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cl::sycl::queue Q(EH);
|
||||
cl::sycl::context C = Q.get_context();
|
||||
cl::sycl::program AppProg(C);
|
||||
|
||||
auto devices = C.get_devices();
|
||||
for (auto& device : devices)
|
||||
std::cout << "Device: " << device.get_info<cl::sycl::info::device::name>() << std::endl;
|
||||
|
||||
AppProg.compile_with_kernel_type<class app_kernel>();
|
||||
auto LibProg = lib_get_program(C);
|
||||
|
||||
cl::sycl::program P( { AppProg, LibProg} );
|
||||
// According to the spec, P is already linked, no need to explicitly call link
|
||||
// P.link();
|
||||
|
||||
const int N = 4;
|
||||
const cl::sycl::range<1> GlobalSize { 8 };
|
||||
const cl::sycl::range<1> LocalSize { 8 };
|
||||
|
||||
std::vector<int> A(GlobalSize.get(0) * N, 1);
|
||||
std::vector<int> B(GlobalSize.get(0) * N, 2);
|
||||
|
||||
cl::sycl::buffer<int> BufA(A.data(), { A.size() });
|
||||
cl::sycl::buffer<int> BufB(B.data(), { B.size() });
|
||||
|
||||
int R = 0;
|
||||
cl::sycl::buffer<int> BufR(&R, 1);
|
||||
|
||||
// We need to explicitly create a kernel and pass it to 'parallel_for',
|
||||
// otherwise, SYCL RT will implicitly create a different program and use it
|
||||
// instead of user-created one.
|
||||
cl::sycl::kernel K = P.get_kernel<class app_kernel>();
|
||||
Q.submit([&](cl::sycl::handler &CGH) {
|
||||
auto AccA = BufA.template get_access<cl::sycl::access::mode::read>(CGH);
|
||||
auto AccB = BufB.template get_access<cl::sycl::access::mode::read>(CGH);
|
||||
auto AccR = BufR.template get_access<cl::sycl::access::mode::atomic>(CGH);
|
||||
auto AccL = cl::sycl::accessor<int, 0, cl::sycl::access::mode::atomic,
|
||||
cl::sycl::access::target::local>(CGH);
|
||||
cl::sycl::stream Out(4096, 256, CGH);
|
||||
|
||||
// Without argument K passed to parallel_for, device build (JIT) will fail
|
||||
// with something like:
|
||||
// The program was built for 1 devices
|
||||
// Build program log for 'Intel(R) Gen9 HD Graphics NEO':
|
||||
// error: undefined reference to `_Z13lib_calculateN2cl4sycl9multi_ptrIiLNS0_6access13address_spaceE1EEES4_i()'
|
||||
// error: backend compiler failed build.
|
||||
// 0 (CL_SUCCESS)
|
||||
CGH.parallel_for<class app_kernel>(/* THIS IS AN IMPORTANT ARGUMENT: */K,
|
||||
cl::sycl::nd_range<1>{ GlobalSize, LocalSize },
|
||||
[=](cl::sycl::nd_item<1> ND) {
|
||||
auto LID = ND.get_local_id(0);
|
||||
cl::sycl::atomic<int, cl::sycl::access::address_space::local_space> A =
|
||||
AccL;
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
// Macro below provides a work-around to ensure that output to stream from
|
||||
// different work-items will not interfiere. NOTE: this doesn't help to fix
|
||||
// races between different threads (i.e. work-groups on CPU)
|
||||
#define PRINT(X) \
|
||||
{ \
|
||||
for (int I = 0; I < LocalSize.get(0); ++I) { \
|
||||
if (I == LID) { \
|
||||
X \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define PRINT(X)
|
||||
#endif // DEBUG_OUTPUT
|
||||
|
||||
if (LID == 0) {
|
||||
A.store(0);
|
||||
PRINT(Out << "LID = " << LID << " A = " << A.load() << cl::sycl::endl;)
|
||||
}
|
||||
ND.barrier(cl::sycl::access::fence_space::local_space);
|
||||
|
||||
auto GID = ND.get_group(0);
|
||||
|
||||
auto Offset = GID * LocalSize.get(0) * N + LID * N;
|
||||
|
||||
A.fetch_add(app_calculate(AccA.get_pointer() + Offset,
|
||||
AccB.get_pointer() + Offset, N));
|
||||
PRINT(Out << "LID = " << LID << " A = " << A.load() << cl::sycl::endl;)
|
||||
|
||||
A.fetch_sub(lib_calculate(AccA.get_pointer() + Offset,
|
||||
AccB.get_pointer() + Offset, N));
|
||||
PRINT(Out << "LID = " << LID << " A = " << A.load() << cl::sycl::endl;)
|
||||
|
||||
ND.barrier(cl::sycl::access::fence_space::local_space);
|
||||
AccR[0].fetch_add(A.load());
|
||||
});
|
||||
});
|
||||
|
||||
Q.wait_and_throw();
|
||||
|
||||
auto AccR = BufR.template get_access<cl::sycl::access::mode::read>();
|
||||
std::cout << "Result: " << AccR[0] << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,784 @@
|
||||
|
||||
#define EMBREE_SYCL_SIMD_LIBRARY
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
#pragma message "SYCL DEVICE"
|
||||
#else
|
||||
#pragma message "SYCL HOST"
|
||||
#endif
|
||||
|
||||
#include <CL/sycl.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include "../../common/simd/simd.h"
|
||||
|
||||
class NEOGPUDeviceSelector : public cl::sycl::device_selector
|
||||
{
|
||||
public:
|
||||
int operator()(const cl::sycl::device& device) const override {
|
||||
using namespace cl::sycl::info;
|
||||
|
||||
const std::string deviceName = device.get_info<device::name>();
|
||||
const std::string deviceVendor = device.get_info<device::vendor>();
|
||||
return device.is_gpu() && deviceName.find("HD Graphics NEO") ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
class CPUDeviceSelector : public cl::sycl::device_selector {
|
||||
public:
|
||||
int operator()(const cl::sycl::device& device) const override {
|
||||
return device.is_cpu() ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
void exception_handler(cl::sycl::exception_list exceptions)
|
||||
{
|
||||
for (std::exception_ptr const& e : exceptions) {
|
||||
try {
|
||||
std::rethrow_exception(e);
|
||||
} catch(cl::sycl::exception const& e) {
|
||||
std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Test
|
||||
{
|
||||
Test (std::string name)
|
||||
: name(name) {}
|
||||
|
||||
virtual ~Test() {}
|
||||
|
||||
virtual bool run(cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue) = 0;
|
||||
|
||||
void invoke(cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::cout << name << ": " << std::flush;
|
||||
bool passed = run(device,context,queue);
|
||||
if (passed) std::cout << " [PASSED]" << std::endl;
|
||||
else std::cout << " [FAILED]" << std::endl;
|
||||
std::cout << std::flush;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct parallel_for_sycl_buffer_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
parallel_for_sycl_buffer_test ()
|
||||
: Test("parallel_for_sycl_buffer_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A);
|
||||
cl::sycl::buffer<int> bufB(B);
|
||||
cl::sycl::buffer<int> bufC(C);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto a = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto b = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto c = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for<class test>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> item) {
|
||||
c[item] = a[item] + b[item];
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (hostA[i]+hostB[i] != hostC[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct parallel_for_sycl_aligned_alloc_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
parallel_for_sycl_aligned_alloc_test ()
|
||||
: Test("parallel_for_sycl_aligned_alloc_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
int* a = (int*) cl::sycl::aligned_alloc(64,size*sizeof(int),device,context,cl::sycl::usm::alloc::shared);
|
||||
int* b = (int*) cl::sycl::aligned_alloc(64,size*sizeof(int),device,context,cl::sycl::usm::alloc::shared);
|
||||
int* c = (int*) cl::sycl::aligned_alloc(64,size*sizeof(int),device,context,cl::sycl::usm::alloc::shared);
|
||||
|
||||
std::generate(a, a+size, std::rand);
|
||||
std::generate(b, b+size, std::rand);
|
||||
std::generate(c, c+size, std::rand);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
cgh.parallel_for<class test>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> item) {
|
||||
int i = item.get(0);
|
||||
c[i] = a[i] + b[i];
|
||||
});
|
||||
});
|
||||
queue.wait_and_throw();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (a[i]+b[i] != c[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
cl::sycl::free(a, context);
|
||||
cl::sycl::free(b, context);
|
||||
cl::sycl::free(c, context);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct subgroup_test : public Test
|
||||
{
|
||||
static const int size = 256*16;
|
||||
|
||||
subgroup_test ()
|
||||
: Test("subgroup_test") {}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(16)]] static inline void test(const uint groupID, cl::sycl::intel::sub_group& subgroup, int* a, int* b, int* c)
|
||||
{
|
||||
const uint subgroupLocalID = subgroup.get_local_id()[0];
|
||||
const uint i = groupID*16+subgroupLocalID;
|
||||
c[i] = a[i] + b[i];
|
||||
}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
int* a = (int*) cl::sycl::aligned_alloc(64,size*sizeof(int),device,context,cl::sycl::usm::alloc::shared);
|
||||
int* b = (int*) cl::sycl::aligned_alloc(64,size*sizeof(int),device,context,cl::sycl::usm::alloc::shared);
|
||||
int* c = (int*) cl::sycl::aligned_alloc(64,size*sizeof(int),device,context,cl::sycl::usm::alloc::shared);
|
||||
|
||||
std::generate(a, a+size, std::rand);
|
||||
std::generate(b, b+size, std::rand);
|
||||
std::generate(c, c+size, std::rand);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
const cl::sycl::nd_range<1> nd_range(cl::sycl::range<1>(size), cl::sycl::range<1>(16));
|
||||
|
||||
cgh.parallel_for(nd_range,[=](cl::sycl::nd_item<1> item) {
|
||||
const uint groupID = item.get_group(0);
|
||||
cl::sycl::intel::sub_group subgroup = item.get_sub_group();
|
||||
test(groupID,subgroup,a,b,c);
|
||||
});
|
||||
});
|
||||
|
||||
queue.wait_and_throw();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (a[i]+b[i] != c[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
cl::sycl::free(a, context);
|
||||
cl::sycl::free(b, context);
|
||||
cl::sycl::free(c, context);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
typedef int (*fptr_ty) (int a, int b);
|
||||
[[intel::device_indirectly_callable]] int add_function(int a, int b) { return a + b; }
|
||||
[[intel::device_indirectly_callable]] int sub_function(int a, int b) { return a - b; }
|
||||
|
||||
struct single_uniform_function_pointer_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
single_uniform_function_pointer_test ()
|
||||
: Test("single_uniform_function_pointer_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufB(B.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufC(C.data(), cl::sycl::range<1>(size));
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto accA = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accB = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accC = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for(cl::sycl::range<1>(size), [=](cl::sycl::id<1> index) {
|
||||
fptr_ty fptr = &add_function;
|
||||
accC[index] = fptr(accA[index],accB[index]);
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
bool passed = true;
|
||||
for (size_t i=0; i<size; i++)
|
||||
passed &= hostA[i] + hostB[i] == hostC[i];
|
||||
|
||||
return passed;
|
||||
}
|
||||
};
|
||||
|
||||
struct function_pointer_take_uniform_address_on_device_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
function_pointer_take_uniform_address_on_device_test ()
|
||||
: Test("function_pointer_take_uniform_address_on_device_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
bool passed = true;
|
||||
|
||||
for (int Mode = 0; Mode < 2; ++Mode)
|
||||
{
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufB(B.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufC(C.data(), cl::sycl::range<1>(size));
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto accA = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accB = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accC = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for(cl::sycl::range<1>(size), [=](cl::sycl::id<1> index) {
|
||||
int i = index.get(0);
|
||||
fptr_ty fptr = Mode ? &add_function : &sub_function;
|
||||
accC[i] = fptr(accA[i], accB[i]);
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (size_t i=0; i<size; i++) {
|
||||
if (Mode) passed &= hostA[i] + hostB[i] == hostC[i];
|
||||
else passed &= hostA[i] - hostB[i] == hostC[i];
|
||||
}
|
||||
}
|
||||
return passed;
|
||||
}
|
||||
};
|
||||
|
||||
struct function_pointer_take_varying_address_on_device_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
function_pointer_take_varying_address_on_device_test ()
|
||||
: Test("function_pointer_take_varying_address_on_device_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
bool passed = true;
|
||||
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufB(B.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufC(C.data(), cl::sycl::range<1>(size));
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto accA = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accB = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accC = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for(cl::sycl::range<1>(size), [=](cl::sycl::id<1> index) {
|
||||
int i = index.get(0);
|
||||
fptr_ty fptr = i%2 ? &add_function : &sub_function;
|
||||
accC[i] = fptr(accA[i], accB[i]);
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (size_t i=0; i<size; i++) {
|
||||
if (i%2) passed &= hostA[i] + hostB[i] == hostC[i];
|
||||
else passed &= hostA[i] - hostB[i] == hostC[i];
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
};
|
||||
|
||||
struct function_pointer_take_uniform_address_on_device_array_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
function_pointer_take_uniform_address_on_device_array_test ()
|
||||
: Test("function_pointer_take_uniform_address_on_device_array_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
bool passed = true;
|
||||
|
||||
cl::sycl::buffer<cl_ulong> DispatchTableBuffer(2);
|
||||
{
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
auto accDT = DispatchTableBuffer.get_access<cl::sycl::access::mode::discard_write>(cgh);
|
||||
cgh.single_task([=]() {
|
||||
accDT[0] = reinterpret_cast<cl_ulong>(&add_function);
|
||||
accDT[1] = reinterpret_cast<cl_ulong>(&sub_function);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (int Mode = 0; Mode < 2; ++Mode)
|
||||
{
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufB(B.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufC(C.data(), cl::sycl::range<1>(size));
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto accA = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accB = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accC = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
auto accDT = DispatchTableBuffer.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
|
||||
cgh.parallel_for<class K>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> index) {
|
||||
fptr_ty fptr = reinterpret_cast<fptr_ty>(accDT[Mode]);
|
||||
accC[index] = fptr(accA[index], accB[index]);
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
if (Mode == 0) {
|
||||
for (size_t i=0; i<size; i++) passed &= hostA[i] + hostB[i] == hostC[i];
|
||||
} else {
|
||||
for (size_t i=0; i<size; i++) passed &= hostA[i] - hostB[i] == hostC[i];
|
||||
}
|
||||
}
|
||||
return passed;
|
||||
}
|
||||
};
|
||||
|
||||
struct function_pointer_take_varying_address_on_device_array_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
function_pointer_take_varying_address_on_device_array_test ()
|
||||
: Test("function_pointer_take_varying_address_on_device_array_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
bool passed = true;
|
||||
|
||||
cl::sycl::buffer<cl_ulong> DispatchTableBuffer(2);
|
||||
{
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
auto accDT = DispatchTableBuffer.get_access<cl::sycl::access::mode::discard_write>(cgh);
|
||||
cgh.single_task([=]() {
|
||||
accDT[0] = reinterpret_cast<cl_ulong>(&add_function);
|
||||
accDT[1] = reinterpret_cast<cl_ulong>(&sub_function);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (int Mode = 0; Mode < 2; ++Mode)
|
||||
{
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufB(B.data(), cl::sycl::range<1>(size));
|
||||
cl::sycl::buffer<int> bufC(C.data(), cl::sycl::range<1>(size));
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto accA = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accB = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto accC = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
auto accDT = DispatchTableBuffer.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
|
||||
cgh.parallel_for<class K>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> index) {
|
||||
fptr_ty fptr = reinterpret_cast<fptr_ty>(accDT[index%2]);
|
||||
accC[index] = fptr(accA[index], accB[index]);
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (size_t i=0; i<size; i++) {
|
||||
if (i%2) passed &= hostA[i] + hostB[i] == hostC[i];
|
||||
else passed &= hostA[i] - hostB[i] == hostC[i];
|
||||
}
|
||||
}
|
||||
return passed;
|
||||
}
|
||||
};
|
||||
|
||||
#if 0 // FIXME: does not compile
|
||||
|
||||
struct access_virtual_structure_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
struct OtherVirtualStructure {
|
||||
virtual void add() {}
|
||||
};
|
||||
|
||||
struct VirtualStructure
|
||||
{
|
||||
VirtualStructure () = default;
|
||||
|
||||
VirtualStructure (int value)
|
||||
: value(value) {}
|
||||
|
||||
static VirtualStructure rand() {
|
||||
return VirtualStructure(std::rand());
|
||||
}
|
||||
|
||||
virtual void add() {}
|
||||
|
||||
int value;
|
||||
OtherVirtualStructure* ptr;
|
||||
};
|
||||
|
||||
access_virtual_structure_test ()
|
||||
: Test("access_virtual_structure_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::vector<VirtualStructure> A(size);
|
||||
std::vector<VirtualStructure> B(size);
|
||||
std::vector<VirtualStructure> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), VirtualStructure::rand);
|
||||
std::generate(B.begin(), B.end(), VirtualStructure::rand);
|
||||
std::generate(C.begin(), C.end(), VirtualStructure::rand);
|
||||
|
||||
cl::sycl::buffer<VirtualStructure> bufA(A);
|
||||
cl::sycl::buffer<VirtualStructure> bufB(B);
|
||||
cl::sycl::buffer<VirtualStructure> bufC(C);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto a = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto b = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto c = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for<class test>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> item) {
|
||||
c[item].value = a[item].value + b[item].value;
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (hostA[i].value+hostB[i].value != hostC[i].value)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct subgroup_library_test : public Test
|
||||
{
|
||||
static const int size = 256;
|
||||
|
||||
subgroup_library_test ()
|
||||
: Test("subgroup_library_test") {}
|
||||
|
||||
[[cl::intel_reqd_sub_group_size(16)]] static inline void test(const uint i, float* a, float* b, float* c)
|
||||
{
|
||||
embree::vfloat4 ai = embree::vfloat4::load(&a[i]);
|
||||
embree::vfloat4 bi = embree::vfloat4::load(&b[i]);
|
||||
embree::vfloat4 ci = embree::vreduce_min(ai+bi);
|
||||
embree::vfloat4::store(&c[i],ci);
|
||||
}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
float* a = (float*) cl::sycl::aligned_alloc(64,4*size*sizeof(float),device,context,cl::sycl::usm::alloc::shared);
|
||||
float* b = (float*) cl::sycl::aligned_alloc(64,4*size*sizeof(float),device,context,cl::sycl::usm::alloc::shared);
|
||||
float* c = (float*) cl::sycl::aligned_alloc(64,4*size*sizeof(float),device,context,cl::sycl::usm::alloc::shared);
|
||||
|
||||
std::generate(a, a+4*size, drand48);
|
||||
std::generate(b, b+4*size, drand48);
|
||||
std::generate(c, c+4*size, drand48);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
const cl::sycl::nd_range<1> nd_range(cl::sycl::range<1>(16*size), cl::sycl::range<1>(16));
|
||||
|
||||
cgh.parallel_for(nd_range,[=](cl::sycl::nd_item<1> item) {
|
||||
const uint i = item.get_group(0);
|
||||
test(4*i,a,b,c);
|
||||
});
|
||||
});
|
||||
|
||||
queue.wait_and_throw();
|
||||
|
||||
for (int i=0; i<4*size; i+=4)
|
||||
{
|
||||
embree::vfloat4 ai = embree::vfloat4::load(&a[i]);
|
||||
embree::vfloat4 bi = embree::vfloat4::load(&b[i]);
|
||||
embree::vfloat4 ci = embree::vreduce_min(ai+bi);
|
||||
embree::vfloat4 ci_device = embree::vfloat4::load(&c[i]);
|
||||
if (embree::any(ci != ci_device))
|
||||
return false;
|
||||
}
|
||||
|
||||
cl::sycl::free(a, context);
|
||||
cl::sycl::free(b, context);
|
||||
cl::sycl::free(c, context);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
SYCL_EXTERNAL int static_lib_add(int a, int b);
|
||||
|
||||
struct static_library_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
static_library_test ()
|
||||
: Test("static_library_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::vector<int> A(size);
|
||||
std::vector<int> B(size);
|
||||
std::vector<int> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), std::rand);
|
||||
std::generate(B.begin(), B.end(), std::rand);
|
||||
std::generate(C.begin(), C.end(), std::rand);
|
||||
|
||||
cl::sycl::buffer<int> bufA(A);
|
||||
cl::sycl::buffer<int> bufB(B);
|
||||
cl::sycl::buffer<int> bufC(C);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto a = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto b = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto c = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for<class test>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> item) {
|
||||
c[item] = static_lib_add(a[item],b[item]);
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (hostA[i]+hostB[i] != hostC[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct pointer_performance_issue_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
pointer_performance_issue_test ()
|
||||
: Test("pointer_performance_issue_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
cl::sycl::int4* a = (cl::sycl::int4*) cl::sycl::aligned_alloc(64,size*sizeof(cl::sycl::int4),device,context,cl::sycl::usm::alloc::shared);
|
||||
cl::sycl::int4* b = (cl::sycl::int4*) cl::sycl::aligned_alloc(64,size*sizeof(cl::sycl::int4),device,context,cl::sycl::usm::alloc::shared);
|
||||
cl::sycl::int4* c = (cl::sycl::int4*) cl::sycl::aligned_alloc(64,size*sizeof(cl::sycl::int4),device,context,cl::sycl::usm::alloc::shared);
|
||||
|
||||
cl::sycl::ulong a_ = (cl::sycl::ulong) a;
|
||||
|
||||
std::generate(a, a+size, std::rand);
|
||||
std::generate(b, b+size, std::rand);
|
||||
std::generate(c, c+size, std::rand);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
cgh.parallel_for<class test>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> item) {
|
||||
int i = item.get(0);
|
||||
//cl::sycl::int4* a = (cl::sycl::int4*) a_; // slow when enabled
|
||||
c[i] = a[i] + b[i];
|
||||
});
|
||||
});
|
||||
queue.wait_and_throw();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (cl::sycl::all(a[i]+b[i] != c[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
cl::sycl::free(a, context);
|
||||
cl::sycl::free(b, context);
|
||||
cl::sycl::free(c, context);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct MyVec3f
|
||||
{
|
||||
float x,y,z;
|
||||
|
||||
__forceinline MyVec3f () {}
|
||||
|
||||
__forceinline MyVec3f ( const MyVec3f& other ) { // disabling copy constructor lets test pass !
|
||||
x = other.x; y = other.y; z = other.z;
|
||||
}
|
||||
};
|
||||
|
||||
struct copy_constructor_bug_test : public Test
|
||||
{
|
||||
copy_constructor_bug_test ()
|
||||
: Test("copy_constructor_bug_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
cl::sycl::float3* a = (cl::sycl::float3*) cl::sycl::aligned_alloc(64,sizeof(cl::sycl::float3),device,context,cl::sycl::usm::alloc::shared);
|
||||
a->x() = a->y() = a->z() = 0;
|
||||
|
||||
MyVec3f vx;
|
||||
vx.x = 1.0f;
|
||||
vx.y = 2.0f;
|
||||
vx.z = 3.0f;
|
||||
|
||||
queue.submit([=](cl::sycl::handler &cgh) {
|
||||
//cl::sycl::stream out(10000, 10000, cgh);
|
||||
cgh.single_task<class test>([=]() {
|
||||
//out << "vx.x = " << vx.x << cl::sycl::endl;
|
||||
//out << "vx.y = " << vx.y << cl::sycl::endl;
|
||||
//out << "vx.z = " << vx.z << cl::sycl::endl;
|
||||
a->x() = vx.x;
|
||||
a->y() = vx.y;
|
||||
a->z() = vx.z;
|
||||
});
|
||||
});
|
||||
|
||||
queue.wait_and_throw();
|
||||
|
||||
if (a->x() != vx.x || a->y() != vx.y || a->z() != vx.z)
|
||||
return false;
|
||||
|
||||
cl::sycl::free(a, context);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
cl::sycl::device device = cl::sycl::device(NEOGPUDeviceSelector());
|
||||
//cl::sycl::device device = cl::sycl::device(CPUDeviceSelector());
|
||||
cl::sycl::queue queue = cl::sycl::queue(device,exception_handler);
|
||||
cl::sycl::context context = queue.get_context();
|
||||
|
||||
std::cout << "GPU Device: " << device.get_info<cl::sycl::info::device::name>() << std::endl;
|
||||
int gpu_maxWorkGroupSize = device.get_info<cl::sycl::info::device::max_work_group_size>();
|
||||
int gpu_maxComputeUnits = device.get_info<cl::sycl::info::device::max_compute_units>();
|
||||
std::cout << "- Max Work Group Size : " << gpu_maxWorkGroupSize << std::endl;
|
||||
std::cout << "- Max Compute Units : " << gpu_maxComputeUnits << std::endl;
|
||||
|
||||
/* create all tests */
|
||||
std::vector<std::unique_ptr<Test>> tests;
|
||||
tests.push_back(std::unique_ptr<Test>(new parallel_for_sycl_buffer_test()));
|
||||
tests.push_back(std::unique_ptr<Test>(new parallel_for_sycl_aligned_alloc_test()));
|
||||
tests.push_back(std::unique_ptr<Test>(new subgroup_test()));
|
||||
tests.push_back(std::unique_ptr<Test>(new function_pointer_take_uniform_address_on_device_test()));
|
||||
tests.push_back(std::unique_ptr<Test>(new function_pointer_take_uniform_address_on_device_array_test()));
|
||||
|
||||
#if 0
|
||||
tests.push_back(std::unique_ptr<Test>(new single_uniform_function_pointer_test()));
|
||||
tests.push_back(std::unique_ptr<Test>(new function_pointer_take_varying_address_on_device_test()));
|
||||
tests.push_back(std::unique_ptr<Test>(new function_pointer_take_varying_address_on_device_array_test()));
|
||||
#endif
|
||||
|
||||
//tests.push_back(std::unique_ptr<Test>(new access_virtual_structure_test())); // FIXME: does not compile
|
||||
|
||||
tests.push_back(std::unique_ptr<Test>(new subgroup_library_test()));
|
||||
|
||||
tests.push_back(std::unique_ptr<Test>(new static_library_test()));
|
||||
|
||||
tests.push_back(std::unique_ptr<Test>(new pointer_performance_issue_test()));
|
||||
|
||||
tests.push_back(std::unique_ptr<Test>(new copy_constructor_bug_test()));
|
||||
|
||||
/* invoke all tests */
|
||||
for (auto& test : tests)
|
||||
test->invoke(device,context,queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#include <CL/sycl.hpp>
|
||||
|
||||
SYCL_EXTERNAL int static_lib_add(int a, int b)
|
||||
{
|
||||
return a+b;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
virtual_struct:
|
||||
~/projects/dpcpp/current/bin/clang++ -fsycl virtual_struct.cpp -o virtual_struct
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
#include <CL/sycl.hpp>
|
||||
#include <iostream>
|
||||
|
||||
class NEOGPUDeviceSelector : public cl::sycl::device_selector
|
||||
{
|
||||
public:
|
||||
int operator()(const cl::sycl::device& device) const override {
|
||||
using namespace cl::sycl::info;
|
||||
|
||||
const std::string deviceName = device.get_info<device::name>();
|
||||
const std::string deviceVendor = device.get_info<device::vendor>();
|
||||
return device.is_gpu() && deviceName.find("HD Graphics NEO") ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
class CPUDeviceSelector : public cl::sycl::device_selector {
|
||||
public:
|
||||
int operator()(const cl::sycl::device& device) const override {
|
||||
return device.is_cpu() ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
void exception_handler(cl::sycl::exception_list exceptions)
|
||||
{
|
||||
for (std::exception_ptr const& e : exceptions) {
|
||||
try {
|
||||
std::rethrow_exception(e);
|
||||
} catch(cl::sycl::exception const& e) {
|
||||
std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Test
|
||||
{
|
||||
Test (std::string name)
|
||||
: name(name) {}
|
||||
|
||||
virtual ~Test() {}
|
||||
|
||||
virtual bool run(cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue) = 0;
|
||||
|
||||
void invoke(cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::cout << name << ": " << std::flush;
|
||||
bool passed = run(device,context,queue);
|
||||
if (passed) std::cout << " [PASSED]" << std::endl;
|
||||
else std::cout << " [FAILED]" << std::endl;
|
||||
std::cout << std::flush;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct access_virtual_structure_test : public Test
|
||||
{
|
||||
static const int size = 1000;
|
||||
|
||||
struct OtherVirtualStructure {
|
||||
virtual void add() {}
|
||||
};
|
||||
|
||||
struct VirtualStructure
|
||||
{
|
||||
VirtualStructure () = default;
|
||||
|
||||
VirtualStructure (int value)
|
||||
: value(value) {}
|
||||
|
||||
static VirtualStructure rand() {
|
||||
return VirtualStructure(std::rand());
|
||||
}
|
||||
|
||||
virtual void add() {}
|
||||
|
||||
int value;
|
||||
OtherVirtualStructure* ptr;
|
||||
};
|
||||
|
||||
access_virtual_structure_test ()
|
||||
: Test("access_virtual_structure_test") {}
|
||||
|
||||
bool run (cl::sycl::device& device, cl::sycl::context context, cl::sycl::queue& queue)
|
||||
{
|
||||
std::vector<VirtualStructure> A(size);
|
||||
std::vector<VirtualStructure> B(size);
|
||||
std::vector<VirtualStructure> C(size);
|
||||
|
||||
std::generate(A.begin(), A.end(), VirtualStructure::rand);
|
||||
std::generate(B.begin(), B.end(), VirtualStructure::rand);
|
||||
std::generate(C.begin(), C.end(), VirtualStructure::rand);
|
||||
|
||||
cl::sycl::buffer<VirtualStructure> bufA(A);
|
||||
cl::sycl::buffer<VirtualStructure> bufB(B);
|
||||
cl::sycl::buffer<VirtualStructure> bufC(C);
|
||||
|
||||
queue.submit([&](cl::sycl::handler& cgh) {
|
||||
|
||||
auto a = bufA.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto b = bufB.get_access<cl::sycl::access::mode::read>(cgh);
|
||||
auto c = bufC.get_access<cl::sycl::access::mode::write>(cgh);
|
||||
|
||||
cgh.parallel_for<class test>(cl::sycl::range<1>(size), [=](cl::sycl::id<1> item) {
|
||||
c[item].value = a[item].value + b[item].value;
|
||||
});
|
||||
});
|
||||
|
||||
auto hostA = bufA.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostB = bufB.get_access<cl::sycl::access::mode::read>();
|
||||
auto hostC = bufC.get_access<cl::sycl::access::mode::read>();
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
if (hostA[i].value+hostB[i].value != hostC[i].value)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
cl::sycl::device device = cl::sycl::device(NEOGPUDeviceSelector());
|
||||
//cl::sycl::device device = cl::sycl::device(CPUDeviceSelector());
|
||||
cl::sycl::queue queue = cl::sycl::queue(device,exception_handler);
|
||||
cl::sycl::context context = queue.get_context();
|
||||
|
||||
std::cout << "GPU Device: " << device.get_info<cl::sycl::info::device::name>() << std::endl;
|
||||
int gpu_maxWorkGroupSize = device.get_info<cl::sycl::info::device::max_work_group_size>();
|
||||
int gpu_maxComputeUnits = device.get_info<cl::sycl::info::device::max_compute_units>();
|
||||
std::cout << "- Max Work Group Size : " << gpu_maxWorkGroupSize << std::endl;
|
||||
std::cout << "- Max Compute Units : " << gpu_maxComputeUnits << std::endl;
|
||||
|
||||
/* create all tests */
|
||||
std::vector<std::unique_ptr<Test>> tests;
|
||||
tests.push_back(std::unique_ptr<Test>(new access_virtual_structure_test()));
|
||||
|
||||
/* invoke all tests */
|
||||
for (auto& test : tests)
|
||||
test->invoke(device,context,queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -17,8 +17,8 @@
|
||||
INCLUDE(tutorial)
|
||||
ADD_TUTORIAL(triangle_geometry)
|
||||
ADD_TUTORIAL_ISPC(triangle_geometry)
|
||||
ADD_TUTORIAL_SYCL(triangle_geometry)
|
||||
|
||||
IF (EMBREE_TESTING_INTENSITY GREATER 0)
|
||||
ADD_EMBREE_TEST(triangle_geometry)
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
#include "../common/tutorial/tutorial.h"
|
||||
|
||||
#if defined(EMBREE_SYCL_TUTORIAL)
|
||||
# define FEATURES FEATURE_RTCORE | FEATURE_SYCL
|
||||
#else
|
||||
# define FEATURES FEATURE_RTCORE
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
struct Tutorial : public TutorialApplication
|
||||
{
|
||||
Tutorial()
|
||||
: TutorialApplication("triangle_geometry",FEATURE_RTCORE)
|
||||
: TutorialApplication("triangle_geometry",FEATURES)
|
||||
{
|
||||
/* set default camera */
|
||||
camera.from = Vec3fa(1.5f,1.5f,-1.5f);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user