Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/builders/bvh_builder_sah.h
9906 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "heuristic_binning_array_aligned.h"
7
#include "heuristic_spatial_array.h"
8
#include "heuristic_openmerge_array.h"
9
10
#define NUM_OBJECT_BINS 32
11
#define NUM_SPATIAL_BINS 16
12
13
namespace embree
14
{
15
namespace isa
16
{
17
MAYBE_UNUSED static const float travCost = 1.0f;
18
MAYBE_UNUSED static const size_t DEFAULT_SINGLE_THREAD_THRESHOLD = 1024;
19
20
struct GeneralBVHBuilder
21
{
22
static const size_t MAX_BRANCHING_FACTOR = 16; //!< maximum supported BVH branching factor
23
static const size_t MIN_LARGE_LEAF_LEVELS = 8; //!< create balanced tree of we are that many levels before the maximum tree depth
24
25
26
/*! settings for SAH builder */
27
struct Settings
28
{
29
/*! default settings */
30
Settings ()
31
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7),
32
travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf) {}
33
34
/*! initialize settings from API settings */
35
Settings (const RTCBuildArguments& settings)
36
: branchingFactor(2), maxDepth(32), logBlockSize(0), minLeafSize(1), maxLeafSize(7),
37
travCost(1.0f), intCost(1.0f), singleThreadThreshold(1024), primrefarrayalloc(inf)
38
{
39
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxBranchingFactor)) branchingFactor = settings.maxBranchingFactor;
40
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxDepth )) maxDepth = settings.maxDepth;
41
if (RTC_BUILD_ARGUMENTS_HAS(settings,sahBlockSize )) logBlockSize = bsr(settings.sahBlockSize);
42
if (RTC_BUILD_ARGUMENTS_HAS(settings,minLeafSize )) minLeafSize = settings.minLeafSize;
43
if (RTC_BUILD_ARGUMENTS_HAS(settings,maxLeafSize )) maxLeafSize = settings.maxLeafSize;
44
if (RTC_BUILD_ARGUMENTS_HAS(settings,traversalCost )) travCost = settings.traversalCost;
45
if (RTC_BUILD_ARGUMENTS_HAS(settings,intersectionCost )) intCost = settings.intersectionCost;
46
47
minLeafSize = min(minLeafSize,maxLeafSize);
48
}
49
50
Settings (size_t sahBlockSize, size_t minLeafSize, size_t maxLeafSize, float travCost, float intCost, size_t singleThreadThreshold, size_t primrefarrayalloc = inf)
51
: branchingFactor(2), maxDepth(32), logBlockSize(bsr(sahBlockSize)), minLeafSize(min(minLeafSize,maxLeafSize)), maxLeafSize(maxLeafSize),
52
travCost(travCost), intCost(intCost), singleThreadThreshold(singleThreadThreshold), primrefarrayalloc(primrefarrayalloc)
53
{
54
}
55
56
public:
57
size_t branchingFactor; //!< branching factor of BVH to build
58
size_t maxDepth; //!< maximum depth of BVH to build
59
size_t logBlockSize; //!< log2 of blocksize for SAH heuristic
60
size_t minLeafSize; //!< minimum size of a leaf
61
size_t maxLeafSize; //!< maximum size of a leaf
62
float travCost; //!< estimated cost of one traversal step
63
float intCost; //!< estimated cost of one primitive intersection
64
size_t singleThreadThreshold; //!< threshold when we switch to single threaded build
65
size_t primrefarrayalloc; //!< builder uses prim ref array to allocate nodes and leaves when a subtree of that size is finished
66
};
67
68
/*! recursive state of builder */
69
template<typename Set, typename Split>
70
struct BuildRecordT
71
{
72
public:
73
__forceinline BuildRecordT () {}
74
75
__forceinline BuildRecordT (size_t depth)
76
: depth(depth), alloc_barrier(false), prims(empty) {}
77
78
__forceinline BuildRecordT (size_t depth, const Set& prims)
79
: depth(depth), alloc_barrier(false), prims(prims) {}
80
81
__forceinline BBox3fa bounds() const { return prims.geomBounds; }
82
83
__forceinline friend bool operator< (const BuildRecordT& a, const BuildRecordT& b) { return a.prims.size() < b.prims.size(); }
84
__forceinline friend bool operator> (const BuildRecordT& a, const BuildRecordT& b) { return a.prims.size() > b.prims.size(); }
85
86
__forceinline size_t size() const { return prims.size(); }
87
88
public:
89
size_t depth; //!< Depth of the root of this subtree.
90
bool alloc_barrier; //!< barrier used to reuse primref-array blocks to allocate nodes
91
Set prims; //!< The list of primitives.
92
};
93
94
template<typename PrimRef, typename Set>
95
struct DefaultCanCreateLeafFunc
96
{
97
__forceinline bool operator()(const PrimRef*, const Set&) const { return true; }
98
};
99
100
template<typename PrimRef, typename Set>
101
struct DefaultCanCreateLeafSplitFunc
102
{
103
__forceinline void operator()(PrimRef*, const Set&, Set&, Set&) const { }
104
};
105
106
template<typename BuildRecord,
107
typename Heuristic,
108
typename Set,
109
typename PrimRef,
110
typename ReductionTy,
111
typename Allocator,
112
typename CreateAllocFunc,
113
typename CreateNodeFunc,
114
typename UpdateNodeFunc,
115
typename CreateLeafFunc,
116
typename CanCreateLeafFunc,
117
typename CanCreateLeafSplitFunc,
118
typename ProgressMonitor>
119
120
class BuilderT
121
{
122
friend struct GeneralBVHBuilder;
123
124
BuilderT (PrimRef* prims,
125
Heuristic& heuristic,
126
const CreateAllocFunc& createAlloc,
127
const CreateNodeFunc& createNode,
128
const UpdateNodeFunc& updateNode,
129
const CreateLeafFunc& createLeaf,
130
const CanCreateLeafFunc& canCreateLeaf,
131
const CanCreateLeafSplitFunc& canCreateLeafSplit,
132
const ProgressMonitor& progressMonitor,
133
const Settings& settings) :
134
cfg(settings),
135
prims(prims),
136
heuristic(heuristic),
137
createAlloc(createAlloc),
138
createNode(createNode),
139
updateNode(updateNode),
140
createLeaf(createLeaf),
141
canCreateLeaf(canCreateLeaf),
142
canCreateLeafSplit(canCreateLeafSplit),
143
progressMonitor(progressMonitor)
144
{
145
if (cfg.branchingFactor > MAX_BRANCHING_FACTOR)
146
throw_RTCError(RTC_ERROR_UNKNOWN,"bvh_builder: branching factor too large");
147
}
148
149
const ReductionTy createLargeLeaf(const BuildRecord& current, Allocator alloc)
150
{
151
/* this should never occur but is a fatal error */
152
if (current.depth > cfg.maxDepth)
153
throw_RTCError(RTC_ERROR_UNKNOWN,"depth limit reached");
154
155
/* create leaf for few primitives */
156
if (current.prims.size() <= cfg.maxLeafSize && canCreateLeaf(prims,current.prims))
157
return createLeaf(prims,current.prims,alloc);
158
159
/* fill all children by always splitting the largest one */
160
ReductionTy values[MAX_BRANCHING_FACTOR];
161
BuildRecord children[MAX_BRANCHING_FACTOR];
162
size_t numChildren = 1;
163
children[0] = current;
164
do {
165
166
/* find best child with largest bounding box area */
167
size_t bestChild = -1;
168
size_t bestSize = 0;
169
for (size_t i=0; i<numChildren; i++)
170
{
171
/* ignore leaves as they cannot get split */
172
if (children[i].prims.size() <= cfg.maxLeafSize && canCreateLeaf(prims,children[i].prims))
173
continue;
174
175
/* remember child with largest size */
176
if (children[i].prims.size() > bestSize) {
177
bestSize = children[i].prims.size();
178
bestChild = i;
179
}
180
}
181
if (bestChild == (size_t)-1) break;
182
183
/*! split best child into left and right child */
184
BuildRecord left(current.depth+1);
185
BuildRecord right(current.depth+1);
186
if (!canCreateLeaf(prims,children[bestChild].prims)) {
187
canCreateLeafSplit(prims,children[bestChild].prims,left.prims,right.prims);
188
} else {
189
heuristic.splitFallback(children[bestChild].prims,left.prims,right.prims);
190
}
191
192
/* add new children left and right */
193
children[bestChild] = children[numChildren-1];
194
children[numChildren-1] = left;
195
children[numChildren+0] = right;
196
numChildren++;
197
198
} while (numChildren < cfg.branchingFactor);
199
200
/* set barrier for primrefarrayalloc */
201
if (unlikely(current.size() > cfg.primrefarrayalloc))
202
for (size_t i=0; i<numChildren; i++)
203
children[i].alloc_barrier = children[i].size() <= cfg.primrefarrayalloc;
204
205
/* create node */
206
auto node = createNode(children,numChildren,alloc);
207
208
/* recurse into each child and perform reduction */
209
for (size_t i=0; i<numChildren; i++)
210
values[i] = createLargeLeaf(children[i],alloc);
211
212
/* perform reduction */
213
return updateNode(current,children,node,values,numChildren);
214
}
215
216
const ReductionTy recurse(BuildRecord& current, Allocator alloc, bool toplevel)
217
{
218
/* get thread local allocator */
219
if (!alloc)
220
alloc = createAlloc();
221
222
/* call memory monitor function to signal progress */
223
if (toplevel && current.size() <= cfg.singleThreadThreshold)
224
progressMonitor(current.size());
225
226
/*! find best split */
227
auto split = heuristic.find(current.prims,cfg.logBlockSize);
228
229
/*! compute leaf and split cost */
230
const float leafSAH = cfg.intCost*current.prims.leafSAH(cfg.logBlockSize);
231
const float splitSAH = cfg.travCost*halfArea(current.prims.geomBounds)+cfg.intCost*split.splitSAH();
232
assert((current.prims.size() == 0) || ((leafSAH >= 0) && (splitSAH >= 0)));
233
234
/*! create a leaf node when threshold reached or SAH tells us to stop */
235
if (current.prims.size() <= cfg.minLeafSize || current.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth || (current.prims.size() <= cfg.maxLeafSize && leafSAH <= splitSAH)) {
236
heuristic.deterministic_order(current.prims);
237
return createLargeLeaf(current,alloc);
238
}
239
240
/*! perform initial split */
241
Set lprims,rprims;
242
heuristic.split(split,current.prims,lprims,rprims);
243
244
/*! initialize child list with initial split */
245
ReductionTy values[MAX_BRANCHING_FACTOR];
246
BuildRecord children[MAX_BRANCHING_FACTOR];
247
children[0] = BuildRecord(current.depth+1,lprims);
248
children[1] = BuildRecord(current.depth+1,rprims);
249
size_t numChildren = 2;
250
251
/*! split until node is full or SAH tells us to stop */
252
while (numChildren < cfg.branchingFactor)
253
{
254
/*! find best child to split */
255
float bestArea = neg_inf;
256
ssize_t bestChild = -1;
257
for (size_t i=0; i<numChildren; i++)
258
{
259
/* ignore leaves as they cannot get split */
260
if (children[i].prims.size() <= cfg.minLeafSize) continue;
261
262
/* find child with largest surface area */
263
if (halfArea(children[i].prims.geomBounds) > bestArea) {
264
bestChild = i;
265
bestArea = halfArea(children[i].prims.geomBounds);
266
}
267
}
268
if (bestChild == -1) break;
269
270
/* perform best found split */
271
BuildRecord& brecord = children[bestChild];
272
BuildRecord lrecord(current.depth+1);
273
BuildRecord rrecord(current.depth+1);
274
auto split = heuristic.find(brecord.prims,cfg.logBlockSize);
275
heuristic.split(split,brecord.prims,lrecord.prims,rrecord.prims);
276
children[bestChild ] = lrecord;
277
children[numChildren] = rrecord;
278
numChildren++;
279
}
280
281
/* set barrier for primrefarrayalloc */
282
if (unlikely(current.size() > cfg.primrefarrayalloc))
283
for (size_t i=0; i<numChildren; i++)
284
children[i].alloc_barrier = children[i].size() <= cfg.primrefarrayalloc;
285
286
/* sort buildrecords for faster shadow ray traversal */
287
std::sort(&children[0],&children[numChildren],std::greater<BuildRecord>());
288
289
/*! create an inner node */
290
auto node = createNode(children,numChildren,alloc);
291
292
/* spawn tasks */
293
if (current.size() > cfg.singleThreadThreshold)
294
{
295
/*! parallel_for is faster than spawning sub-tasks */
296
parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) { // FIXME: no range here
297
for (size_t i=r.begin(); i<r.end(); i++) {
298
values[i] = recurse(children[i],nullptr,true);
299
_mm_mfence(); // to allow non-temporal stores during build
300
}
301
});
302
303
return updateNode(current,children,node,values,numChildren);
304
}
305
/* recurse into each child */
306
else
307
{
308
for (size_t i=0; i<numChildren; i++)
309
values[i] = recurse(children[i],alloc,false);
310
311
return updateNode(current,children,node,values,numChildren);
312
}
313
}
314
315
private:
316
Settings cfg;
317
PrimRef* prims;
318
Heuristic& heuristic;
319
const CreateAllocFunc& createAlloc;
320
const CreateNodeFunc& createNode;
321
const UpdateNodeFunc& updateNode;
322
const CreateLeafFunc& createLeaf;
323
const CanCreateLeafFunc& canCreateLeaf;
324
const CanCreateLeafSplitFunc& canCreateLeafSplit;
325
const ProgressMonitor& progressMonitor;
326
};
327
328
template<
329
typename ReductionTy,
330
typename Heuristic,
331
typename Set,
332
typename PrimRef,
333
typename CreateAllocFunc,
334
typename CreateNodeFunc,
335
typename UpdateNodeFunc,
336
typename CreateLeafFunc,
337
typename ProgressMonitor>
338
339
__noinline static ReductionTy build(Heuristic& heuristic,
340
PrimRef* prims,
341
const Set& set,
342
CreateAllocFunc createAlloc,
343
CreateNodeFunc createNode, UpdateNodeFunc updateNode,
344
const CreateLeafFunc& createLeaf,
345
const ProgressMonitor& progressMonitor,
346
const Settings& settings)
347
{
348
typedef BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
349
350
typedef BuilderT<
351
BuildRecord,
352
Heuristic,
353
Set,
354
PrimRef,
355
ReductionTy,
356
decltype(createAlloc()),
357
CreateAllocFunc,
358
CreateNodeFunc,
359
UpdateNodeFunc,
360
CreateLeafFunc,
361
DefaultCanCreateLeafFunc<PrimRef, Set>,
362
DefaultCanCreateLeafSplitFunc<PrimRef, Set>,
363
ProgressMonitor> Builder;
364
365
/* instantiate builder */
366
Builder builder(prims,
367
heuristic,
368
createAlloc,
369
createNode,
370
updateNode,
371
createLeaf,
372
DefaultCanCreateLeafFunc<PrimRef, Set>(),
373
DefaultCanCreateLeafSplitFunc<PrimRef, Set>(),
374
progressMonitor,
375
settings);
376
377
/* build hierarchy */
378
BuildRecord record(1,set);
379
const ReductionTy root = builder.recurse(record,nullptr,true);
380
_mm_mfence(); // to allow non-temporal stores during build
381
return root;
382
}
383
384
template<
385
typename ReductionTy,
386
typename Heuristic,
387
typename Set,
388
typename PrimRef,
389
typename CreateAllocFunc,
390
typename CreateNodeFunc,
391
typename UpdateNodeFunc,
392
typename CreateLeafFunc,
393
typename CanCreateLeafFunc,
394
typename CanCreateLeafSplitFunc,
395
typename ProgressMonitor>
396
397
__noinline static ReductionTy build(Heuristic& heuristic,
398
PrimRef* prims,
399
const Set& set,
400
CreateAllocFunc createAlloc,
401
CreateNodeFunc createNode, UpdateNodeFunc updateNode,
402
const CreateLeafFunc& createLeaf,
403
const CanCreateLeafFunc& canCreateLeaf,
404
const CanCreateLeafSplitFunc& canCreateLeafSplit,
405
const ProgressMonitor& progressMonitor,
406
const Settings& settings)
407
{
408
typedef BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
409
410
typedef BuilderT<
411
BuildRecord,
412
Heuristic,
413
Set,
414
PrimRef,
415
ReductionTy,
416
decltype(createAlloc()),
417
CreateAllocFunc,
418
CreateNodeFunc,
419
UpdateNodeFunc,
420
CreateLeafFunc,
421
CanCreateLeafFunc,
422
CanCreateLeafSplitFunc,
423
ProgressMonitor> Builder;
424
425
/* instantiate builder */
426
Builder builder(prims,
427
heuristic,
428
createAlloc,
429
createNode,
430
updateNode,
431
createLeaf,
432
canCreateLeaf,
433
canCreateLeafSplit,
434
progressMonitor,
435
settings);
436
437
/* build hierarchy */
438
BuildRecord record(1,set);
439
const ReductionTy root = builder.recurse(record,nullptr,true);
440
_mm_mfence(); // to allow non-temporal stores during build
441
return root;
442
}
443
};
444
445
/* SAH builder that operates on an array of BuildRecords */
446
struct BVHBuilderBinnedSAH
447
{
448
typedef PrimInfoRange Set;
449
typedef HeuristicArrayBinningSAH<PrimRef,NUM_OBJECT_BINS> Heuristic;
450
typedef GeneralBVHBuilder::BuildRecordT<Set,typename Heuristic::Split> BuildRecord;
451
typedef GeneralBVHBuilder::Settings Settings;
452
453
/*! special builder that propagates reduction over the tree */
454
template<
455
typename ReductionTy,
456
typename CreateAllocFunc,
457
typename CreateNodeFunc,
458
typename UpdateNodeFunc,
459
typename CreateLeafFunc,
460
typename ProgressMonitor>
461
462
static ReductionTy build(CreateAllocFunc createAlloc,
463
CreateNodeFunc createNode, UpdateNodeFunc updateNode,
464
const CreateLeafFunc& createLeaf,
465
const ProgressMonitor& progressMonitor,
466
PrimRef* prims, const PrimInfo& pinfo,
467
const Settings& settings)
468
{
469
Heuristic heuristic(prims);
470
return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
471
heuristic,
472
prims,
473
PrimInfoRange(0,pinfo.size(),pinfo),
474
createAlloc,
475
createNode,
476
updateNode,
477
createLeaf,
478
progressMonitor,
479
settings);
480
}
481
482
/*! special builder that propagates reduction over the tree */
483
template<
484
typename ReductionTy,
485
typename CreateAllocFunc,
486
typename CreateNodeFunc,
487
typename UpdateNodeFunc,
488
typename CreateLeafFunc,
489
typename CanCreateLeafFunc,
490
typename CanCreateLeafSplitFunc,
491
typename ProgressMonitor>
492
493
static ReductionTy build(CreateAllocFunc createAlloc,
494
CreateNodeFunc createNode, UpdateNodeFunc updateNode,
495
const CreateLeafFunc& createLeaf,
496
const CanCreateLeafFunc& canCreateLeaf,
497
const CanCreateLeafSplitFunc& canCreateLeafSplit,
498
const ProgressMonitor& progressMonitor,
499
PrimRef* prims, const PrimInfo& pinfo,
500
const Settings& settings)
501
{
502
Heuristic heuristic(prims);
503
return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
504
heuristic,
505
prims,
506
PrimInfoRange(0,pinfo.size(),pinfo),
507
createAlloc,
508
createNode,
509
updateNode,
510
createLeaf,
511
canCreateLeaf,
512
canCreateLeafSplit,
513
progressMonitor,
514
settings);
515
}
516
};
517
518
/* Spatial SAH builder that operates on an double-buffered array of BuildRecords */
519
struct BVHBuilderBinnedFastSpatialSAH
520
{
521
typedef PrimInfoExtRange Set;
522
typedef Split2<BinSplit<NUM_OBJECT_BINS>,SpatialBinSplit<NUM_SPATIAL_BINS> > Split;
523
typedef GeneralBVHBuilder::BuildRecordT<Set,Split> BuildRecord;
524
typedef GeneralBVHBuilder::Settings Settings;
525
526
static const unsigned int GEOMID_MASK = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS;
527
static const unsigned int SPLITS_MASK = 0xFFFFFFFF << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
528
529
template<typename ReductionTy, typename UserCreateLeaf>
530
struct CreateLeafExt
531
{
532
__forceinline CreateLeafExt (const UserCreateLeaf userCreateLeaf)
533
: userCreateLeaf(userCreateLeaf) {}
534
535
// __noinline is workaround for ICC2016 compiler bug
536
template<typename Allocator>
537
__noinline ReductionTy operator() (PrimRef* prims, const range<size_t>& range, Allocator alloc) const
538
{
539
for (size_t i=range.begin(); i<range.end(); i++)
540
prims[i].lower.u &= GEOMID_MASK;
541
542
return userCreateLeaf(prims,range,alloc);
543
}
544
545
const UserCreateLeaf userCreateLeaf;
546
};
547
548
/*! special builder that propagates reduction over the tree */
549
template<
550
typename ReductionTy,
551
typename CreateAllocFunc,
552
typename CreateNodeFunc,
553
typename UpdateNodeFunc,
554
typename CreateLeafFunc,
555
typename SplitPrimitiveFunc,
556
typename ProgressMonitor>
557
558
static ReductionTy build(CreateAllocFunc createAlloc,
559
CreateNodeFunc createNode,
560
UpdateNodeFunc updateNode,
561
const CreateLeafFunc& createLeaf,
562
SplitPrimitiveFunc splitPrimitive,
563
ProgressMonitor progressMonitor,
564
PrimRef* prims,
565
const size_t extSize,
566
const PrimInfo& pinfo,
567
const Settings& settings)
568
{
569
typedef HeuristicArraySpatialSAH<SplitPrimitiveFunc,PrimRef,NUM_OBJECT_BINS,NUM_SPATIAL_BINS> Heuristic;
570
Heuristic heuristic(splitPrimitive,prims,pinfo);
571
572
/* calculate total surface area */ // FIXME: this sum is not deterministic
573
const float A = (float) parallel_reduce(size_t(0),pinfo.size(),0.0, [&] (const range<size_t>& r) -> double {
574
575
double A = 0.0f;
576
for (size_t i=r.begin(); i<r.end(); i++)
577
{
578
PrimRef& prim = prims[i];
579
A += area(prim.bounds());
580
}
581
return A;
582
},std::plus<double>());
583
584
585
/* calculate maximum number of spatial splits per primitive */
586
const unsigned int maxSplits = ((size_t)1 << RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS)-1;
587
const float f = 10.0f;
588
589
const float invA = 1.0f / A;
590
parallel_for( size_t(0), pinfo.size(), [&](const range<size_t>& r) {
591
592
for (size_t i=r.begin(); i<r.end(); i++)
593
{
594
PrimRef& prim = prims[i];
595
assert((prim.geomID() & SPLITS_MASK) == 0);
596
// FIXME: is there a better general heuristic ?
597
const float nf = ceilf(f*pinfo.size()*area(prim.bounds()) * invA);
598
unsigned int n = 4+min((int)maxSplits-4, max(1, (int)(nf)));
599
prim.lower.u |= n << (32-RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS);
600
}
601
});
602
603
return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,PrimRef>(
604
heuristic,
605
prims,
606
PrimInfoExtRange(0,pinfo.size(),extSize,pinfo),
607
createAlloc,
608
createNode,
609
updateNode,
610
CreateLeafExt<ReductionTy,CreateLeafFunc>(createLeaf),
611
progressMonitor,
612
settings);
613
}
614
};
615
616
/* Open/Merge SAH builder that operates on an array of BuildRecords */
617
struct BVHBuilderBinnedOpenMergeSAH
618
{
619
static const size_t NUM_OBJECT_BINS_HQ = 32;
620
typedef PrimInfoExtRange Set;
621
typedef BinSplit<NUM_OBJECT_BINS_HQ> Split;
622
typedef GeneralBVHBuilder::BuildRecordT<Set,Split> BuildRecord;
623
typedef GeneralBVHBuilder::Settings Settings;
624
625
/*! special builder that propagates reduction over the tree */
626
template<
627
typename ReductionTy,
628
typename BuildRef,
629
typename CreateAllocFunc,
630
typename CreateNodeFunc,
631
typename UpdateNodeFunc,
632
typename CreateLeafFunc,
633
typename NodeOpenerFunc,
634
typename ProgressMonitor>
635
636
static ReductionTy build(CreateAllocFunc createAlloc,
637
CreateNodeFunc createNode,
638
UpdateNodeFunc updateNode,
639
const CreateLeafFunc& createLeaf,
640
NodeOpenerFunc nodeOpenerFunc,
641
ProgressMonitor progressMonitor,
642
BuildRef* prims,
643
const size_t extSize,
644
const PrimInfo& pinfo,
645
const Settings& settings)
646
{
647
typedef HeuristicArrayOpenMergeSAH<NodeOpenerFunc,BuildRef,NUM_OBJECT_BINS_HQ> Heuristic;
648
Heuristic heuristic(nodeOpenerFunc,prims,settings.branchingFactor);
649
650
return GeneralBVHBuilder::build<ReductionTy,Heuristic,Set,BuildRef>(
651
heuristic,
652
prims,
653
PrimInfoExtRange(0,pinfo.size(),extSize,pinfo),
654
createAlloc,
655
createNode,
656
updateNode,
657
createLeaf,
658
progressMonitor,
659
settings);
660
}
661
};
662
}
663
}
664
665