1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#include "bvh.h"
5#include "bvh_builder.h"
6#include "../builders/primrefgen.h"
7#include "../builders/splitter.h"
8
9#include "../geometry/linei.h"
10#include "../geometry/triangle.h"
11#include "../geometry/trianglev.h"
12#include "../geometry/trianglev_mb.h"
13#include "../geometry/trianglei.h"
14#include "../geometry/quadv.h"
15#include "../geometry/quadi.h"
16#include "../geometry/object.h"
17#include "../geometry/instance.h"
18#include "../geometry/subgrid.h"
19
20#include "../common/state.h"
21#include "../../common/algorithms/parallel_for_for.h"
22#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
23
24#define PROFILE 0
25#define PROFILE_RUNS 20
26
27namespace embree
28{
29 namespace isa
30 {
31 template<int N, typename Primitive>
32 struct CreateLeaf
33 {
34 typedef BVHN<N> BVH;
35 typedef typename BVH::NodeRef NodeRef;
36
37 __forceinline CreateLeaf (BVH* bvh) : bvh(bvh) {}
38
39 __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
40 {
41 size_t n = set.size();
42 size_t items = Primitive::blocks(n);
43 size_t start = set.begin();
44 Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
45 typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
46 for (size_t i=0; i<items; i++) {
47 accel[i].fill(prims,start,set.end(),bvh->scene);
48 }
49 return node;
50 }
51
52 BVH* bvh;
53 };
54
55
56 template<int N, typename Primitive>
57 struct CreateLeafQuantized
58 {
59 typedef BVHN<N> BVH;
60 typedef typename BVH::NodeRef NodeRef;
61
62 __forceinline CreateLeafQuantized (BVH* bvh) : bvh(bvh) {}
63
64 __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
65 {
66 size_t n = set.size();
67 size_t items = Primitive::blocks(n);
68 size_t start = set.begin();
69 Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
70 typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,items);
71 for (size_t i=0; i<items; i++) {
72 accel[i].fill(prims,start,set.end(),bvh->scene);
73 }
74 return node;
75 }
76
77 BVH* bvh;
78 };
79
80 /************************************************************************************/
81 /************************************************************************************/
82 /************************************************************************************/
83 /************************************************************************************/
84
85 template<int N, typename Primitive>
86 struct BVHNBuilderSAH : public Builder
87 {
88 typedef BVHN<N> BVH;
89 typedef typename BVHN<N>::NodeRef NodeRef;
90
91 BVH* bvh;
92 Scene* scene;
93 Geometry* mesh;
94 mvector<PrimRef> prims;
95 GeneralBVHBuilder::Settings settings;
96 Geometry::GTypeMask gtype_;
97 unsigned int geomID_ = std::numeric_limits<unsigned int>::max ();
98 bool primrefarrayalloc;
99 unsigned int numPreviousPrimitives = 0;
100
101 BVHNBuilderSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize,
102 const Geometry::GTypeMask gtype, bool primrefarrayalloc = false)
103 : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0),
104 settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), primrefarrayalloc(primrefarrayalloc) {}
105
106 BVHNBuilderSAH (BVH* bvh, Geometry* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
107 : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), geomID_(geomID), primrefarrayalloc(false) {}
108
109 // FIXME: shrink bvh->alloc in destructor here and in other builders too
110
111 void build()
112 {
113 /* we reset the allocator when the mesh size changed */
114 if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
115 bvh->alloc.clear();
116 }
117
118 /* if we use the primrefarray for allocations we have to take it back from the BVH */
119 if (settings.primrefarrayalloc != size_t(inf))
120 bvh->alloc.unshare(prims);
121
122 /* skip build for empty scene */
123 const size_t numPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(gtype_,false);
124 numPreviousPrimitives = numPrimitives;
125 if (numPrimitives == 0) {
126 bvh->clear();
127 prims.clear();
128 return;
129 }
130
131 double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderSAH");
132
133#if PROFILE
134 profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
135#endif
136
137 /* create primref array */
138 if (primrefarrayalloc) {
139 settings.primrefarrayalloc = numPrimitives/1000;
140 if (settings.primrefarrayalloc < 1000)
141 settings.primrefarrayalloc = inf;
142 }
143
144 /* enable os_malloc for two level build */
145 if (mesh)
146 bvh->alloc.setOSallocation(true);
147
148 /* initialize allocator */
149 const size_t node_bytes = numPrimitives*sizeof(typename BVH::AABBNodeMB)/(4*N);
150 const size_t leaf_bytes = size_t(1.2*Primitive::blocks(numPrimitives)*sizeof(Primitive));
151 bvh->alloc.init_estimate(node_bytes+leaf_bytes);
152 settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
153 prims.resize(numPrimitives);
154
155 PrimInfo pinfo = mesh ?
156 createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) :
157 createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
158
159 /* pinfo might has zero size due to invalid geometry */
160 if (unlikely(pinfo.size() == 0))
161 {
162 bvh->clear();
163 prims.clear();
164 return;
165 }
166
167 /* call BVH builder */
168 NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeaf<N,Primitive>(bvh),bvh->scene->progressInterface,prims.data(),pinfo,settings);
169 bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
170 bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
171
172#if PROFILE
173 });
174#endif
175
176 /* if we allocated using the primrefarray we have to keep it alive */
177 if (settings.primrefarrayalloc != size_t(inf))
178 bvh->alloc.share(prims);
179
180 /* for static geometries we can do some cleanups */
181 else if (scene && scene->isStaticAccel()) {
182 prims.clear();
183 }
184 bvh->cleanup();
185 bvh->postBuild(t0);
186 }
187
188 void clear() {
189 prims.clear();
190 }
191 };
192
193 /************************************************************************************/
194 /************************************************************************************/
195 /************************************************************************************/
196 /************************************************************************************/
197
198 template<int N, typename Primitive>
199 struct BVHNBuilderSAHQuantized : public Builder
200 {
201 typedef BVHN<N> BVH;
202 typedef typename BVHN<N>::NodeRef NodeRef;
203
204 BVH* bvh;
205 Scene* scene;
206 Geometry* mesh;
207 mvector<PrimRef> prims;
208 GeneralBVHBuilder::Settings settings;
209 Geometry::GTypeMask gtype_;
210 unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
211 unsigned int numPreviousPrimitives = 0;
212
213 BVHNBuilderSAHQuantized (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
214 : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype) {}
215
216 BVHNBuilderSAHQuantized (BVH* bvh, Geometry* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
217 : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), gtype_(gtype), geomID_(geomID) {}
218
219 // FIXME: shrink bvh->alloc in destructor here and in other builders too
220
221 void build()
222 {
223 /* we reset the allocator when the mesh size changed */
224 if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
225 bvh->alloc.clear();
226 }
227
228 /* skip build for empty scene */
229 const size_t numPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(gtype_,false);
230 numPreviousPrimitives = numPrimitives;
231 if (numPrimitives == 0) {
232 prims.clear();
233 bvh->clear();
234 return;
235 }
236
237 double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::QBVH" + toString(N) + "BuilderSAH");
238
239#if PROFILE
240 profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
241#endif
242 /* create primref array */
243 prims.resize(numPrimitives);
244 PrimInfo pinfo = mesh ?
245 createPrimRefArray(mesh,geomID_,numPrimitives,prims,bvh->scene->progressInterface) :
246 createPrimRefArray(scene,gtype_,false,numPrimitives,prims,bvh->scene->progressInterface);
247
248 /* enable os_malloc for two level build */
249 if (mesh)
250 bvh->alloc.setOSallocation(true);
251
252 /* call BVH builder */
253 const size_t node_bytes = numPrimitives*sizeof(typename BVH::QuantizedNode)/(4*N);
254 const size_t leaf_bytes = size_t(1.2*Primitive::blocks(numPrimitives)*sizeof(Primitive));
255 bvh->alloc.init_estimate(node_bytes+leaf_bytes);
256 settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
257 NodeRef root = BVHNBuilderQuantizedVirtual<N>::build(&bvh->alloc,CreateLeafQuantized<N,Primitive>(bvh),bvh->scene->progressInterface,prims.data(),pinfo,settings);
258 bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
259 //bvh->layoutLargeNodes(pinfo.size()*0.005f); // FIXME: COPY LAYOUT FOR LARGE NODES !!!
260#if PROFILE
261 });
262#endif
263
264 /* clear temporary data for static geometry */
265 if (scene && scene->isStaticAccel()) {
266 prims.clear();
267 }
268 bvh->cleanup();
269 bvh->postBuild(t0);
270 }
271
272 void clear() {
273 prims.clear();
274 }
275 };
276
277 /************************************************************************************/
278 /************************************************************************************/
279 /************************************************************************************/
280 /************************************************************************************/
281
282
283 template<int N, typename Primitive>
284 struct CreateLeafGrid
285 {
286 typedef BVHN<N> BVH;
287 typedef typename BVH::NodeRef NodeRef;
288
289 __forceinline CreateLeafGrid (BVH* bvh, const SubGridBuildData * const sgrids) : bvh(bvh),sgrids(sgrids) {}
290
291 __forceinline NodeRef operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
292 {
293 const size_t items = set.size(); //Primitive::blocks(n);
294 const size_t start = set.begin();
295
296 /* collect all subsets with unique geomIDs */
297 assert(items <= N);
298 unsigned int geomIDs[N];
299 unsigned int num_geomIDs = 1;
300 geomIDs[0] = prims[start].geomID();
301
302 for (size_t i=1;i<items;i++)
303 {
304 bool found = false;
305 const unsigned int new_geomID = prims[start+i].geomID();
306 for (size_t j=0;j<num_geomIDs;j++)
307 if (new_geomID == geomIDs[j])
308 { found = true; break; }
309 if (!found)
310 geomIDs[num_geomIDs++] = new_geomID;
311 }
312
313 /* allocate all leaf memory in one single block */
314 SubGridQBVHN<N>* accel = (SubGridQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridQBVHN<N>),BVH::byteAlignment);
315 typename BVH::NodeRef node = BVH::encodeLeaf((char*)accel,num_geomIDs);
316
317 for (size_t g=0;g<num_geomIDs;g++)
318 {
319 unsigned int x[N];
320 unsigned int y[N];
321 unsigned int primID[N];
322 BBox3fa bounds[N];
323 unsigned int pos = 0;
324 for (size_t i=0;i<items;i++)
325 {
326 if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
327
328 const SubGridBuildData& sgrid_bd = sgrids[prims[start+i].primID()];
329 x[pos] = sgrid_bd.sx;
330 y[pos] = sgrid_bd.sy;
331 primID[pos] = sgrid_bd.primID;
332 bounds[pos] = prims[start+i].bounds();
333 pos++;
334 }
335 assert(pos <= N);
336 new (&accel[g]) SubGridQBVHN<N>(x,y,primID,bounds,geomIDs[g],pos);
337 }
338
339 return node;
340 }
341
342 BVH* bvh;
343 const SubGridBuildData * const sgrids;
344 };
345
346
347 template<int N>
348 struct BVHNBuilderSAHGrid : public Builder
349 {
350 typedef BVHN<N> BVH;
351 typedef typename BVHN<N>::NodeRef NodeRef;
352
353 BVH* bvh;
354 Scene* scene;
355 GridMesh* mesh;
356 mvector<PrimRef> prims;
357 mvector<SubGridBuildData> sgrids;
358 GeneralBVHBuilder::Settings settings;
359 const unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
360 unsigned int numPreviousPrimitives = 0;
361
362 BVHNBuilderSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
363 : bvh(bvh), scene(scene), mesh(nullptr), prims(scene->device,0), sgrids(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD) {}
364
365 BVHNBuilderSAHGrid (BVH* bvh, GridMesh* mesh, unsigned int geomID, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const size_t mode)
366 : bvh(bvh), scene(nullptr), mesh(mesh), prims(bvh->device,0), sgrids(scene->device,0), settings(sahBlockSize, minLeafSize, min(maxLeafSize,BVH::maxLeafBlocks), travCost, intCost, DEFAULT_SINGLE_THREAD_THRESHOLD), geomID_(geomID) {}
367
368 void build()
369 {
370 /* we reset the allocator when the mesh size changed */
371 if (mesh && mesh->numPrimitives != numPreviousPrimitives) {
372 bvh->alloc.clear();
373 }
374
375 /* if we use the primrefarray for allocations we have to take it back from the BVH */
376 if (settings.primrefarrayalloc != size_t(inf))
377 bvh->alloc.unshare(prims);
378
379 const size_t numGridPrimitives = mesh ? mesh->size() : scene->getNumPrimitives(GridMesh::geom_type,false);
380 numPreviousPrimitives = numGridPrimitives;
381
382
383 PrimInfo pinfo = mesh ? createPrimRefArrayGrids(mesh,prims,sgrids) : createPrimRefArrayGrids(scene,prims,sgrids);
384 const size_t numPrimitives = pinfo.size();
385 /* no primitives */
386 if (numPrimitives == 0) {
387 bvh->clear();
388 prims.clear();
389 sgrids.clear();
390 return;
391 }
392
393 double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderSAH");
394
395 /* create primref array */
396 settings.primrefarrayalloc = numPrimitives/1000;
397 if (settings.primrefarrayalloc < 1000)
398 settings.primrefarrayalloc = inf;
399
400 /* enable os_malloc for two level build */
401 if (mesh)
402 bvh->alloc.setOSallocation(true);
403
404 /* initialize allocator */
405 const size_t node_bytes = numPrimitives*sizeof(typename BVH::AABBNodeMB)/(4*N);
406 const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
407
408 bvh->alloc.init_estimate(node_bytes+leaf_bytes);
409 settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,numPrimitives,node_bytes+leaf_bytes);
410
411 /* pinfo might has zero size due to invalid geometry */
412 if (unlikely(pinfo.size() == 0))
413 {
414 bvh->clear();
415 sgrids.clear();
416 prims.clear();
417 return;
418 }
419
420 /* call BVH builder */
421 NodeRef root = BVHNBuilderVirtual<N>::build(&bvh->alloc,CreateLeafGrid<N,SubGridQBVHN<N>>(bvh,sgrids.data()),bvh->scene->progressInterface,prims.data(),pinfo,settings);
422 bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
423 bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f));
424
425 /* clear temporary array */
426 sgrids.clear();
427
428 /* if we allocated using the primrefarray we have to keep it alive */
429 if (settings.primrefarrayalloc != size_t(inf))
430 bvh->alloc.share(prims);
431
432 /* for static geometries we can do some cleanups */
433 else if (scene && scene->isStaticAccel()) {
434 prims.clear();
435 }
436 bvh->cleanup();
437 bvh->postBuild(t0);
438 }
439
440 void clear() {
441 prims.clear();
442 }
443 };
444
445 /************************************************************************************/
446 /************************************************************************************/
447 /************************************************************************************/
448 /************************************************************************************/
449
450
451#if defined(EMBREE_GEOMETRY_TRIANGLE)
452 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); }
453 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); }
454 Builder* BVH4Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Triangle4i>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
455
456 Builder* BVH4Triangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Triangle4>((BVH4*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
457 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); }
458 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); }
459
460 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); }
461#if defined(__AVX__)
462 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); }
463 Builder* BVH8Triangle4vMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4v>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
464 Builder* BVH8Triangle4iMeshBuilderSAH (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Triangle4i>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,TriangleMesh::geom_type); }
465
466 Builder* BVH8Triangle4SceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
467 Builder* BVH8Triangle4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4v>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type); }
468 Builder* BVH8Triangle4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,TriangleMesh::geom_type,true); }
469 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); }
470 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); }
471
472
473
474#endif
475#endif
476
477#if defined(EMBREE_GEOMETRY_QUAD)
478 Builder* BVH4Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Quad4v>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
479 Builder* BVH4Quad4iMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<4,Quad4i>((BVH4*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
480 Builder* BVH4Quad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Quad4v>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
481 Builder* BVH4Quad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<4,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type,true); }
482 Builder* BVH4QuantizedQuad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Quad4v>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
483 Builder* BVH4QuantizedQuad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<4,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
484
485#if defined(__AVX__)
486 Builder* BVH8Quad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Quad4v>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
487 Builder* BVH8Quad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAH<8,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type,true); }
488 Builder* BVH8QuantizedQuad4vSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Quad4v>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
489 Builder* BVH8QuantizedQuad4iSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHQuantized<8,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,QuadMesh::geom_type); }
490 Builder* BVH8Quad4vMeshBuilderSAH (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAH<8,Quad4v>((BVH8*)bvh,mesh,geomID,4,1.0f,4,inf,QuadMesh::geom_type); }
491
492#endif
493#endif
494
495#if defined(EMBREE_GEOMETRY_USER)
496
497 Builder* BVH4VirtualSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
498 int minLeafSize = scene->device->object_accel_min_leaf_size;
499 int maxLeafSize = scene->device->object_accel_max_leaf_size;
500 return new BVHNBuilderSAH<4,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,UserGeometry::geom_type);
501 }
502
503 Builder* BVH4VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) {
504 return new BVHNBuilderSAH<4,Object>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,UserGeometry::geom_type);
505 }
506#if defined(__AVX__)
507
508 Builder* BVH8VirtualSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
509 int minLeafSize = scene->device->object_accel_min_leaf_size;
510 int maxLeafSize = scene->device->object_accel_max_leaf_size;
511 return new BVHNBuilderSAH<8,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,UserGeometry::geom_type);
512 }
513
514 Builder* BVH8VirtualMeshBuilderSAH (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) {
515 return new BVHNBuilderSAH<8,Object>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,UserGeometry::geom_type);
516 }
517#endif
518#endif
519
520#if defined(EMBREE_GEOMETRY_INSTANCE)
521 Builder* BVH4InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
522 Builder* BVH4InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) {
523 return new BVHNBuilderSAH<4,InstancePrimitive>((BVH4*)bvh,mesh,geomID,4,1.0f,1,inf,gtype);
524 }
525#if defined(__AVX__)
526 Builder* BVH8InstanceSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
527 Builder* BVH8InstanceMeshBuilderSAH (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) {
528 return new BVHNBuilderSAH<8,InstancePrimitive>((BVH8*)bvh,mesh,geomID,8,1.0f,1,inf,gtype);
529 }
530#endif
531#endif
532
533#if defined(EMBREE_GEOMETRY_GRID)
534 Builder* BVH4GridMeshBuilderSAH (void* bvh, GridMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAHGrid<4>((BVH4*)bvh,mesh,geomID,4,1.0f,4,4,mode); }
535 Builder* BVH4GridSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4,mode); } // FIXME: check whether cost factors are correct
536
537#if defined(__AVX__)
538 Builder* BVH8GridMeshBuilderSAH (void* bvh, GridMesh* mesh, unsigned int geomID, size_t mode) { return new BVHNBuilderSAHGrid<8>((BVH8*)bvh,mesh,geomID,8,1.0f,8,8,mode); }
539 Builder* BVH8GridSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8,mode); } // FIXME: check whether cost factors are correct
540#endif
541#endif
542 }
543}
544