42 #ifndef OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
45 #include <boost/shared_ptr.hpp>
46 #include <boost/bind.hpp>
47 #include <boost/function.hpp>
48 #include <tbb/blocked_range.h>
49 #include <tbb/parallel_for.h>
50 #include <openvdb/Types.h>
63 static const bool IsConstTree =
false;
66 template<
typename TreeT>
struct TreeTraits<const TreeT> {
67 static const bool IsConstTree =
true;
77 template<
typename ManagerT>
80 typedef typename ManagerT::RangeType
RangeT;
81 typedef typename ManagerT::LeafType
LeafT;
82 typedef typename ManagerT::BufferType
BufT;
85 LeafT** leafs,
BufT* bufs,
size_t bufsPerLeaf)
87 for (
size_t n = r.begin(), m = r.end(), N = bufsPerLeaf; n != m; ++n) {
88 leafs[n]->swap(bufs[n * N + auxBufferIdx]);
108 template<
typename TreeT>
130 assert(this->isValid());
142 return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
145 size_t pos()
const {
return mPos; }
146 bool isValid()
const {
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
148 bool test()
const {
return mPos < mRange.mEnd; }
150 operator bool()
const {
return this->test(); }
152 bool empty()
const {
return !this->test(); }
157 return (mPos != other.mPos) || (&mRange != &other.mRange);
168 mEnd(end), mBegin(begin), mGrainSize(grainSize), mLeafManager(leafManager) {}
174 size_t size()
const {
return mEnd - mBegin; }
180 bool empty()
const {
return !(mBegin < mEnd);}
185 mEnd(r.mEnd), mBegin(doSplit(r)), mGrainSize(r.mGrainSize),
186 mLeafManager(r.mLeafManager) {}
189 size_t mEnd, mBegin, mGrainSize;
195 size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
207 mAuxBuffersPerLeaf(auxBuffersPerLeaf),
213 this->rebuild(serial);
221 mLeafCount(other.mLeafCount),
222 mAuxBufferCount(other.mAuxBufferCount),
223 mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf),
224 mLeafs(other.mLeafs),
225 mAuxBuffers(other.mAuxBuffers),
235 delete [] mAuxBuffers;
246 this->initLeafArray();
247 this->initAuxBuffers(serial);
250 void rebuild(
size_t auxBuffersPerLeaf,
bool serial=
false)
253 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
254 this->rebuild(serial);
259 this->rebuild(serial);
264 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
265 this->rebuild(serial);
268 void rebuildAuxBuffers(
size_t auxBuffersPerLeaf,
bool serial=
false)
274 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
275 this->initAuxBuffers(serial);
283 this->removeAuxBuffers();
284 this->initLeafArray();
305 LeafType&
leaf(
size_t leafIdx)
const { assert(leafIdx<mLeafCount);
return *mLeafs[leafIdx]; }
319 assert(leafIdx < mLeafCount);
320 assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
321 return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
322 : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
334 return LeafRange(0, mLeafCount, *
this, grainsize);
348 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree())
return false;
349 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, bufferIdx - 1);
350 this->cook(serial ? 0 : 512);
357 bool swapBuffer(
size_t bufferIdx1,
size_t bufferIdx2,
bool serial =
false)
359 const size_t b1 =
std::min(bufferIdx1, bufferIdx2);
360 const size_t b2 =
std::max(bufferIdx1, bufferIdx2);
361 if (b1 == b2 || b2 > mAuxBuffersPerLeaf)
return false;
363 if (this->isConstTree())
return false;
364 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, b2-1);
366 mTask = boost::bind(&LeafManager::doSwapAuxBuffer, _1, _2, b1-1, b2-1);
368 this->cook(serial ? 0 : 512);
382 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf)
return false;
383 mTask = boost::bind(&LeafManager::doSyncAuxBuffer, _1, _2, bufferIdx - 1);
384 this->cook(serial ? 0 : 64);
393 switch (mAuxBuffersPerLeaf) {
394 case 0:
return false;
395 case 1: mTask = boost::bind(&LeafManager::doSyncAllBuffers1, _1, _2);
break;
396 case 2: mTask = boost::bind(&LeafManager::doSyncAllBuffers2, _1, _2);
break;
397 default: mTask = boost::bind(&LeafManager::doSyncAllBuffersN, _1, _2);
break;
399 this->cook(serial ? 0 : 64);
460 template<
typename LeafOp>
461 void foreach(
const LeafOp& op,
bool threaded =
true)
463 LeafTransformer<LeafOp> transform(*
this, op);
464 transform.run(threaded);
473 if (mTask) mTask(const_cast<LeafManager*>(
this), r);
482 const size_t leafCount = mTree->leafCount();
483 if (leafCount != mLeafCount) {
485 mLeafs = (leafCount == 0) ? NULL :
new LeafType*[leafCount];
486 mLeafCount = leafCount;
488 LeafIterType iter = mTree->beginLeaf();
489 for (
size_t n = 0; n != leafCount; ++n, ++iter) mLeafs[n] = iter.getLeaf();
492 void initAuxBuffers(
bool serial)
494 const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
495 if (auxBufferCount != mAuxBufferCount) {
496 delete [] mAuxBuffers;
497 mAuxBuffers = (auxBufferCount == 0) ? NULL :
new NonConstBufferType[auxBufferCount];
498 mAuxBufferCount = auxBufferCount;
500 this->syncAllBuffers(serial);
503 void cook(
size_t grainsize)
506 tbb::parallel_for(this->getRange(grainsize), *
this);
508 (*this)(this->getRange());
512 void doSwapLeafBuffer(
const RangeType& r,
size_t auxBufferIdx)
514 LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
515 r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
518 void doSwapAuxBuffer(
const RangeType& r,
size_t auxBufferIdx1,
size_t auxBufferIdx2)
520 for (
size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
521 mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
525 void doSyncAuxBuffer(
const RangeType& r,
size_t auxBufferIdx)
527 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
528 mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
532 void doSyncAllBuffers1(
const RangeType& r)
534 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
535 mAuxBuffers[n] = mLeafs[n]->buffer();
539 void doSyncAllBuffers2(
const RangeType& r)
541 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
542 const BufferType& leafBuffer = mLeafs[n]->buffer();
543 mAuxBuffers[2*n ] = leafBuffer;
544 mAuxBuffers[2*n+1] = leafBuffer;
548 void doSyncAllBuffersN(
const RangeType& r)
550 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
551 const BufferType& leafBuffer = mLeafs[n]->buffer();
552 for (
size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
558 template<
typename LeafOp>
559 struct LeafTransformer
561 LeafTransformer(LeafManager& leafs,
const LeafOp& leafOp)
562 : mLeafManager(&leafs), mLeafOp(leafOp) {}
563 void run(
bool threaded =
true)
566 tbb::parallel_for(mLeafManager->getRange(), *
this);
568 (*this)(mLeafManager->getRange());
571 void operator()(
const tbb::blocked_range<size_t>& range)
const
573 for (
size_t n = range.begin(); n < range.end(); ++n) {
574 mLeafOp(mLeafManager->leaf(n), n);
577 LeafManager* mLeafManager;
578 const LeafOp mLeafOp;
581 typedef typename boost::function<void (LeafManager*, const RangeType&)> FuncType;
584 size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
586 NonConstBufferType* mAuxBuffers;
588 const bool mIsMaster;
593 template<
typename TreeT>
612 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED