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;
84 static inline void doSwapLeafBuffer(
const RangeT& r,
size_t auxBufferIdx,
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]);
105 template<
typename TreeT>
127 assert(this->isValid());
139 return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
142 size_t pos()
const {
return mPos; }
143 bool isValid()
const {
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
145 operator bool()
const {
return mPos < mRange.mEnd; }
150 return (mPos != other.mPos) || (&mRange != &other.mRange);
161 mEnd(end), mBegin(begin), mGrainSize(grainSize), mLeafManager(leafManager) {}
167 size_t size()
const {
return mEnd - mBegin; }
173 bool empty()
const {
return !(mBegin < mEnd);}
178 mEnd(r.mEnd), mBegin(doSplit(r)), mGrainSize(r.mGrainSize),
179 mLeafManager(r.mLeafManager) {}
182 size_t mEnd, mBegin, mGrainSize;
188 size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
200 mAuxBuffersPerLeaf(auxBuffersPerLeaf),
206 this->rebuild(serial);
214 mLeafCount(other.mLeafCount),
215 mAuxBufferCount(other.mAuxBufferCount),
216 mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf),
217 mLeafs(other.mLeafs),
218 mAuxBuffers(other.mAuxBuffers),
228 delete [] mAuxBuffers;
237 void rebuild(
bool serial=
false)
239 this->initLeafArray();
240 this->initAuxBuffers(serial);
244 void rebuild(
size_t auxBuffersPerLeaf,
bool serial=
false)
246 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
247 this->rebuild(serial);
252 this->rebuild(serial);
254 void rebuild(
TreeType& tree,
size_t auxBuffersPerLeaf,
bool serial=
false)
257 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
258 this->rebuild(serial);
265 void rebuildAuxBuffers(
size_t auxBuffersPerLeaf,
bool serial=
false)
267 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
268 this->initAuxBuffers(serial);
274 void rebuildLeafArray()
276 this->removeAuxBuffers();
277 this->initLeafArray();
298 LeafType&
leaf(
size_t leafIdx)
const { assert(leafIdx<mLeafCount);
return *mLeafs[leafIdx]; }
310 BufferType& getBuffer(
size_t leafIdx,
size_t bufferIdx)
const
312 assert(leafIdx < mLeafCount);
313 assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
314 return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
315 : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
327 return LeafRange(0, mLeafCount, *
this, grainsize);
339 bool swapLeafBuffer(
size_t bufferIdx,
bool serial =
false)
341 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree())
return false;
342 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, bufferIdx - 1);
343 this->cook(serial ? 0 : 512);
350 bool swapBuffer(
size_t bufferIdx1,
size_t bufferIdx2,
bool serial =
false)
352 const size_t b1 =
std::min(bufferIdx1, bufferIdx2);
353 const size_t b2 =
std::max(bufferIdx1, bufferIdx2);
354 if (b1 == b2 || b2 > mAuxBuffersPerLeaf)
return false;
356 if (this->isConstTree())
return false;
357 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, b2-1);
359 mTask = boost::bind(&LeafManager::doSwapAuxBuffer, _1, _2, b1-1, b2-1);
361 this->cook(serial ? 0 : 512);
373 bool syncAuxBuffer(
size_t bufferIdx,
bool serial =
false)
375 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf)
return false;
376 mTask = boost::bind(&LeafManager::doSyncAuxBuffer, _1, _2, bufferIdx - 1);
377 this->cook(serial ? 0 : 64);
384 bool syncAllBuffers(
bool serial =
false)
386 switch (mAuxBuffersPerLeaf) {
387 case 0:
return false;
388 case 1: mTask = boost::bind(&LeafManager::doSyncAllBuffers1, _1, _2);
break;
389 case 2: mTask = boost::bind(&LeafManager::doSyncAllBuffers2, _1, _2);
break;
390 default: mTask = boost::bind(&LeafManager::doSyncAllBuffersN, _1, _2);
break;
392 this->cook(serial ? 0 : 64);
402 if (mTask) mTask(const_cast<LeafManager*>(
this), r);
409 const size_t leafCount = mTree->leafCount();
410 if (leafCount != mLeafCount) {
412 mLeafs = (leafCount == 0) ? NULL :
new LeafType*[leafCount];
413 mLeafCount = leafCount;
415 LeafIterType iter = mTree->beginLeaf();
416 for (
size_t n = 0; n != leafCount; ++n, ++iter) mLeafs[n] = iter.getLeaf();
419 void initAuxBuffers(
bool serial)
421 const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
422 if (auxBufferCount != mAuxBufferCount) {
423 delete [] mAuxBuffers;
424 mAuxBuffers = (auxBufferCount == 0) ? NULL :
new NonConstBufferType[auxBufferCount];
425 mAuxBufferCount = auxBufferCount;
427 this->syncAllBuffers(serial);
430 void cook(
size_t grainsize)
433 tbb::parallel_for(this->getRange(grainsize), *
this);
435 (*this)(this->getRange());
439 void doSwapLeafBuffer(
const RangeType& r,
size_t auxBufferIdx)
441 LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
442 r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
445 void doSwapAuxBuffer(
const RangeType& r,
size_t auxBufferIdx1,
size_t auxBufferIdx2)
447 for (
size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
448 mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
452 void doSyncAuxBuffer(
const RangeType& r,
size_t auxBufferIdx)
454 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
455 mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
459 void doSyncAllBuffers1(
const RangeType& r)
461 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
462 mAuxBuffers[n] = mLeafs[n]->buffer();
466 void doSyncAllBuffers2(
const RangeType& r)
468 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
469 const BufferType& leafBuffer = mLeafs[n]->buffer();
470 mAuxBuffers[2*n ] = leafBuffer;
471 mAuxBuffers[2*n+1] = leafBuffer;
475 void doSyncAllBuffersN(
const RangeType& r)
477 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
478 const BufferType& leafBuffer = mLeafs[n]->buffer();
479 for (
size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
483 typedef typename boost::function<void (LeafManager*, const RangeType&)> FuncType;
486 size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
488 NonConstBufferType* mAuxBuffers;
490 const bool mIsMaster;
495 template<
typename TreeT>
503 static inline void doSwapLeafBuffer(
const RangeT&,
size_t ,
514 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED