Compare commits

...
358 Commits
Author SHA1 Message Date
cbenthin 1c539c3e9b required changes due to compiler update: ocl_global -> opencl_global and ocl_local -> opencl_local 2019-12-10 17:14:18 +01:00
cbenthin db6e680325 cleanups 2019-12-10 15:59:19 +01:00
cbenthin c8288045ea simple compressed qbvh mb nodes working 2019-12-10 15:15:50 +01:00
Sven Woop a2f51f16bf Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-10 11:37:12 +01:00
Sven Woop 22ca07cb3f fixed SYCL rtcIntersect interface 2019-12-10 11:37:07 +01:00
cbenthin 77fed4d218 updates 2019-12-10 11:35:31 +01:00
Sven Woop 43bfb0966a cleanups 2019-12-10 11:27:24 +01:00
Sven Woop a804fcd873 first SYCL version of triangle_geometry tutorial runs 2019-12-10 11:25:39 +01:00
Sven Woop 2b5581a581 added copy_constructor_bug_test 2019-12-10 11:12:46 +01:00
cbenthin 78ef8476ca first version of compressed MB encoding, not fully working yet 2019-12-10 10:18:31 +01:00
cbenthin 1a3c3ef2bb updates 2019-12-10 08:34:06 +01:00
Sven Woop 1c591829bb first SYCL version of triangle_geometry tutorial 2019-12-10 08:27:21 +01:00
cbenthin b051d35e4d updates & fixes 2019-12-09 19:08:25 +01:00
cbenthin 501d81964a updates 2019-12-09 14:48:40 +01:00
Sven Woop 0a25869c0d Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-09 11:50:55 +01:00
Sven Woop 15d50637e9 updates 2019-12-09 11:42:47 +01:00
Sven Woop a17eb57780 added sycl pointer perf test 2019-12-09 11:33:34 +01:00
Sven Woop d204039384 fix for sycl_test 2019-12-09 11:33:16 +01:00
cbenthin e839fb310f fixes 2019-12-09 11:06:36 +01:00
cbenthin c8900a5a4c Merge remote-tracking branch 'origin/devel' into sycl 2019-12-09 10:50:11 +01:00
cbenthin f525bf88fc updates 2019-12-09 10:49:56 +01:00
Sven Woop 8a5acfceb3 tried profiling on device, not implemented yet 2019-12-09 10:09:41 +01:00
Sven Woop 25ecb8b35c fixes to get rtcIntersectGPUTest working 2019-12-09 10:03:19 +01:00
Sven Woop 3966b99862 static lib as default, DPCPP enabled by default, ISA=SSE2 by default 2019-12-09 10:02:34 +01:00
Sven Woop f86ac79968 compile fix 2019-12-09 08:45:10 +01:00
Sven Woop 255ad42fea Added static lib sycl test. 2019-12-09 08:30:47 +01:00
Sven Woop e05d2c0b9d Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-06 14:45:17 +01:00
Sven Woop 5f52ff3583 added virtual_struct reproducer 2019-12-06 14:45:10 +01:00
cbenthin 22e64801ce cleanups 2019-12-06 14:41:39 +01:00
cbenthin 26b929734e Merge branch 'sycl' of https://gitlab.com/sdvis/embree into sycl 2019-12-06 14:31:23 +01:00
cbenthin 86f6ec6433 reenabling fct calls testing framework again 2019-12-06 14:31:20 +01:00
Sven Woop 4ea282f0c8 Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-06 14:27:53 +01:00
Sven Woop c232392335 using mostly embree Vec3f and Vec3i types in SYCL traversal 2019-12-06 14:27:47 +01:00
cbenthin 6360dcba5c reenabling fct calls testing framework again 2019-12-06 14:17:05 +01:00
Sven Woop 163636399e added math_sycl.h 2019-12-06 14:01:08 +01:00
cbenthin 725f0e6259 to test indirect fct calls 2019-12-05 16:59:55 +01:00
Sven Woop d3a2a5e872 Merge commit '3da1dc0bad9b31e7348deca08f2d7e9298c69fed' into sycl 2019-12-05 11:06:09 +01:00
Sven Woop 3da1dc0bad using embree ray for SYCL code 2019-12-05 11:05:31 +01:00
Sven Woop e9e3387dda updates 2019-12-05 10:52:50 +01:00
Sven Woop ca8af6f7e9 can compile part of Embree with SYCL SIMD library enabled 2019-12-05 10:48:51 +01:00
Sven Woop 45a1667211 added vec3ba_sycl and vec3ia_sycl 2019-12-05 10:19:54 +01:00
Sven Woop a64ea4c043 Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-05 08:01:12 +01:00
cbenthin 08ac6ce20f convertion for mb gpu path updates 2019-12-04 16:17:39 +01:00
Sven Woop b473755889 added vec3fa_sycl.h 2019-12-04 11:46:37 +01:00
Sven Woop f3a1200841 renames 2019-12-04 10:48:30 +01:00
Sven Woop 7621a6bea1 updates to sycl simd library 2019-12-04 10:43:29 +01:00
Sven Woop 6994e405cc updates to sycl simd library 2019-12-04 10:42:18 +01:00
Sven Woop c48ce76adc Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-04 10:29:01 +01:00
Sven Woop 6a7daed2bb generic SYCL SIMD wrapper 2019-12-04 10:25:54 +01:00
cbenthin fd5ea59117 Merge remote-tracking branch 'origin/devel' into sycl 2019-12-04 10:16:30 +01:00
cbenthin f28f7eb4f5 cleanups 2019-12-04 10:15:26 +01:00
Sven Woop 84f61f9c71 updates 2019-12-04 10:10:04 +01:00
Sven Woop 0f884c9342 using generic vboolf SYCL implementation 2019-12-04 10:01:49 +01:00
Sven Woop d4d32c392a updates to SYCL SIMD library 2019-12-04 09:45:43 +01:00
Sven Woop 826eb9aef2 updates to SYCL SIMD library 2019-12-04 09:31:10 +01:00
cbenthin fbab9d87a4 counting leaf items in org bvh for GPU allocation 2019-12-04 09:04:09 +01:00
Sven Woop e978963b89 updates to vint4_sycl.h 2019-12-04 08:33:28 +01:00
Sven Woop a0e4508a00 enabled sycl SIMD library again 2019-12-04 08:21:00 +01:00
cbenthin 86dcc2a40b fixes to get mb barbarian working 2019-12-03 23:13:58 +01:00
cbenthin 9de5bacd81 Merge branch 'sycl' of https://gitlab.com/sdvis/embree into sycl 2019-12-03 15:43:12 +01:00
cbenthin 8f1db409e6 limiting max prims per leaf for GPU MB path 2019-12-03 15:43:02 +01:00
Sven Woop a4baf0db09 Merge branch 'sycl' of gitlab.com:sdvis/embree into sycl 2019-12-03 11:40:43 +01:00
Sven Woop 5d9fb4937e disabled SYCL SIMD wrapper for now 2019-12-03 11:40:38 +01:00
Sven Woop 34919811b6 removed debug output 2019-12-03 11:20:50 +01:00
Sven Woop f6e3b5a1ca extensions to SYCL SIMD library 2019-12-03 09:53:22 +01:00
Sven Woop 46c89c537f extensions to SYCL SIMD library 2019-12-03 09:51:30 +01:00
Sven Woop 8da10d31ee extensions to SYCL SIMD library 2019-12-03 09:50:10 +01:00
Sven Woop a814f62039 added vint4_sycl.h 2019-12-03 09:13:15 +01:00
Sven Woop 195f28336c added vboolf4_sycl.h 2019-12-03 08:19:56 +01:00
Sven Woop 9b413172b7 first SIMD SYCL library 2019-12-03 07:51:00 +01:00
cbenthin c22b17f5d1 updates and fixes 2019-12-02 20:27:04 +01:00
cbenthin fb430f58a0 cleanups and fixes 2019-12-02 19:10:11 +01:00
cbenthin b2337f7c1e first version of mb working 2019-12-02 16:00:45 +01:00
cbenthin e6a0bb88aa bugfixes in mb code 2019-12-02 12:32:35 +01:00
Sven Woop d55eb12d0e added vfloat4_sycl file 2019-12-02 11:33:55 +01:00
cbenthin abe4c5a200 Merge branch 'sycl' of https://gitlab.com/sdvis/embree into sycl 2019-12-02 10:37:36 +01:00
cbenthin f03eeb9fa4 new leaf encoding, debugging MB code 2019-12-02 10:37:28 +01:00
Sven Woop 9197ab0095 added virtual struct SYCL test 2019-12-02 10:00:09 +01:00
Sven Woop 3e45b6b1e2 printing device name 2019-12-02 08:14:01 +01:00
Sven Woop 8569234919 added sycl library test 2019-12-02 07:57:17 +01:00
Sven Woop bdd40710b7 updates to sycl tests 2019-11-29 15:34:10 +01:00
Sven Woop 80f54b3a4d updates to sycl tests 2019-11-29 15:21:29 +01:00
Sven Woop 7e0798f329 updates to sycl tests 2019-11-29 15:20:12 +01:00
Sven Woop 0dbbe1986e updates to sycl tests 2019-11-29 15:15:58 +01:00
Sven Woop 183c7e00df updates to sycl tests 2019-11-29 15:15:26 +01:00
Sven Woop 696d09d41f updates to sycl tests 2019-11-29 15:11:13 +01:00
Sven Woop e899659072 updates to sycl tests 2019-11-29 15:10:01 +01:00
Sven Woop 81e6aea43b updates to sycl tests 2019-11-29 15:08:49 +01:00
Sven Woop 75fdff2daf updates to sycl tests 2019-11-29 14:58:50 +01:00
Sven Woop 1ac4e0e7d0 updates to function pointer test 2019-11-29 14:35:44 +01:00
Sven Woop f02ffaf2a3 added function pointer test 2019-11-29 14:07:44 +01:00
Sven Woop efe4bbf708 added subgroup test 2019-11-29 12:02:31 +01:00
Sven Woop e53bd68813 testing usm 2019-11-29 11:45:11 +01:00
Sven Woop aff1b8a892 updates to sycl tests 2019-11-29 11:28:10 +01:00
cbenthin d4555d6a93 Merge branch 'sycl' of https://gitlab.com/sdvis/embree into sycl 2019-11-29 10:53:24 +01:00
Sven Woop a7ed267a88 added simple sycl example 2019-11-29 10:52:09 +01:00
cbenthin e25ebea61d updates 2019-11-28 16:12:29 +01:00
cbenthin c6c56e8faf updates 2019-11-28 15:48:27 +01:00
cbenthin 1cdc1da6e1 updates to mb code 2019-11-28 12:40:05 +01:00
cbenthin d3b86a6ce0 correctly lerping bounds0 and bounds1 2019-11-27 20:53:12 +01:00
cbenthin 654960f178 updates 2019-11-27 15:31:28 +01:00
cbenthin c0416b600c updates 2019-11-27 11:05:55 +01:00
cbenthin af0458922f mb infrastructure updates 2019-11-26 18:49:18 +01:00
cbenthin 1047a791a9 Merge remote-tracking branch 'origin/devel' into sycl 2019-11-25 14:51:23 +01:00
cbenthin e2ee296b51 moving general templated trav+isec code to header 2019-11-25 14:51:08 +01:00
cbenthin bcb4d3ec41 seperated out child node sorting code 2019-11-25 14:31:24 +01:00
cbenthin 5fcd9ede79 more updates 2019-11-22 18:38:22 +01:00
cbenthin 6616c827ff more infrastructure updates 2019-11-22 16:28:04 +01:00
cbenthin 644c81fdeb updates 2019-11-22 12:32:53 +01:00
cbenthin 48090a347e infrastructure updates 2019-11-22 11:07:00 +01:00
cbenthin 791b07a297 more infrastructure updates 2019-11-21 19:29:12 +01:00
cbenthin eafceb14d7 mb infrastructure updates 2019-11-21 18:04:57 +01:00
cbenthin 26c77304c8 Merge remote-tracking branch 'origin/devel' into sycl 2019-11-21 14:23:30 +01:00
cbenthin 7741c659bc infrastructure updates 2019-11-21 14:23:14 +01:00
cbenthin 6a217105ff updates 2019-11-21 14:14:27 +01:00
Dmitry Babokin 09f938aa79 Explicitly specifying type for reduction identities 2019-11-20 09:53:43 -08:00
Dmitry Babokin 8cff1df627 Complete DeviceGPU initilization correctly with out CPU device 2019-11-20 09:00:20 -08:00
cbenthin 2fcc39aaec changing sycl exception catching code 2019-11-20 15:03:03 +01:00
cbenthin 8fc8c7d745 indirect fct call test, causes hang 2019-11-20 14:23:51 +01:00
Dmitry Babokin 02745407c1 Validate CMAKE_BUILD_TYPE 2019-11-19 17:02:25 -08:00
cbenthin 5af7ce6b1c fct calls still don't work with latest run-time 2019-11-19 20:34:49 +01:00
cbenthin 5710b2b993 Merge branch 'sycl' of https://gitlab.com/sdvis/embree into sycl 2019-11-19 15:37:10 +01:00
cbenthin f46e3e88a7 adding infrastructure 2019-11-19 15:36:57 +01:00
Dmitry Babokin 767ac7bb0a Adding support for ISPC v1.13 2019-11-18 15:29:13 -08:00
cbenthin dfc03fe694 merge with devel 2019-11-18 14:38:35 +01:00
cbenthin 723bcd004a workaround for compiler bug wiht vector selects 2019-11-13 11:17:36 +01:00
cbenthin 38b62acdd6 fixed compile bugs with latest compiler drop 2019-11-12 17:12:51 +01:00
cbenthin 4ffcd740f5 taking fct address bug 2019-11-08 20:53:28 +01:00
cbenthin 383e254a94 passing active mask to traceRayBVH16 2019-11-08 16:33:53 +01:00
cbenthin ed98afda4a showcasing perf bug 2019-11-08 11:18:00 +01:00
cbenthin cf3abbec82 masked control flow causes huge slowdown, reason unknown 2019-11-07 15:17:48 +01:00
cbenthin 1db62bfe5b calling packet rtcIntersectGPU working 2019-11-07 10:54:07 +01:00
cbenthin e877c78acc packet input, single ray traversal internal working 2019-11-06 14:34:37 +01:00
cbenthin 657a1f9751 Merge remote-tracking branch 'origin/devel' into sycl 2019-11-06 12:14:39 +01:00
cbenthin 44363d2bff updates 2019-11-05 19:53:38 +01:00
cbenthin 9a46b465be updates, calls still not working 2019-11-05 18:33:02 +01:00
cbenthin 8edf29d179 mm 2019-11-05 13:32:31 +01:00
cbenthin 5c0b258b91 need dummy kernel to absorb initial USM costs 2019-11-04 13:54:24 +01:00
cbenthin f33716072e updated code to include fixes of the latest compiler drop 2019-11-01 12:37:06 +01:00
cbenthin 16e295ca29 verbose 2 prints out GPU BHV info now 2019-11-01 11:50:42 +01:00
cbenthin cd176187d7 enabled stream output buffer again 2019-11-01 11:29:06 +01:00
cbenthin db47037198 bugfix in breadth-firt builder phase 2019-10-31 14:11:58 +01:00
cbenthin b4d10fc0fe need to comment out unused sycl::stream implementation to get back usable perf 2019-10-30 17:42:59 +01:00
cbenthin de15d9cb6b need to comment out unused sycl::stream implementation to get back usable perf 2019-10-30 17:32:15 +01:00
cbenthin e9bcc59877 adapting static clang linker settings to make new sycl compiler work 2019-10-30 15:34:02 +01:00
cbenthin 661d3631c0 updates 2019-10-29 12:25:27 +01:00
cbenthin 14af2c3e00 merge 2019-10-29 12:21:37 +01:00
cbenthin f2ef01c6a8 Merge remote-tracking branch 'origin/devel' into sycl 2019-10-29 11:31:44 +01:00
cbenthin 4e2760f76e test 2019-10-24 17:33:56 +02:00
cbenthin 6d3ff20b84 merge with devel 2019-10-24 16:41:35 +02:00
cbenthin 3a545c34e9 test case for 32bit global_ptr issue 2019-10-17 19:17:07 +02:00
cbenthin e10f199e55 global_ptr<> issue 2019-10-17 16:32:00 +02:00
cbenthin 65dddf452c introducing ALIGNED_STRUCT_USM_ macro to make class USM visible, uses new internal_alignedMalloc calls 2019-10-17 15:56:13 +02:00
cbenthin bdbbb6a844 added global_ptr<> wrappers 2019-10-17 13:43:10 +02:00
cbenthin ebfc9116f4 code triggering bug 2019-10-17 10:46:37 +02:00
cbenthin 71449762ed Merge remote-tracking branch 'origin/devel' into sycl 2019-10-16 15:06:43 +02:00
cbenthin e062cbf14d merged with devel 2019-10-15 19:12:59 +02:00
cbenthin 1d79f7dfac cleanups to new sg reduction syntax 2019-10-15 18:46:40 +02:00
cbenthin 37715726a0 Merge remote-tracking branch 'origin/private/asachkov/update-sg-syntax' into sycl 2019-10-15 17:36:04 +02:00
cbenthin d8d16b46e5 disable fct call for now 2019-10-15 17:35:26 +02:00
Alexey Sachkov ce9e70be73 Use new sub-groups built-ins syntax 2019-10-14 17:01:46 +03:00
cbenthin c248db1c75 Merge remote-tracking branch 'origin/devel' into sycl 2019-10-04 08:09:14 +02:00
cbenthin 23a3d91246 simple SYCL_EXTERNAL fct call + static embree seems to work 2019-10-02 19:00:54 +02:00
cbenthin c22fedde2f updates 2019-10-02 15:32:31 +02:00
cbenthin b1ce99a1bf removed dbg outputs 2019-10-01 14:13:34 +02:00
cbenthin cf4601cbf5 Merge remote-tracking branch 'origin/devel' into sycl 2019-10-01 13:57:21 +02:00
cbenthin 1c01ef0541 updates 2019-10-01 11:29:13 +02:00
cbenthin ec67b001ac updates 2019-09-30 18:50:55 +02:00
cbenthin 8340afdc48 updates 2019-09-30 16:38:09 +02:00
cbenthin 0ba7904e10 fixes 2019-09-30 12:20:28 +02:00
cbenthin 83d03f5ff4 updates 2019-09-27 19:59:05 +02:00
cbenthin 120572f140 updates 2019-09-27 18:02:10 +02:00
cbenthin 2a9d7686fc integrated new presplit builder into fast spatial split builder as option 2019-09-27 17:27:41 +02:00
cbenthin 19a669d294 moved all presplit logic to seperate header file 2019-09-27 15:04:58 +02:00
cbenthin 2d41acb4db updates 2019-09-27 10:12:55 +02:00
cbenthin bf9e2f1791 parallel sorting step 2019-09-26 21:47:07 +02:00
cbenthin 425b572b6f cleanups 2019-09-26 19:34:54 +02:00
cbenthin 58f305e645 even better presplit builder 2019-09-26 18:12:08 +02:00
cbenthin c705db5f14 prepsplits working 2019-09-26 15:09:39 +02:00
cbenthin 2ff35d4ef8 added traversal stats, more presplit builder work 2019-09-26 10:37:46 +02:00
cbenthin 615110d256 first version of presplits 2019-09-25 19:37:14 +02:00
cbenthin e729819e3e merge with devel 2019-09-25 14:46:36 +02:00
cbenthin 23c82d464d Merge remote-tracking branch 'origin/devel' into sycl 2019-09-25 14:38:35 +02:00
cbenthin ee8aa70fc6 before sync 2019-09-25 14:38:23 +02:00
cbenthin bc9622b7dd passing expected number of primrefs to primrefgen, instead of querying prims.size() 2019-09-25 12:20:24 +02:00
cbenthin 0292f7c00c fixed compile errors 2019-09-25 11:06:41 +02:00
cbenthin b70f70d24a Merge remote-tracking branch 'origin/devel' into sycl 2019-09-23 13:43:21 +02:00
cbenthin 584d55c7bf code works with latest run-time and compiler again 2019-09-23 12:02:10 +02:00
cbenthin 64b0c34769 restored working version 2019-09-19 19:35:19 +02:00
cbenthin 57860ac6f5 linker bug 2019-09-19 17:55:29 +02:00
cbenthin d7e2c1cb3b restored working version 2019-09-18 14:58:39 +02:00
cbenthin 6ac028e83c fct call bug 2019-09-18 14:44:17 +02:00
cbenthin daeb2f0768 linker bug 2019-09-18 10:54:31 +02:00
cbenthin 94f68bc100 cpu device for serial stats gathering not working right now 2019-09-18 09:34:06 +02:00
cbenthin ea57db0e49 shading as kernel 2019-09-17 21:22:48 +02:00
cbenthin 0049d4d100 kernel for ray inits 2019-09-17 19:37:53 +02:00
cbenthin fadf381751 templated gpu stream intersector 2019-09-17 08:58:45 +02:00
cbenthin f9210cb471 updates 2019-09-16 20:17:40 +02:00
cbenthin 84be1637c7 standard fast tris/quads working 2019-09-16 19:37:49 +02:00
cbenthin eeb3748819 templated gpu traversal over primitive intersection 2019-09-16 14:52:22 +02:00
cbenthin f96ebc5fb3 updates to gpu tri/quad framework 2019-09-16 14:17:47 +02:00
cbenthin 2c18e8eb9f host initializes now leaf data based on USM primref array 2019-09-16 12:35:57 +02:00
cbenthin 981a9390e5 updates to triangle1v/quad1v 2019-09-16 12:02:59 +02:00
cbenthin 919280b8fc adding infrastructure 2019-09-16 11:53:27 +02:00
cbenthin ae73fa051e variable sized leaves now supported 2019-09-16 11:28:59 +02:00
cbenthin d7b663f1ac starting with support for tris 2019-09-14 11:09:13 +02:00
cbenthin be717ff6c6 Merge remote-tracking branch 'origin/devel' into sycl 2019-09-13 11:25:47 +02:00
cbenthin 9a43f88e5c adding compile options for unnamed lambdas 2019-09-13 11:25:35 +02:00
cbenthin e52d56ff8c compiles now with DPCPP support turned off 2019-09-12 23:17:36 +02:00
cbenthin f85322566e adding quad1v 2019-09-12 19:42:29 +02:00
cbenthin faa8303382 compile fixes 2019-09-12 17:10:14 +02:00
cbenthin a7ebec62ee noderefs with 32bit offsets 2019-09-12 16:18:21 +02:00
cbenthin f8861be1ce added explicit qbvh node intersection function to cleanup traversal code 2019-09-12 15:27:56 +02:00
cbenthin e32f0b7f24 reusing USM allocated primref array 2019-09-12 14:47:12 +02:00
cbenthin 976b13711c extended mvector with optional USM allocation support 2019-09-12 12:24:00 +02:00
cbenthin 423b0b6d65 Merge remote-tracking branch 'origin/devel' into sycl 2019-09-12 10:21:12 +02:00
cbenthin 72eeeed34d sync 2019-09-12 10:20:57 +02:00
cbenthin 218a004f7d updates 2019-09-11 18:47:50 +02:00
cbenthin 24c4619d67 more parallel_fors 2019-09-11 17:53:00 +02:00
cbenthin a431274108 fixes 2019-09-11 17:31:14 +02:00
cbenthin a487f021a8 simplified node layout, lots of cleanups 2019-09-11 14:47:20 +02:00
cbenthin 16d33a3268 updates 2019-09-11 10:56:37 +02:00
cbenthin f999c79ddf updates 2019-09-09 18:27:02 +02:00
cbenthin 8476f5fe74 updates to use sycl::ctz, requires updated compiler 2019-09-09 13:46:30 +02:00
cbenthin ef0f6ba977 cleanups 2019-09-08 18:43:45 +02:00
cbenthin 21dd453dec updates and cleanups 2019-09-08 11:11:41 +02:00
cbenthin 6d8d752a83 parallel phase working 2019-09-08 10:26:53 +02:00
cbenthin 4fb35c1144 first version of working breadth first phase 2019-09-07 18:04:11 +02:00
cbenthin 9496d741e1 more updates to breadth first phase 2019-09-07 11:43:36 +02:00
cbenthin bcb54b9099 more fixes and checks 2019-09-07 11:06:45 +02:00
cbenthin c95b346fc4 fixes 2019-09-07 10:48:08 +02:00
cbenthin b9c84040f1 deactivating parallel partition for now 2019-09-06 21:16:16 +02:00
cbenthin deccb6eb63 parallel partition 2019-09-06 16:26:47 +02:00
cbenthin 283514078f bugfix 2019-09-06 12:42:46 +02:00
cbenthin 94db952ef6 debugging 2019-09-06 12:30:46 +02:00
cbenthin 4fe317bb52 updates 2019-09-05 22:26:32 +02:00
cbenthin f695109205 more updates 2019-09-05 20:00:57 +02:00
cbenthin fe601f8509 first version of find_parallel_split 2019-09-05 18:50:19 +02:00
cbenthin c1df3629e0 added sorting of children within a wide node 2019-09-05 15:57:50 +02:00
cbenthin 1f430a9c3b fixed nullptr dereference 2019-09-05 14:40:17 +02:00
cbenthin e83ea3039e added reduceBins32 2019-09-05 14:22:31 +02:00
Evgeniy Tyurin 5a160bfdd5 Add possibility to select CPU device with EMBREE_USE_CPU env var 2019-09-05 14:34:45 +03:00
cbenthin 428cefec6c infrastructure for reducing 32 bins 2019-09-05 11:58:51 +02:00
cbenthin 308a67442e updates 2019-09-05 08:57:15 +02:00
cbenthin 891a352967 adding infrastructure 2019-09-04 19:53:30 +02:00
cbenthin 7a4494efe0 sorting networks 2019-09-04 18:30:28 +02:00
cbenthin 1810141d97 adding bvh stats generation 2019-09-04 16:55:38 +02:00
cbenthin d3701fdd36 enabled stack culling 2019-09-03 22:01:20 +02:00
cbenthin 3c22966cec changed default res to 1024^2 2019-09-03 19:58:34 +02:00
cbenthin aabee86bc3 workaround for broken sycl::dot 2019-09-03 19:51:57 +02:00
cbenthin d7882d4b81 dot bug 2019-09-03 16:04:14 +02:00
cbenthin 3e4fa9613c disabled compiler warnings 2019-09-03 08:39:08 +02:00
cbenthin 31f5b20de8 cleanups 2019-09-02 22:19:46 +02:00
cbenthin 71d3c6409d bugfix 2019-09-02 21:46:43 +02:00
cbenthin 801220ed5d debugging 2019-09-02 20:25:59 +02:00
cbenthin ea5133fe9d qbvh nodes 2019-09-02 19:07:55 +02:00
cbenthin c5bb4b2e40 updates 2019-09-02 18:03:12 +02:00
cbenthin 130b455be0 updates 2019-09-02 14:55:50 +02:00
cbenthin f2934a9f5d cornell box working 2019-09-02 11:42:45 +02:00
cbenthin 2a73d3f97d Merge remote-tracking branch 'origin/devel' into sycl 2019-09-02 10:44:51 +02:00
cbenthin 21492a112c update 2019-09-02 10:44:38 +02:00
cbenthin ee76baca76 debugging 2019-09-02 10:20:53 +02:00
cbenthin cf430a3ac4 updates 2019-09-01 15:28:22 +02:00
cbenthin 1b7116b333 updates and fixes 2019-09-01 13:58:25 +02:00
cbenthin 67f3f1d33f updates and fixes 2019-09-01 12:36:06 +02:00
cbenthin 96ee4d5917 trav updates 2019-08-30 21:17:31 +02:00
cbenthin 11d99d6722 testing ballot 2019-08-30 14:58:54 +02:00
cbenthin 6f7e3ecca4 workarounds 2019-08-28 20:35:56 +02:00
cbenthin ab1d6a7b49 adding gpu/sycl specific ray class 2019-08-28 19:10:21 +02:00
cbenthin c35c788a09 updates 2019-08-28 15:33:37 +02:00
cbenthin 445810a1e7 moving gpu device init to app code, just passing device and queue ptrs to Embree 2019-08-28 12:20:38 +02:00
cbenthin 92701d1e8c updates 2019-08-27 22:14:21 +02:00
cbenthin 30a4760fa7 Merge remote-tracking branch 'origin/devel' into sycl 2019-08-27 19:14:53 +02:00
cbenthin 7f9c24005a updates 2019-08-27 19:14:44 +02:00
cbenthin 74d838c981 added missing files 2019-08-27 16:50:51 +02:00
cbenthin d90b52f0bb restructering, working on stream intersector, broadcast->shuffle 2019-08-27 14:22:47 +02:00
cbenthin 5481b9fa16 Merge remote-tracking branch 'origin/devel' into sycl 2019-08-26 10:43:32 +02:00
cbenthin ab711bb34a splitting up files 2019-08-23 12:26:31 +02:00
cbenthin 38c1b8f701 removing ctor workarounds 2019-08-23 12:06:12 +02:00
cbenthin 11c29c8561 updates 2019-08-22 19:49:47 +02:00
cbenthin 26870da323 removed stream workaround 2019-08-22 18:42:23 +02:00
cbenthin cd55a49d63 compute bounds general iterates in WG sized steps for now 2019-08-22 18:21:24 +02:00
cbenthin 7907538a53 updates 2019-08-22 18:04:12 +02:00
cbenthin b44d736167 cleanups 2019-08-22 14:54:25 +02:00
cbenthin daf4450820 merge with devel 2019-08-22 11:46:36 +02:00
cbenthin 2a5ae73d01 Merge remote-tracking branch 'origin/devel' into sycl 2019-08-22 11:20:05 +02:00
cbenthin e99200ca6e fixes 2019-08-22 11:19:44 +02:00
cbenthin 957475814f replacing buffers by USM 2019-08-21 20:27:43 +02:00
cbenthin 2cf4d08bad before usm tests 2019-08-21 19:52:28 +02:00
cbenthin a9e03a598f updates 2019-08-21 16:20:44 +02:00
cbenthin ea33e05bea updates 2019-08-21 15:48:41 +02:00
cbenthin 50ba2ab635 updates 2019-08-21 15:19:31 +02:00
cbenthin 7b522de25b updates 2019-08-21 14:00:48 +02:00
cbenthin 1eec731b10 updates 2019-08-20 20:38:06 +02:00
cbenthin a9a3a60efe compiler bug... 2019-08-19 21:38:51 +02:00
cbenthin 41414000d4 updates & fixes, still not working 2019-08-19 12:25:50 +02:00
cbenthin a435db84ca updates 2019-08-16 16:31:21 +02:00
cbenthin 96363fbdcf more updates 2019-08-13 15:46:37 +02:00
cbenthin 8b6e6ac862 stream hang bug 2019-08-09 19:29:25 +02:00
cbenthin 2a77b9b624 split changes 2019-08-09 14:51:51 +02:00
cbenthin 38f801411a stream issue 2019-08-09 14:40:58 +02:00
cbenthin d57f7b7905 updates 2019-08-09 11:32:58 +02:00
cbenthin da2ffd6368 printf->sycl::stream due to compiler change 2019-08-09 11:26:29 +02:00
cbenthin cebcc1d216 updates 2019-08-08 19:01:56 +02:00
cbenthin d8053e29ab compiles again with latest compiler drop 2019-08-08 17:18:31 +02:00
cbenthin d54d4fb03c adding exception handling 2019-07-05 10:28:55 +02:00
cbenthin 1eae987941 triggering run-time bug 2019-07-04 19:31:55 +02:00
cbenthin 6bc8231cfe adding more code 2019-07-04 18:31:43 +02:00
cbenthin 91b80b2c0b workaround for compile errors 2019-07-04 17:23:05 +02:00
cbenthin cd4be2844f ccompiler bug 2019-06-28 11:32:31 +02:00
cbenthin 000acc1358 updates 2019-06-27 11:41:08 +02:00
cbenthin 99677bb22d porting more code 2019-06-26 21:26:38 +02:00
cbenthin 49b98b168f updates 2019-06-26 15:04:21 +02:00
cbenthin 9a0f9a610e larger restructs 2019-06-26 13:51:17 +02:00
cbenthin 1157bb3384 cleanups & updates 2019-06-26 11:57:18 +02:00
cbenthin ef28a21b63 updates 2019-06-26 11:28:10 +02:00
cbenthin ffe7d21945 updates 2019-06-25 16:38:29 +02:00
cbenthin c83f601508 updates 2019-06-20 19:46:19 +02:00
cbenthin 3ea6f3ef8f updates 2019-06-20 18:19:28 +02:00
cbenthin 9800fe45d8 working on bvh builder 2019-06-20 16:10:52 +02:00
cbenthin d08cb07fcf updates 2019-06-19 21:24:45 +02:00
cbenthin f17d7c627a updates 2019-06-19 20:20:20 +02:00
cbenthin 2fd16c26bb updates 2019-06-19 16:16:29 +02:00
cbenthin 15c81b8218 updates 2019-06-19 15:31:58 +02:00
cbenthin 058e9ce72a updates 2019-06-19 15:26:20 +02:00
cbenthin 55f0680d3b Merge remote-tracking branch 'origin/devel' into sycl 2019-06-18 11:11:51 +02:00
cbenthin e0dc1ee8fe some workaround for removing ambiguous between embree and sycl device 2019-06-17 11:12:29 +02:00
cbenthin fbca0fc7cc enabling ctor causes compile error 2019-06-07 10:46:29 +02:00
cbenthin 57b56531f3 updates 2019-06-07 10:45:11 +02:00
cbenthin 7fa9f08b7b updates 2019-06-07 10:40:38 +02:00
cbenthin 1b636a88ba updates 2019-06-07 10:40:18 +02:00
cbenthin 7e80b37265 version generating compiler errors 2019-05-31 13:41:47 +02:00
cbenthin 7abf88af73 updates and fixes 2019-05-31 11:58:10 +02:00
cbenthin 9e2a8dcab4 this version causes a hard freeze 2019-05-30 19:53:46 +02:00
cbenthin 5414ab5fcc updates 2019-05-30 16:39:31 +02:00
cbenthin 8a5d3b6500 updates 2019-05-30 14:15:08 +02:00
cbenthin bfc0798962 updates 2019-05-28 21:26:33 +02:00
cbenthin b62ad99982 updates 2019-05-28 21:06:22 +02:00
cbenthin ab550c2381 updates 2019-05-28 20:04:32 +02:00
cbenthin b74e6d6ab0 updates 2019-05-28 15:55:46 +02:00
cbenthin 3a85df53c6 temporarily disabled convert tutorial due to clang issues 2019-05-28 14:46:39 +02:00
cbenthin 350f214d95 updates 2019-05-22 19:37:20 +02:00
cbenthin 48dced1260 updates 2019-05-22 14:31:05 +02:00
cbenthin f141ed5fae updates 2019-05-22 14:30:22 +02:00
cbenthin 574ac598b1 updates 2019-05-21 21:53:02 +02:00
cbenthin 023ee677d6 updates 2019-05-21 18:06:54 +02:00
cbenthin 16753a99d1 updates 2019-05-21 16:30:16 +02:00
cbenthin d0fa655775 Merge remote-tracking branch 'origin/devel' into sycl 2019-05-21 13:56:02 +02:00
cbenthin 78eb9c2693 Merge remote-tracking branch 'origin/devel' into sycl 2019-05-21 13:44:06 +02:00
cbenthin 32a7efcecd Merge remote-tracking branch 'origin/devel' into sycl 2019-05-20 11:55:53 +02:00
cbenthin b1b145c253 Merge remote-tracking branch 'origin/devel' into sycl 2019-05-17 18:25:11 +02:00
cbenthin c21d7a5e7c more infrastructure 2019-05-17 18:24:56 +02:00
cbenthin b259057f2a infrastructure work, adding triangle1v and primitive1 2019-05-17 15:39:41 +02:00
cbenthin 8edf00e43a updates 2019-05-16 20:02:54 +02:00
cbenthin b190878fb0 updates 2019-05-16 18:42:12 +02:00
cbenthin c9bad6a566 Merge remote-tracking branch 'origin/devel' into sycl 2019-05-16 15:25:19 +02:00
cbenthin 5201912a41 init code works 2019-05-16 15:22:24 +02:00
cbenthin 684a3316ab updates 2019-05-15 18:36:04 +02:00
106 changed files with 11133 additions and 237 deletions
+16 -2
View File
@@ -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
##############################################################
+20 -4
View File
@@ -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()
+10
View File
@@ -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})
+5 -3
View File
@@ -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
}
+9 -3
View File
@@ -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
////////////////////////////////////////////////////////////////////////////////
+8
View File
@@ -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
+273
View File
@@ -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
}
+4
View File
@@ -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
}
+9
View File
@@ -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
+129
View File
@@ -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;
}
}
+9
View File
@@ -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
+318
View File
@@ -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;
}
+9
View File
@@ -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
+188
View File
@@ -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;
}
}
+5
View File
@@ -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
}
+7
View File
@@ -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
+27
View File
@@ -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
View File
@@ -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;
+220
View File
@@ -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;
}
}
+595
View File
@@ -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;
}
}
+482
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+5
View File
@@ -76,6 +76,11 @@ namespace embree
return *this;
}
__forceinline allocator& getAlloc()
{
return alloc;
}
/********************** Iterators ****************************/
__forceinline iterator begin() { return items; };
+3 -1
View File
@@ -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 */
+3
View File
@@ -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);
+9
View File
@@ -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);
+6 -2
View File
@@ -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)
+2 -2
View File
@@ -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];
+2 -2
View File
@@ -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];
+2
View File
@@ -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
View File
@@ -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;
};
//}
}
+10 -10
View File
@@ -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
+5 -5
View File
@@ -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);
+1
View File
@@ -199,5 +199,6 @@ namespace embree
#if !defined(__AVX__) || !defined(EMBREE_TARGET_SSE2) && !defined(EMBREE_TARGET_SSE42)
template class BVHN<4>;
#endif
}
+16 -4
View File
@@ -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;
}
+2
View File
@@ -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
+871
View File
@@ -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
}
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+9 -5
View File
@@ -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
+2 -2
View File
@@ -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; }
+4 -2
View File
@@ -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);
+178
View File
@@ -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
}
+69
View File
@@ -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
}
+227
View File
@@ -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);
+209
View File
@@ -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
};
};
+7
View File
@@ -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;
+6
View File
@@ -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;
};
+1 -1
View File
@@ -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)
+19
View File
@@ -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
};
}
+1 -1
View File
@@ -20,7 +20,7 @@
#include "accel.h"
namespace embree
{
{
#define MODE_HIGH_QUALITY (1<<8)
/*! virtual interface for all hierarchy builders */
+4
View File
@@ -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;
+78
View File
@@ -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
}
+49
View File
@@ -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
}
+2 -1
View File
@@ -131,7 +131,8 @@ namespace embree
std::swap(a,b);
#endif
}
/************************************************************************************/
/************************************************************************************/
/************************************************************************************/
+47 -15
View File
@@ -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);
+6 -4
View File
@@ -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"); \
}
+6 -6
View File
@@ -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);
+48 -2
View File
@@ -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();
+3 -2
View File
@@ -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
+5 -1
View File
@@ -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;
}
+2
View File
@@ -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
View File
@@ -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 */
+103
View File
@@ -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);
}
}
+136
View File
@@ -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;
}
+134
View File
@@ -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
};
}
+130
View File
@@ -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;
}
+134
View File
@@ -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;
};
}
+13 -1
View File
@@ -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()));
}
};
+179
View File
@@ -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
+173
View File
@@ -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
+688
View File
@@ -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 &centBounds, 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
+695
View File
@@ -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
+193
View File
@@ -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
+337
View File
@@ -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
+124
View File
@@ -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
+2 -1
View File
@@ -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)
+2
View File
@@ -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
+2 -1
View File
@@ -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");
+2 -1
View File
@@ -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
+53 -9
View File
@@ -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);
+7
View File
@@ -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)
+100
View File
@@ -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.
+42
View File
@@ -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;
}
+10
View File
@@ -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&);
+133
View File
@@ -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;
}
+784
View File
@@ -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;
}
+1 -1
View File
@@ -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