Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/builders/heuristic_binning.h
9913 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "priminfo.h"
7
#include "priminfo_mb.h"
8
#include "../../common/algorithms/parallel_reduce.h"
9
#include "../../common/algorithms/parallel_partition.h"
10
11
namespace embree
12
{
13
namespace isa
14
{
15
/*! mapping into bins */
16
template<size_t BINS>
17
struct BinMapping
18
{
19
public:
20
__forceinline BinMapping() {}
21
22
/*! calculates the mapping */
23
__forceinline BinMapping(size_t N, const BBox3fa& centBounds)
24
{
25
num = min(BINS,size_t(4.0f + 0.05f*N));
26
assert(num >= 1);
27
const vfloat4 eps = 1E-34f;
28
const vfloat4 diag = max(eps, (vfloat4) centBounds.size());
29
scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
30
ofs = (vfloat4) centBounds.lower;
31
}
32
33
/*! calculates the mapping */
34
__forceinline BinMapping(const BBox3fa& centBounds)
35
{
36
num = BINS;
37
const vfloat4 eps = 1E-34f;
38
const vfloat4 diag = max(eps, (vfloat4) centBounds.size());
39
scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
40
ofs = (vfloat4) centBounds.lower;
41
}
42
43
/*! calculates the mapping */
44
template<typename PrimInfo>
45
__forceinline BinMapping(const PrimInfo& pinfo)
46
{
47
const vfloat4 eps = 1E-34f;
48
num = min(BINS,size_t(4.0f + 0.05f*pinfo.size()));
49
const vfloat4 diag = max(eps,(vfloat4) pinfo.centBounds.size());
50
scale = select(diag > eps,vfloat4(0.99f*num)/diag,vfloat4(0.0f));
51
ofs = (vfloat4) pinfo.centBounds.lower;
52
}
53
54
/*! returns number of bins */
55
__forceinline size_t size() const { return num; }
56
57
/*! slower but safe binning */
58
__forceinline Vec3ia bin(const Vec3fa& p) const
59
{
60
const vint4 i = floori((vfloat4(p)-ofs)*scale);
61
assert(i[0] >= 0 && (size_t)i[0] < num);
62
assert(i[1] >= 0 && (size_t)i[1] < num);
63
assert(i[2] >= 0 && (size_t)i[2] < num);
64
65
// we clamp to handle corner cases that could calculate out of bounds bin
66
return Vec3ia(clamp(i,vint4(0),vint4(num-1)));
67
}
68
69
/*! faster but unsafe binning */
70
__forceinline Vec3ia bin_unsafe(const Vec3fa& p) const {
71
return Vec3ia(floori((vfloat4(p)-ofs)*scale));
72
}
73
74
/*! faster but unsafe binning */
75
template<typename PrimRef>
76
__forceinline Vec3ia bin_unsafe(const PrimRef& p) const {
77
return bin_unsafe(p.binCenter());
78
}
79
80
/*! faster but unsafe binning */
81
template<typename PrimRef, typename BinBoundsAndCenter>
82
__forceinline Vec3ia bin_unsafe(const PrimRef& p, const BinBoundsAndCenter& binBoundsAndCenter) const {
83
return bin_unsafe(binBoundsAndCenter.binCenter(p));
84
}
85
86
template<typename PrimRef>
87
__forceinline bool bin_unsafe(const PrimRef& ref,
88
const vint4& vSplitPos,
89
const vbool4& splitDimMask) const // FIXME: rename to isLeft
90
{
91
return any(((vint4)bin_unsafe(center2(ref.bounds())) < vSplitPos) & splitDimMask);
92
}
93
/*! calculates left spatial position of bin */
94
__forceinline float pos(const size_t bin, const size_t dim) const {
95
return madd(float(bin),1.0f / scale[dim],ofs[dim]);
96
}
97
98
/*! returns true if the mapping is invalid in some dimension */
99
__forceinline bool invalid(const size_t dim) const {
100
return scale[dim] == 0.0f;
101
}
102
103
/*! stream output */
104
friend embree_ostream operator<<(embree_ostream cout, const BinMapping& mapping) {
105
return cout << "BinMapping { num = " << mapping.num << ", ofs = " << mapping.ofs << ", scale = " << mapping.scale << "}";
106
}
107
108
public:
109
size_t num;
110
vfloat4 ofs,scale; //!< linear function that maps to bin ID
111
};
112
113
/*! stores all information to perform some split */
114
template<size_t BINS>
115
struct BinSplit
116
{
117
enum
118
{
119
SPLIT_OBJECT = 0,
120
SPLIT_FALLBACK = 1,
121
SPLIT_ENFORCE = 2, // splits with larger ID are enforced in createLargeLeaf even if we could create a leaf already
122
SPLIT_TEMPORAL = 2,
123
SPLIT_GEOMID = 3,
124
};
125
126
/*! construct an invalid split by default */
127
__forceinline BinSplit()
128
: sah(inf), dim(-1), pos(0), data(0) {}
129
130
__forceinline BinSplit(float sah, unsigned data, int dim = 0, float fpos = 0)
131
: sah(sah), dim(dim), fpos(fpos), data(data) {}
132
133
/*! constructs specified split */
134
__forceinline BinSplit(float sah, int dim, int pos, const BinMapping<BINS>& mapping)
135
: sah(sah), dim(dim), pos(pos), data(0), mapping(mapping) {}
136
137
/*! tests if this split is valid */
138
__forceinline bool valid() const { return dim != -1; }
139
140
/*! calculates surface area heuristic for performing the split */
141
__forceinline float splitSAH() const { return sah; }
142
143
/*! stream output */
144
friend embree_ostream operator<<(embree_ostream cout, const BinSplit& split) {
145
return cout << "BinSplit { sah = " << split.sah << ", dim = " << split.dim << ", pos = " << split.pos << "}";
146
}
147
148
public:
149
float sah; //!< SAH cost of the split
150
int dim; //!< split dimension
151
union { int pos; float fpos; }; //!< bin index for splitting
152
unsigned int data; //!< extra optional split data
153
BinMapping<BINS> mapping; //!< mapping into bins
154
};
155
156
/*! stores extended information about the split */
157
template<typename BBox>
158
struct SplitInfoT
159
{
160
161
__forceinline SplitInfoT () {}
162
163
__forceinline SplitInfoT (size_t leftCount, const BBox& leftBounds, size_t rightCount, const BBox& rightBounds)
164
: leftCount(leftCount), rightCount(rightCount), leftBounds(leftBounds), rightBounds(rightBounds) {}
165
166
public:
167
size_t leftCount,rightCount;
168
BBox leftBounds,rightBounds;
169
};
170
171
typedef SplitInfoT<BBox3fa> SplitInfo;
172
typedef SplitInfoT<LBBox3fa> SplitInfo2;
173
174
/*! stores all binning information */
175
template<size_t BINS, typename PrimRef, typename BBox>
176
struct __aligned(64) BinInfoT
177
{
178
typedef BinSplit<BINS> Split;
179
typedef vbool4 vbool;
180
typedef vint4 vint;
181
typedef vfloat4 vfloat;
182
183
__forceinline BinInfoT() {
184
}
185
186
__forceinline BinInfoT(EmptyTy) {
187
clear();
188
}
189
190
/*! bin access function */
191
__forceinline BBox &bounds(const size_t binID, const size_t dimID) { return _bounds[binID][dimID]; }
192
__forceinline const BBox &bounds(const size_t binID, const size_t dimID) const { return _bounds[binID][dimID]; }
193
194
__forceinline unsigned int &counts(const size_t binID, const size_t dimID) { return _counts[binID][dimID]; }
195
__forceinline const unsigned int &counts(const size_t binID, const size_t dimID) const { return _counts[binID][dimID]; }
196
197
__forceinline vuint4 &counts(const size_t binID) { return _counts[binID]; }
198
__forceinline const vuint4 &counts(const size_t binID) const { return _counts[binID]; }
199
200
/*! clears the bin info */
201
__forceinline void clear()
202
{
203
for (size_t i=0; i<BINS; i++) {
204
bounds(i,0) = bounds(i,1) = bounds(i,2) = empty;
205
counts(i) = vuint4(zero);
206
}
207
}
208
209
/*! bins an array of primitives */
210
__forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<BINS>& mapping)
211
{
212
if (unlikely(N == 0)) return;
213
size_t i;
214
for (i=0; i<N-1; i+=2)
215
{
216
/*! map even and odd primitive to bin */
217
BBox prim0; Vec3fa center0;
218
prims[i+0].binBoundsAndCenter(prim0,center0);
219
const vint4 bin0 = (vint4)mapping.bin(center0);
220
221
BBox prim1; Vec3fa center1;
222
prims[i+1].binBoundsAndCenter(prim1,center1);
223
const vint4 bin1 = (vint4)mapping.bin(center1);
224
225
/*! increase bounds for bins for even primitive */
226
const unsigned int b00 = extract<0>(bin0); bounds(b00,0).extend(prim0);
227
const unsigned int b01 = extract<1>(bin0); bounds(b01,1).extend(prim0);
228
const unsigned int b02 = extract<2>(bin0); bounds(b02,2).extend(prim0);
229
const unsigned int s0 = (unsigned int)prims[i+0].size();
230
counts(b00,0)+=s0;
231
counts(b01,1)+=s0;
232
counts(b02,2)+=s0;
233
234
/*! increase bounds of bins for odd primitive */
235
const unsigned int b10 = extract<0>(bin1); bounds(b10,0).extend(prim1);
236
const unsigned int b11 = extract<1>(bin1); bounds(b11,1).extend(prim1);
237
const unsigned int b12 = extract<2>(bin1); bounds(b12,2).extend(prim1);
238
const unsigned int s1 = (unsigned int)prims[i+1].size();
239
counts(b10,0)+=s1;
240
counts(b11,1)+=s1;
241
counts(b12,2)+=s1;
242
}
243
/*! for uneven number of primitives */
244
if (i < N)
245
{
246
/*! map primitive to bin */
247
BBox prim0; Vec3fa center0;
248
prims[i].binBoundsAndCenter(prim0,center0);
249
const vint4 bin0 = (vint4)mapping.bin(center0);
250
251
/*! increase bounds of bins */
252
const unsigned int s0 = (unsigned int)prims[i].size();
253
const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
254
const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
255
const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
256
}
257
}
258
259
/*! bins an array of primitives */
260
template<typename BinBoundsAndCenter>
261
__forceinline void bin (const PrimRef* prims, size_t N, const BinMapping<BINS>& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
262
{
263
if (N == 0) return;
264
265
size_t i;
266
for (i=0; i<N-1; i+=2)
267
{
268
/*! map even and odd primitive to bin */
269
BBox prim0; Vec3fa center0; binBoundsAndCenter.binBoundsAndCenter(prims[i+0],prim0,center0);
270
const vint4 bin0 = (vint4)mapping.bin(center0);
271
BBox prim1; Vec3fa center1; binBoundsAndCenter.binBoundsAndCenter(prims[i+1],prim1,center1);
272
const vint4 bin1 = (vint4)mapping.bin(center1);
273
274
/*! increase bounds for bins for even primitive */
275
const unsigned int s0 = prims[i+0].size();
276
const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
277
const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
278
const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
279
280
/*! increase bounds of bins for odd primitive */
281
const unsigned int s1 = prims[i+1].size();
282
const int b10 = extract<0>(bin1); counts(b10,0)+=s1; bounds(b10,0).extend(prim1);
283
const int b11 = extract<1>(bin1); counts(b11,1)+=s1; bounds(b11,1).extend(prim1);
284
const int b12 = extract<2>(bin1); counts(b12,2)+=s1; bounds(b12,2).extend(prim1);
285
}
286
287
/*! for uneven number of primitives */
288
if (i < N)
289
{
290
/*! map primitive to bin */
291
BBox prim0; Vec3fa center0; binBoundsAndCenter.binBoundsAndCenter(prims[i+0],prim0,center0);
292
const vint4 bin0 = (vint4)mapping.bin(center0);
293
294
/*! increase bounds of bins */
295
const unsigned int s0 = prims[i+0].size();
296
const int b00 = extract<0>(bin0); counts(b00,0)+=s0; bounds(b00,0).extend(prim0);
297
const int b01 = extract<1>(bin0); counts(b01,1)+=s0; bounds(b01,1).extend(prim0);
298
const int b02 = extract<2>(bin0); counts(b02,2)+=s0; bounds(b02,2).extend(prim0);
299
}
300
}
301
302
__forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<BINS>& mapping) {
303
bin(prims+begin,end-begin,mapping);
304
}
305
306
template<typename BinBoundsAndCenter>
307
__forceinline void bin(const PrimRef* prims, size_t begin, size_t end, const BinMapping<BINS>& mapping, const BinBoundsAndCenter& binBoundsAndCenter) {
308
bin<BinBoundsAndCenter>(prims+begin,end-begin,mapping,binBoundsAndCenter);
309
}
310
311
/*! merges in other binning information */
312
__forceinline void merge (const BinInfoT& other, size_t numBins)
313
{
314
315
for (size_t i=0; i<numBins; i++)
316
{
317
counts(i) += other.counts(i);
318
bounds(i,0).extend(other.bounds(i,0));
319
bounds(i,1).extend(other.bounds(i,1));
320
bounds(i,2).extend(other.bounds(i,2));
321
}
322
}
323
324
/*! reduces binning information */
325
static __forceinline const BinInfoT reduce (const BinInfoT& a, const BinInfoT& b, const size_t numBins = BINS)
326
{
327
BinInfoT c;
328
for (size_t i=0; i<numBins; i++)
329
{
330
c.counts(i) = a.counts(i)+b.counts(i);
331
c.bounds(i,0) = embree::merge(a.bounds(i,0),b.bounds(i,0));
332
c.bounds(i,1) = embree::merge(a.bounds(i,1),b.bounds(i,1));
333
c.bounds(i,2) = embree::merge(a.bounds(i,2),b.bounds(i,2));
334
}
335
return c;
336
}
337
338
/*! finds the best split by scanning binning information */
339
__forceinline Split best(const BinMapping<BINS>& mapping, const size_t blocks_shift) const
340
{
341
/* sweep from right to left and compute parallel prefix of merged bounds */
342
vfloat4 rAreas[BINS];
343
vuint4 rCounts[BINS];
344
vuint4 count = 0; BBox bx = empty; BBox by = empty; BBox bz = empty;
345
for (size_t i=mapping.size()-1; i>0; i--)
346
{
347
count += counts(i);
348
rCounts[i] = count;
349
bx.extend(bounds(i,0)); rAreas[i][0] = expectedApproxHalfArea(bx);
350
by.extend(bounds(i,1)); rAreas[i][1] = expectedApproxHalfArea(by);
351
bz.extend(bounds(i,2)); rAreas[i][2] = expectedApproxHalfArea(bz);
352
rAreas[i][3] = 0.0f;
353
}
354
/* sweep from left to right and compute SAH */
355
vuint4 blocks_add = (1 << blocks_shift)-1;
356
vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0;
357
count = 0; bx = empty; by = empty; bz = empty;
358
for (size_t i=1; i<mapping.size(); i++, ii+=1)
359
{
360
count += counts(i-1);
361
bx.extend(bounds(i-1,0)); float Ax = expectedApproxHalfArea(bx);
362
by.extend(bounds(i-1,1)); float Ay = expectedApproxHalfArea(by);
363
bz.extend(bounds(i-1,2)); float Az = expectedApproxHalfArea(bz);
364
const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
365
const vfloat4 rArea = rAreas[i];
366
const vuint4 lCount = (count +blocks_add) >> (unsigned int)(blocks_shift); // if blocks_shift >=1 then lCount < 4B and could be represented with an vint4, which would allow for faster vfloat4 conversions.
367
const vuint4 rCount = (rCounts[i]+blocks_add) >> (unsigned int)(blocks_shift);
368
const vfloat4 sah = madd(lArea,vfloat4(lCount),rArea*vfloat4(rCount));
369
//const vfloat4 sah = madd(lArea,vfloat4(vint4(lCount)),rArea*vfloat4(vint4(rCount)));
370
371
vbestPos = select(sah < vbestSAH,ii ,vbestPos);
372
vbestSAH = select(sah < vbestSAH,sah,vbestSAH);
373
}
374
375
/* find best dimension */
376
float bestSAH = inf;
377
int bestDim = -1;
378
int bestPos = 0;
379
for (int dim=0; dim<3; dim++)
380
{
381
/* ignore zero sized dimensions */
382
if (unlikely(mapping.invalid(dim)))
383
continue;
384
385
/* test if this is a better dimension */
386
if (vbestSAH[dim] < bestSAH && vbestPos[dim] != 0) {
387
bestDim = dim;
388
bestPos = vbestPos[dim];
389
bestSAH = vbestSAH[dim];
390
}
391
}
392
return Split(bestSAH,bestDim,bestPos,mapping);
393
}
394
395
/*! finds the best split by scanning binning information */
396
__forceinline Split best_block_size(const BinMapping<BINS>& mapping, const size_t blockSize) const
397
{
398
/* sweep from right to left and compute parallel prefix of merged bounds */
399
vfloat4 rAreas[BINS];
400
vuint4 rCounts[BINS];
401
vuint4 count = 0; BBox bx = empty; BBox by = empty; BBox bz = empty;
402
for (size_t i=mapping.size()-1; i>0; i--)
403
{
404
count += counts(i);
405
rCounts[i] = count;
406
bx.extend(bounds(i,0)); rAreas[i][0] = expectedApproxHalfArea(bx);
407
by.extend(bounds(i,1)); rAreas[i][1] = expectedApproxHalfArea(by);
408
bz.extend(bounds(i,2)); rAreas[i][2] = expectedApproxHalfArea(bz);
409
rAreas[i][3] = 0.0f;
410
}
411
/* sweep from left to right and compute SAH */
412
vuint4 blocks_add = blockSize-1;
413
vfloat4 blocks_factor = 1.0f/float(blockSize);
414
vuint4 ii = 1; vfloat4 vbestSAH = pos_inf; vuint4 vbestPos = 0;
415
count = 0; bx = empty; by = empty; bz = empty;
416
for (size_t i=1; i<mapping.size(); i++, ii+=1)
417
{
418
count += counts(i-1);
419
bx.extend(bounds(i-1,0)); float Ax = expectedApproxHalfArea(bx);
420
by.extend(bounds(i-1,1)); float Ay = expectedApproxHalfArea(by);
421
bz.extend(bounds(i-1,2)); float Az = expectedApproxHalfArea(bz);
422
const vfloat4 lArea = vfloat4(Ax,Ay,Az,Az);
423
const vfloat4 rArea = rAreas[i];
424
const vfloat4 lCount = floor(vfloat4(count +blocks_add)*blocks_factor);
425
const vfloat4 rCount = floor(vfloat4(rCounts[i]+blocks_add)*blocks_factor);
426
const vfloat4 sah = madd(lArea,lCount,rArea*rCount);
427
428
vbestPos = select(sah < vbestSAH,ii ,vbestPos);
429
vbestSAH = select(sah < vbestSAH,sah,vbestSAH);
430
}
431
432
/* find best dimension */
433
float bestSAH = inf;
434
int bestDim = -1;
435
int bestPos = 0;
436
for (int dim=0; dim<3; dim++)
437
{
438
/* ignore zero sized dimensions */
439
if (unlikely(mapping.invalid(dim)))
440
continue;
441
442
/* test if this is a better dimension */
443
if (vbestSAH[dim] < bestSAH && vbestPos[dim] != 0) {
444
bestDim = dim;
445
bestPos = vbestPos[dim];
446
bestSAH = vbestSAH[dim];
447
}
448
}
449
return Split(bestSAH,bestDim,bestPos,mapping);
450
}
451
452
/*! calculates extended split information */
453
__forceinline void getSplitInfo(const BinMapping<BINS>& mapping, const Split& split, SplitInfoT<BBox>& info) const
454
{
455
if (split.dim == -1) {
456
new (&info) SplitInfoT<BBox>(0,empty,0,empty);
457
return;
458
}
459
460
size_t leftCount = 0;
461
BBox leftBounds = empty;
462
for (size_t i=0; i<(size_t)split.pos; i++) {
463
leftCount += counts(i,split.dim);
464
leftBounds.extend(bounds(i,split.dim));
465
}
466
size_t rightCount = 0;
467
BBox rightBounds = empty;
468
for (size_t i=split.pos; i<mapping.size(); i++) {
469
rightCount += counts(i,split.dim);
470
rightBounds.extend(bounds(i,split.dim));
471
}
472
new (&info) SplitInfoT<BBox>(leftCount,leftBounds,rightCount,rightBounds);
473
}
474
475
/*! gets the number of primitives left of the split */
476
__forceinline size_t getLeftCount(const BinMapping<BINS>& mapping, const Split& split) const
477
{
478
if (unlikely(split.dim == -1)) return -1;
479
480
size_t leftCount = 0;
481
for (size_t i = 0; i < (size_t)split.pos; i++) {
482
leftCount += counts(i, split.dim);
483
}
484
return leftCount;
485
}
486
487
/*! gets the number of primitives right of the split */
488
__forceinline size_t getRightCount(const BinMapping<BINS>& mapping, const Split& split) const
489
{
490
if (unlikely(split.dim == -1)) return -1;
491
492
size_t rightCount = 0;
493
for (size_t i = (size_t)split.pos; i<mapping.size(); i++) {
494
rightCount += counts(i, split.dim);
495
}
496
return rightCount;
497
}
498
499
private:
500
BBox _bounds[BINS][3]; //!< geometry bounds for each bin in each dimension
501
vuint4 _counts[BINS]; //!< counts number of primitives that map into the bins
502
};
503
}
504
505
template<typename BinInfoT, typename BinMapping, typename PrimRef>
506
__forceinline void bin_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, const BinMapping& mapping)
507
{
508
if (likely(end-begin < parallelThreshold)) {
509
binner.bin(prims,begin,end,mapping);
510
} else {
511
binner = parallel_reduce(begin,end,blockSize,binner,
512
[&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping); return binner; },
513
[&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
514
}
515
}
516
517
template<typename BinBoundsAndCenter, typename BinInfoT, typename BinMapping, typename PrimRef>
518
__forceinline void bin_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, size_t parallelThreshold, const BinMapping& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
519
{
520
if (likely(end-begin < parallelThreshold)) {
521
binner.bin(prims,begin,end,mapping,binBoundsAndCenter);
522
} else {
523
binner = parallel_reduce(begin,end,blockSize,binner,
524
[&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping, binBoundsAndCenter); return binner; },
525
[&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
526
}
527
}
528
529
template<bool parallel, typename BinInfoT, typename BinMapping, typename PrimRef>
530
__forceinline void bin_serial_or_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, const BinMapping& mapping)
531
{
532
if (!parallel) {
533
binner.bin(prims,begin,end,mapping);
534
} else {
535
binner = parallel_reduce(begin,end,blockSize,binner,
536
[&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping); return binner; },
537
[&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
538
}
539
}
540
541
template<bool parallel, typename BinBoundsAndCenter, typename BinInfoT, typename BinMapping, typename PrimRef>
542
__forceinline void bin_serial_or_parallel(BinInfoT& binner, const PrimRef* prims, size_t begin, size_t end, size_t blockSize, const BinMapping& mapping, const BinBoundsAndCenter& binBoundsAndCenter)
543
{
544
if (!parallel) {
545
binner.bin(prims,begin,end,mapping,binBoundsAndCenter);
546
} else {
547
binner = parallel_reduce(begin,end,blockSize,binner,
548
[&](const range<size_t>& r) -> BinInfoT { BinInfoT binner(empty); binner.bin(prims + r.begin(), r.size(), mapping, binBoundsAndCenter); return binner; },
549
[&](const BinInfoT& b0, const BinInfoT& b1) -> BinInfoT { BinInfoT r = b0; r.merge(b1, mapping.size()); return r; });
550
}
551
}
552
}
553
554