Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/bvh/bvh_builder_sah_mb.cpp
9906 views
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/bvh_builder_msmblur.h"
7
8
#include "../builders/primrefgen.h"
9
#include "../builders/splitter.h"
10
11
#include "../geometry/linei.h"
12
#include "../geometry/triangle.h"
13
#include "../geometry/trianglev.h"
14
#include "../geometry/trianglev_mb.h"
15
#include "../geometry/trianglei.h"
16
#include "../geometry/quadv.h"
17
#include "../geometry/quadi.h"
18
#include "../geometry/object.h"
19
#include "../geometry/instance.h"
20
#include "../geometry/instance_array.h"
21
#include "../geometry/subgrid.h"
22
23
#include "../common/state.h"
24
25
// FIXME: remove after removing BVHNBuilderMBlurRootTimeSplitsSAH
26
#include "../../common/algorithms/parallel_for_for.h"
27
#include "../../common/algorithms/parallel_for_for_prefix_sum.h"
28
29
30
namespace embree
31
{
32
namespace isa
33
{
34
35
#if 0
36
template<int N, typename Primitive>
37
struct CreateMBlurLeaf
38
{
39
typedef BVHN<N> BVH;
40
typedef typename BVH::NodeRef NodeRef;
41
typedef typename BVH::NodeRecordMB NodeRecordMB;
42
43
__forceinline CreateMBlurLeaf (BVH* bvh, PrimRef* prims, size_t time) : bvh(bvh), prims(prims), time(time) {}
44
45
__forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
46
{
47
size_t items = Primitive::blocks(set.size());
48
size_t start = set.begin();
49
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
50
Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteAlignment);
51
NodeRef node = bvh->encodeLeaf((char*)accel,items);
52
53
LBBox3fa allBounds = empty;
54
for (size_t i=0; i<items; i++)
55
allBounds.extend(accel[i].fillMB(prims, start, set.end(), bvh->scene, time));
56
57
return NodeRecordMB(node,allBounds);
58
}
59
60
BVH* bvh;
61
PrimRef* prims;
62
size_t time;
63
};
64
#endif
65
66
template<int N, typename Mesh, typename Primitive>
67
struct CreateMSMBlurLeaf
68
{
69
typedef BVHN<N> BVH;
70
typedef typename BVH::NodeRef NodeRef;
71
typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
72
73
__forceinline CreateMSMBlurLeaf (BVH* bvh) : bvh(bvh) {}
74
75
__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
76
{
77
size_t items = Primitive::blocks(current.prims.size());
78
size_t start = current.prims.begin();
79
size_t end = current.prims.end();
80
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
81
Primitive* accel = (Primitive*) alloc.malloc1(items*sizeof(Primitive),BVH::byteNodeAlignment);
82
NodeRef node = bvh->encodeLeaf((char*)accel,items);
83
LBBox3fa allBounds = empty;
84
for (size_t i=0; i<items; i++)
85
allBounds.extend(accel[i].fillMB(current.prims.prims->data(), start, current.prims.end(), bvh->scene, current.prims.time_range));
86
return NodeRecordMB4D(node,allBounds,current.prims.time_range);
87
}
88
89
BVH* bvh;
90
};
91
92
/* Motion blur BVH with 4D nodes and internal time splits */
93
template<int N, typename Mesh, typename Primitive>
94
struct BVHNBuilderMBlurSAH : public Builder
95
{
96
typedef BVHN<N> BVH;
97
typedef typename BVHN<N>::NodeRef NodeRef;
98
typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
99
typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
100
101
BVH* bvh;
102
Scene* scene;
103
const size_t sahBlockSize;
104
const float intCost;
105
const size_t minLeafSize;
106
const size_t maxLeafSize;
107
const Geometry::GTypeMask gtype_;
108
109
BVHNBuilderMBlurSAH (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize, const Geometry::GTypeMask gtype)
110
: bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks)), gtype_(gtype) {}
111
112
void build()
113
{
114
/* skip build for empty scene */
115
const size_t numPrimitives = scene->getNumPrimitives(gtype_,true);
116
if (numPrimitives == 0) { bvh->clear(); return; }
117
118
double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAH");
119
120
#if PROFILE
121
profile(2,PROFILE_RUNS,numPrimitives,[&] (ProfileTimer& timer) {
122
#endif
123
124
//const size_t numTimeSteps = scene->getNumTimeSteps<typename Mesh::type_t,true>();
125
//const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
126
127
/*if (numTimeSegments == 1)
128
buildSingleSegment(numPrimitives);
129
else*/
130
buildMultiSegment(numPrimitives);
131
132
#if PROFILE
133
});
134
#endif
135
136
/* clear temporary data for static geometry */
137
bvh->cleanup();
138
bvh->postBuild(t0);
139
}
140
141
#if 0 // No longer compatible when time_ranges are present for geometries. Would have to create temporal nodes sometimes, and put only a single geometry into leaf.
142
void buildSingleSegment(size_t numPrimitives)
143
{
144
/* create primref array */
145
mvector<PrimRef> prims(scene->device,numPrimitives);
146
const PrimInfo pinfo = createPrimRefArrayMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface,0);
147
/* early out if no valid primitives */
148
if (pinfo.size() == 0) { bvh->clear(); return; }
149
/* estimate acceleration structure size */
150
const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
151
const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive));
152
bvh->alloc.init_estimate(node_bytes+leaf_bytes);
153
154
/* settings for BVH build */
155
GeneralBVHBuilder::Settings settings;
156
settings.branchingFactor = N;
157
settings.maxDepth = BVH::maxBuildDepthLeaf;
158
settings.logBlockSize = bsr(sahBlockSize);
159
settings.minLeafSize = min(minLeafSize,maxLeafSize);
160
settings.maxLeafSize = maxLeafSize;
161
settings.travCost = travCost;
162
settings.intCost = intCost;
163
settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
164
165
/* build hierarchy */
166
auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
167
(typename BVH::CreateAlloc(bvh),typename BVH::AABBNodeMB::Create(),typename BVH::AABBNodeMB::Set(),
168
CreateMBlurLeaf<N,Primitive>(bvh,prims.data(),0),bvh->scene->progressInterface,
169
prims.data(),pinfo,settings);
170
171
bvh->set(root.ref,root.lbounds,pinfo.size());
172
}
173
#endif
174
175
void buildMultiSegment(size_t numPrimitives)
176
{
177
/* create primref array */
178
mvector<PrimRefMB> prims(scene->device,numPrimitives);
179
PrimInfoMB pinfo = createPrimRefArrayMSMBlur(scene,gtype_,numPrimitives,prims,bvh->scene->progressInterface);
180
181
/* early out if no valid primitives */
182
if (pinfo.size() == 0) { bvh->clear(); return; }
183
184
/* estimate acceleration structure size */
185
const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
186
const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(Primitive));
187
bvh->alloc.init_estimate(node_bytes+leaf_bytes);
188
189
/* settings for BVH build */
190
BVHBuilderMSMBlur::Settings settings;
191
settings.branchingFactor = N;
192
settings.maxDepth = BVH::maxDepth;
193
settings.logBlockSize = bsr(sahBlockSize);
194
settings.minLeafSize = min(minLeafSize,maxLeafSize);
195
settings.maxLeafSize = maxLeafSize;
196
settings.travCost = travCost;
197
settings.intCost = intCost;
198
settings.singleLeafTimeSegment = Primitive::singleTimeSegment;
199
settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
200
201
/* build hierarchy */
202
auto root =
203
BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
204
RecalculatePrimRef<Mesh>(scene),
205
typename BVH::CreateAlloc(bvh),
206
typename BVH::AABBNodeMB4D::Create(),
207
typename BVH::AABBNodeMB4D::Set(),
208
CreateMSMBlurLeaf<N,Mesh,Primitive>(bvh),
209
bvh->scene->progressInterface,
210
settings);
211
212
bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
213
}
214
215
void clear() {
216
}
217
};
218
219
/************************************************************************************/
220
/************************************************************************************/
221
/************************************************************************************/
222
/************************************************************************************/
223
224
struct GridRecalculatePrimRef
225
{
226
Scene* scene;
227
const SubGridBuildData * const sgrids;
228
229
__forceinline GridRecalculatePrimRef (Scene* scene, const SubGridBuildData * const sgrids)
230
: scene(scene), sgrids(sgrids) {}
231
232
__forceinline PrimRefMB operator() (const PrimRefMB& prim, const BBox1f time_range) const
233
{
234
const unsigned int geomID = prim.geomID();
235
const GridMesh* mesh = scene->get<GridMesh>(geomID);
236
const unsigned int buildID = prim.primID();
237
const SubGridBuildData &subgrid = sgrids[buildID];
238
const unsigned int primID = subgrid.primID;
239
const size_t x = subgrid.x();
240
const size_t y = subgrid.y();
241
const LBBox3fa lbounds = mesh->linearBounds(mesh->grid(primID),x,y,time_range);
242
const unsigned num_time_segments = mesh->numTimeSegments();
243
const range<int> tbounds = mesh->timeSegmentRange(time_range);
244
return PrimRefMB (lbounds, tbounds.size(), mesh->time_range, num_time_segments, geomID, buildID);
245
}
246
247
__forceinline LBBox3fa linearBounds(const PrimRefMB& prim, const BBox1f time_range) const {
248
const unsigned int geomID = prim.geomID();
249
const GridMesh* mesh = scene->get<GridMesh>(geomID);
250
const unsigned int buildID = prim.primID();
251
const SubGridBuildData &subgrid = sgrids[buildID];
252
const unsigned int primID = subgrid.primID;
253
const size_t x = subgrid.x();
254
const size_t y = subgrid.y();
255
return mesh->linearBounds(mesh->grid(primID),x,y,time_range);
256
}
257
258
};
259
260
template<int N>
261
struct CreateMSMBlurLeafGrid
262
{
263
typedef BVHN<N> BVH;
264
typedef typename BVH::NodeRef NodeRef;
265
typedef typename BVH::NodeRecordMB4D NodeRecordMB4D;
266
267
__forceinline CreateMSMBlurLeafGrid (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids) : scene(scene), bvh(bvh), sgrids(sgrids) {}
268
269
__forceinline const NodeRecordMB4D operator() (const BVHBuilderMSMBlur::BuildRecord& current, const FastAllocator::CachedAllocator& alloc) const
270
{
271
const size_t items = current.prims.size();
272
const size_t start = current.prims.begin();
273
274
const PrimRefMB* prims = current.prims.prims->data();
275
/* collect all subsets with unique geomIDs */
276
assert(items <= N);
277
unsigned int geomIDs[N];
278
unsigned int num_geomIDs = 1;
279
geomIDs[0] = prims[start].geomID();
280
281
for (size_t i=1;i<items;i++)
282
{
283
bool found = false;
284
const unsigned int new_geomID = prims[start+i].geomID();
285
for (size_t j=0;j<num_geomIDs;j++)
286
if (new_geomID == geomIDs[j])
287
{ found = true; break; }
288
if (!found)
289
geomIDs[num_geomIDs++] = new_geomID;
290
}
291
292
/* allocate all leaf memory in one single block */
293
SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
294
typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
295
296
LBBox3fa allBounds = empty;
297
298
for (size_t g=0;g<num_geomIDs;g++)
299
{
300
const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
301
unsigned int x[N];
302
unsigned int y[N];
303
unsigned int primID[N];
304
BBox3fa bounds0[N];
305
BBox3fa bounds1[N];
306
unsigned int pos = 0;
307
for (size_t i=0;i<items;i++)
308
{
309
if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
310
311
const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
312
x[pos] = sgrid_bd.sx;
313
y[pos] = sgrid_bd.sy;
314
primID[pos] = sgrid_bd.primID;
315
const size_t x = sgrid_bd.x();
316
const size_t y = sgrid_bd.y();
317
LBBox3fa newBounds = mesh->linearBounds(mesh->grid(sgrid_bd.primID),x,y,current.prims.time_range);
318
allBounds.extend(newBounds);
319
bounds0[pos] = newBounds.bounds0;
320
bounds1[pos] = newBounds.bounds1;
321
pos++;
322
}
323
assert(pos <= N);
324
new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],current.prims.time_range.lower,1.0f/current.prims.time_range.size(),pos);
325
}
326
return NodeRecordMB4D(node,allBounds,current.prims.time_range);
327
}
328
329
Scene *scene;
330
BVH* bvh;
331
const SubGridBuildData * const sgrids;
332
};
333
334
#if 0
335
template<int N>
336
struct CreateLeafGridMB
337
{
338
typedef BVHN<N> BVH;
339
typedef typename BVH::NodeRef NodeRef;
340
typedef typename BVH::NodeRecordMB NodeRecordMB;
341
342
__forceinline CreateLeafGridMB (Scene* scene, BVH* bvh, const SubGridBuildData * const sgrids)
343
: scene(scene), bvh(bvh), sgrids(sgrids) {}
344
345
__forceinline NodeRecordMB operator() (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) const
346
{
347
const size_t items = set.size();
348
const size_t start = set.begin();
349
350
/* collect all subsets with unique geomIDs */
351
assert(items <= N);
352
unsigned int geomIDs[N];
353
unsigned int num_geomIDs = 1;
354
geomIDs[0] = prims[start].geomID();
355
356
for (size_t i=1;i<items;i++)
357
{
358
bool found = false;
359
const unsigned int new_geomID = prims[start+i].geomID();
360
for (size_t j=0;j<num_geomIDs;j++)
361
if (new_geomID == geomIDs[j])
362
{ found = true; break; }
363
if (!found)
364
geomIDs[num_geomIDs++] = new_geomID;
365
}
366
367
/* allocate all leaf memory in one single block */
368
SubGridMBQBVHN<N>* accel = (SubGridMBQBVHN<N>*) alloc.malloc1(num_geomIDs*sizeof(SubGridMBQBVHN<N>),BVH::byteAlignment);
369
typename BVH::NodeRef node = bvh->encodeLeaf((char*)accel,num_geomIDs);
370
371
LBBox3fa allBounds = empty;
372
373
for (size_t g=0;g<num_geomIDs;g++)
374
{
375
const GridMesh* __restrict__ const mesh = scene->get<GridMesh>(geomIDs[g]);
376
377
unsigned int x[N];
378
unsigned int y[N];
379
unsigned int primID[N];
380
BBox3fa bounds0[N];
381
BBox3fa bounds1[N];
382
unsigned int pos = 0;
383
for (size_t i=0;i<items;i++)
384
{
385
if (unlikely(prims[start+i].geomID() != geomIDs[g])) continue;
386
387
const SubGridBuildData &sgrid_bd = sgrids[prims[start+i].primID()];
388
x[pos] = sgrid_bd.sx;
389
y[pos] = sgrid_bd.sy;
390
primID[pos] = sgrid_bd.primID;
391
const size_t x = sgrid_bd.x();
392
const size_t y = sgrid_bd.y();
393
bool MAYBE_UNUSED valid0 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,0,bounds0[pos]);
394
bool MAYBE_UNUSED valid1 = mesh->buildBounds(mesh->grid(sgrid_bd.primID),x,y,1,bounds1[pos]);
395
assert(valid0);
396
assert(valid1);
397
allBounds.extend(LBBox3fa(bounds0[pos],bounds1[pos]));
398
pos++;
399
}
400
new (&accel[g]) SubGridMBQBVHN<N>(x,y,primID,bounds0,bounds1,geomIDs[g],0.0f,1.0f,pos);
401
}
402
return NodeRecordMB(node,allBounds);
403
}
404
405
Scene *scene;
406
BVH* bvh;
407
const SubGridBuildData * const sgrids;
408
};
409
#endif
410
411
412
/* Motion blur BVH with 4D nodes and internal time splits */
413
template<int N>
414
struct BVHNBuilderMBlurSAHGrid : public Builder
415
{
416
typedef BVHN<N> BVH;
417
typedef typename BVHN<N>::NodeRef NodeRef;
418
typedef typename BVHN<N>::NodeRecordMB NodeRecordMB;
419
typedef typename BVHN<N>::AABBNodeMB AABBNodeMB;
420
421
BVH* bvh;
422
Scene* scene;
423
const size_t sahBlockSize;
424
const float intCost;
425
const size_t minLeafSize;
426
const size_t maxLeafSize;
427
mvector<SubGridBuildData> sgrids;
428
429
430
BVHNBuilderMBlurSAHGrid (BVH* bvh, Scene* scene, const size_t sahBlockSize, const float intCost, const size_t minLeafSize, const size_t maxLeafSize)
431
: bvh(bvh), scene(scene), sahBlockSize(sahBlockSize), intCost(intCost), minLeafSize(minLeafSize), maxLeafSize(min(maxLeafSize,BVH::maxLeafBlocks)), sgrids(scene->device,0) {}
432
433
434
PrimInfo createPrimRefArrayMBlurGrid(Scene* scene, mvector<PrimRef>& prims, BuildProgressMonitor& progressMonitor, size_t itime)
435
{
436
/* first run to get #primitives */
437
ParallelForForPrefixSumState<PrimInfo> pstate;
438
Scene::Iterator<GridMesh,true> iter(scene);
439
440
pstate.init(iter,size_t(1024));
441
442
/* iterate over all meshes in the scene */
443
PrimInfo pinfo = parallel_for_for_prefix_sum0( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID) -> PrimInfo {
444
445
PrimInfo pinfo(empty);
446
for (size_t j=r.begin(); j<r.end(); j++)
447
{
448
if (!mesh->valid(j,range<size_t>(0,1))) continue;
449
BBox3fa bounds = empty;
450
const PrimRef prim(bounds,unsigned(geomID),unsigned(j));
451
pinfo.add_center2(prim,mesh->getNumSubGrids(j));
452
}
453
return pinfo;
454
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
455
456
size_t numPrimitives = pinfo.size();
457
if (numPrimitives == 0) return pinfo;
458
459
/* resize arrays */
460
sgrids.resize(numPrimitives);
461
prims.resize(numPrimitives);
462
463
/* second run to fill primrefs and SubGridBuildData arrays */
464
pinfo = parallel_for_for_prefix_sum1( pstate, iter, PrimInfo(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfo& base) -> PrimInfo {
465
466
k = base.size();
467
size_t p_index = k;
468
PrimInfo pinfo(empty);
469
for (size_t j=r.begin(); j<r.end(); j++)
470
{
471
const GridMesh::Grid &g = mesh->grid(j);
472
if (!mesh->valid(j,range<size_t>(0,1))) continue;
473
474
for (unsigned int y=0; y<g.resY-1u; y+=2)
475
for (unsigned int x=0; x<g.resX-1u; x+=2)
476
{
477
BBox3fa bounds = empty;
478
if (!mesh->buildBounds(g,x,y,itime,bounds)) continue; // get bounds of subgrid
479
const PrimRef prim(bounds,unsigned(geomID),unsigned(p_index));
480
pinfo.add_center2(prim);
481
sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
482
prims[p_index++] = prim;
483
}
484
}
485
return pinfo;
486
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
487
488
assert(pinfo.size() == numPrimitives);
489
return pinfo;
490
}
491
492
PrimInfoMB createPrimRefArrayMSMBlurGrid(Scene* scene, mvector<PrimRefMB>& prims, BuildProgressMonitor& progressMonitor, BBox1f t0t1 = BBox1f(0.0f,1.0f))
493
{
494
/* first run to get #primitives */
495
ParallelForForPrefixSumState<PrimInfoMB> pstate;
496
Scene::Iterator<GridMesh,true> iter(scene);
497
498
pstate.init(iter,size_t(1024));
499
/* iterate over all meshes in the scene */
500
PrimInfoMB pinfoMB = parallel_for_for_prefix_sum0( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t /*geomID*/) -> PrimInfoMB {
501
502
PrimInfoMB pinfoMB(empty);
503
for (size_t j=r.begin(); j<r.end(); j++)
504
{
505
if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
506
LBBox3fa bounds(empty);
507
PrimInfoMB gridMB(0,mesh->getNumSubGrids(j));
508
pinfoMB.merge(gridMB);
509
}
510
return pinfoMB;
511
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
512
513
size_t numPrimitives = pinfoMB.size();
514
if (numPrimitives == 0) return pinfoMB;
515
516
/* resize arrays */
517
sgrids.resize(numPrimitives);
518
prims.resize(numPrimitives);
519
/* second run to fill primrefs and SubGridBuildData arrays */
520
pinfoMB = parallel_for_for_prefix_sum1( pstate, iter, PrimInfoMB(empty), [&](GridMesh* mesh, const range<size_t>& r, size_t k, size_t geomID, const PrimInfoMB& base) -> PrimInfoMB {
521
522
k = base.size();
523
size_t p_index = k;
524
PrimInfoMB pinfoMB(empty);
525
for (size_t j=r.begin(); j<r.end(); j++)
526
{
527
if (!mesh->valid(j, mesh->timeSegmentRange(t0t1))) continue;
528
const GridMesh::Grid &g = mesh->grid(j);
529
530
for (unsigned int y=0; y<g.resY-1u; y+=2)
531
for (unsigned int x=0; x<g.resX-1u; x+=2)
532
{
533
const PrimRefMB prim(mesh->linearBounds(g,x,y,t0t1),mesh->numTimeSegments(),mesh->time_range,mesh->numTimeSegments(),unsigned(geomID),unsigned(p_index));
534
pinfoMB.add_primref(prim);
535
sgrids[p_index] = SubGridBuildData(x | g.get3x3FlagsX(x), y | g.get3x3FlagsY(y), unsigned(j));
536
prims[p_index++] = prim;
537
}
538
}
539
return pinfoMB;
540
}, [](const PrimInfoMB& a, const PrimInfoMB& b) -> PrimInfoMB { return PrimInfoMB::merge2(a,b); });
541
542
assert(pinfoMB.size() == numPrimitives);
543
pinfoMB.time_range = t0t1;
544
return pinfoMB;
545
}
546
547
void build()
548
{
549
/* skip build for empty scene */
550
const size_t numPrimitives = scene->getNumPrimitives(GridMesh::geom_type,true);
551
if (numPrimitives == 0) { bvh->clear(); return; }
552
553
double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderMBlurSAHGrid");
554
555
//const size_t numTimeSteps = scene->getNumTimeSteps<GridMesh,true>();
556
//const size_t numTimeSegments = numTimeSteps-1; assert(numTimeSteps > 1);
557
//if (numTimeSegments == 1)
558
// buildSingleSegment(numPrimitives);
559
//else
560
buildMultiSegment(numPrimitives);
561
562
/* clear temporary data for static geometry */
563
bvh->cleanup();
564
bvh->postBuild(t0);
565
}
566
567
#if 0
568
void buildSingleSegment(size_t numPrimitives)
569
{
570
/* create primref array */
571
mvector<PrimRef> prims(scene->device,numPrimitives);
572
const PrimInfo pinfo = createPrimRefArrayMBlurGrid(scene,prims,bvh->scene->progressInterface,0);
573
/* early out if no valid primitives */
574
if (pinfo.size() == 0) { bvh->clear(); return; }
575
576
/* estimate acceleration structure size */
577
const size_t node_bytes = pinfo.size()*sizeof(AABBNodeMB)/(4*N);
578
//TODO: check leaf_bytes
579
const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
580
bvh->alloc.init_estimate(node_bytes+leaf_bytes);
581
582
/* settings for BVH build */
583
GeneralBVHBuilder::Settings settings;
584
settings.branchingFactor = N;
585
settings.maxDepth = BVH::maxBuildDepthLeaf;
586
settings.logBlockSize = bsr(sahBlockSize);
587
settings.minLeafSize = min(minLeafSize,maxLeafSize);
588
settings.maxLeafSize = maxLeafSize;
589
settings.travCost = travCost;
590
settings.intCost = intCost;
591
settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
592
593
/* build hierarchy */
594
auto root = BVHBuilderBinnedSAH::build<NodeRecordMB>
595
(typename BVH::CreateAlloc(bvh),
596
typename BVH::AABBNodeMB::Create(),
597
typename BVH::AABBNodeMB::Set(),
598
CreateLeafGridMB<N>(scene,bvh,sgrids.data()),
599
bvh->scene->progressInterface,
600
prims.data(),pinfo,settings);
601
602
bvh->set(root.ref,root.lbounds,pinfo.size());
603
}
604
#endif
605
606
void buildMultiSegment(size_t numPrimitives)
607
{
608
/* create primref array */
609
mvector<PrimRefMB> prims(scene->device,numPrimitives);
610
PrimInfoMB pinfo = createPrimRefArrayMSMBlurGrid(scene,prims,bvh->scene->progressInterface);
611
612
/* early out if no valid primitives */
613
if (pinfo.size() == 0) { bvh->clear(); return; }
614
615
616
617
GridRecalculatePrimRef recalculatePrimRef(scene,sgrids.data());
618
619
/* estimate acceleration structure size */
620
const size_t node_bytes = pinfo.num_time_segments*sizeof(AABBNodeMB)/(4*N);
621
//FIXME: check leaf_bytes
622
//const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.num_time_segments)*sizeof(SubGridQBVHN<N>));
623
const size_t leaf_bytes = size_t(1.2*(float)numPrimitives/N * sizeof(SubGridQBVHN<N>));
624
625
bvh->alloc.init_estimate(node_bytes+leaf_bytes);
626
627
/* settings for BVH build */
628
BVHBuilderMSMBlur::Settings settings;
629
settings.branchingFactor = N;
630
settings.maxDepth = BVH::maxDepth;
631
settings.logBlockSize = bsr(sahBlockSize);
632
settings.minLeafSize = min(minLeafSize,maxLeafSize);
633
settings.maxLeafSize = maxLeafSize;
634
settings.travCost = travCost;
635
settings.intCost = intCost;
636
settings.singleLeafTimeSegment = false;
637
settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes);
638
639
/* build hierarchy */
640
auto root =
641
BVHBuilderMSMBlur::build<NodeRef>(prims,pinfo,scene->device,
642
recalculatePrimRef,
643
typename BVH::CreateAlloc(bvh),
644
typename BVH::AABBNodeMB4D::Create(),
645
typename BVH::AABBNodeMB4D::Set(),
646
CreateMSMBlurLeafGrid<N>(scene,bvh,sgrids.data()),
647
bvh->scene->progressInterface,
648
settings);
649
bvh->set(root.ref,root.lbounds,pinfo.num_time_segments);
650
}
651
652
void clear() {
653
}
654
};
655
656
/************************************************************************************/
657
/************************************************************************************/
658
/************************************************************************************/
659
/************************************************************************************/
660
661
#if defined(EMBREE_GEOMETRY_TRIANGLE)
662
Builder* BVH4Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
663
Builder* BVH4Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,TriangleMesh,Triangle4vMB>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
664
#if defined(__AVX__)
665
Builder* BVH8Triangle4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
666
Builder* BVH8Triangle4vMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,TriangleMesh,Triangle4vMB>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_TRIANGLE_MESH); }
667
#endif
668
#endif
669
670
#if defined(EMBREE_GEOMETRY_QUAD)
671
Builder* BVH4Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<4,QuadMesh,Quad4i>((BVH4*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
672
#if defined(__AVX__)
673
Builder* BVH8Quad4iMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAH<8,QuadMesh,Quad4i>((BVH8*)bvh,scene,4,1.0f,4,inf,Geometry::MTY_QUAD_MESH); }
674
#endif
675
#endif
676
677
#if defined(EMBREE_GEOMETRY_USER)
678
Builder* BVH4VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
679
int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
680
int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
681
return new BVHNBuilderMBlurSAH<4,UserGeometry,Object>((BVH4*)bvh,scene,4,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
682
}
683
#if defined(__AVX__)
684
Builder* BVH8VirtualMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) {
685
int minLeafSize = scene->device->object_accel_mb_min_leaf_size;
686
int maxLeafSize = scene->device->object_accel_mb_max_leaf_size;
687
return new BVHNBuilderMBlurSAH<8,UserGeometry,Object>((BVH8*)bvh,scene,8,1.0f,minLeafSize,maxLeafSize,Geometry::MTY_USER_GEOMETRY);
688
}
689
#endif
690
#endif
691
692
#if defined(EMBREE_GEOMETRY_INSTANCE)
693
Builder* BVH4InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,Instance,InstancePrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
694
#if defined(__AVX__)
695
Builder* BVH8InstanceMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,Instance,InstancePrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
696
#endif
697
#endif
698
699
#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)
700
Builder* BVH4InstanceArrayMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<4,InstanceArray,InstanceArrayPrimitive>((BVH4*)bvh,scene,4,1.0f,1,1,gtype); }
701
#if defined(__AVX__)
702
Builder* BVH8InstanceArrayMBSceneBuilderSAH (void* bvh, Scene* scene, Geometry::GTypeMask gtype) { return new BVHNBuilderMBlurSAH<8,InstanceArray,InstanceArrayPrimitive>((BVH8*)bvh,scene,8,1.0f,1,1,gtype); }
703
#endif
704
#endif
705
706
#if defined(EMBREE_GEOMETRY_GRID)
707
Builder* BVH4GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<4>((BVH4*)bvh,scene,4,1.0f,4,4); }
708
#if defined(__AVX__)
709
Builder* BVH8GridMBSceneBuilderSAH (void* bvh, Scene* scene, size_t mode) { return new BVHNBuilderMBlurSAHGrid<8>((BVH8*)bvh,scene,8,1.0f,8,8); }
710
#endif
711
#endif
712
}
713
}
714
715