Go to the documentation of this file.
42 #ifndef OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
46 #include <tbb/blocked_range.h>
47 #include <tbb/parallel_for.h>
48 #include <tbb/parallel_reduce.h>
50 #include <type_traits>
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 using RangeT =
typename ManagerT::RangeType;
81 using LeafT =
typename ManagerT::LeafType;
82 using BufT =
typename ManagerT::BufferType;
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>
134 assert(this->isValid());
148 return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
151 size_t pos()
const {
return mPos; }
153 bool isValid()
const {
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
155 bool test()
const {
return mPos < mRange.mEnd; }
157 operator bool()
const {
return this->test(); }
159 bool empty()
const {
return !this->test(); }
162 return (mPos != other.mPos) || (&mRange != &other.mRange);
175 , mGrainSize(grainSize)
176 , mLeafManager(leafManager)
184 size_t size()
const {
return mEnd - mBegin; }
190 bool empty()
const {
return !(mBegin < mEnd);}
197 , mGrainSize(r.mGrainSize)
198 , mLeafManager(r.mLeafManager)
203 size_t mEnd, mBegin, mGrainSize;
209 size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
221 , mAuxBuffersPerLeaf(auxBuffersPerLeaf)
223 , mAuxBuffers(nullptr)
227 this->rebuild(serial);
234 size_t auxBuffersPerLeaf=0,
bool serial=
false)
236 , mLeafCount(end-begin)
238 , mAuxBuffersPerLeaf(auxBuffersPerLeaf)
240 , mAuxBuffers(nullptr)
244 size_t n = mLeafCount;
245 LeafType **target = mLeafs, **source = begin;
246 while (n--) *target++ = *source++;
247 if (auxBuffersPerLeaf) this->initAuxBuffers(serial);
255 , mLeafCount(other.mLeafCount)
256 , mAuxBufferCount(other.mAuxBufferCount)
257 , mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf)
258 , mLeafs(other.mLeafs)
259 , mAuxBuffers(other.mAuxBuffers)
269 delete [] mAuxBuffers;
280 this->initLeafArray();
281 this->initAuxBuffers(serial);
284 void rebuild(
size_t auxBuffersPerLeaf,
bool serial=
false)
287 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
288 this->rebuild(serial);
293 this->rebuild(serial);
298 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
299 this->rebuild(serial);
302 void rebuildAuxBuffers(
size_t auxBuffersPerLeaf,
bool serial=
false)
308 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
309 this->initAuxBuffers(serial);
317 this->removeAuxBuffers();
318 this->initLeafArray();
333 return tbb::parallel_reduce(this->leafRange(),
Index64(0),
335 for (
const auto& leaf: range) { sum += leaf.onVoxelCount(); }
358 LeafType&
leaf(
size_t leafIdx)
const { assert(leafIdx<mLeafCount);
return *mLeafs[leafIdx]; }
372 assert(leafIdx < mLeafCount);
373 assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
374 return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
375 : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
387 return LeafRange(0, mLeafCount, *
this, grainsize);
401 namespace ph = std::placeholders;
402 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree())
return false;
403 mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, bufferIdx - 1);
404 this->cook(serial ? 0 : 512);
411 bool swapBuffer(
size_t bufferIdx1,
size_t bufferIdx2,
bool serial =
false)
413 namespace ph = std::placeholders;
414 const size_t b1 =
std::min(bufferIdx1, bufferIdx2);
415 const size_t b2 =
std::max(bufferIdx1, bufferIdx2);
416 if (b1 == b2 || b2 > mAuxBuffersPerLeaf)
return false;
418 if (this->isConstTree())
return false;
419 mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, b2-1);
421 mTask = std::bind(&LeafManager::doSwapAuxBuffer, ph::_1, ph::_2, b1-1, b2-1);
423 this->cook(serial ? 0 : 512);
437 namespace ph = std::placeholders;
438 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf)
return false;
439 mTask = std::bind(&LeafManager::doSyncAuxBuffer, ph::_1, ph::_2, bufferIdx - 1);
440 this->cook(serial ? 0 : 64);
449 namespace ph = std::placeholders;
450 switch (mAuxBuffersPerLeaf) {
451 case 0:
return false;
452 case 1: mTask = std::bind(&LeafManager::doSyncAllBuffers1, ph::_1, ph::_2);
break;
453 case 2: mTask = std::bind(&LeafManager::doSyncAllBuffers2, ph::_1, ph::_2);
break;
454 default: mTask = std::bind(&LeafManager::doSyncAllBuffersN, ph::_1, ph::_2);
break;
456 this->cook(serial ? 0 : 64);
522 template<
typename LeafOp>
523 void foreach(
const LeafOp& op,
bool threaded =
true,
size_t grainSize=1)
525 LeafTransformer<LeafOp> transform(op);
526 transform.run(this->leafRange(grainSize), threaded);
571 template<
typename LeafOp>
572 void reduce(LeafOp& op,
bool threaded =
true,
size_t grainSize=1)
574 LeafReducer<LeafOp> transform(op);
575 transform.run(this->leafRange(grainSize), threaded);
583 template<
typename ArrayT>
586 using T =
typename ArrayT::value_type;
587 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
588 using LeafT =
typename std::conditional<std::is_const<
589 typename std::remove_pointer<T>::type>::value,
const LeafType,
LeafType>::type;
592 if (std::is_same<T, LeafT*>::value) {
593 array.resize(mLeafCount);
594 for (
size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
596 mTree->getNodes(array);
605 template<
typename ArrayT>
608 using T =
typename ArrayT::value_type;
609 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
610 static_assert(std::is_const<
typename std::remove_pointer<T>::type>::value,
611 "argument to getNodes() must be an array of const node pointers");
614 if (std::is_same<T, const LeafType*>::value) {
615 array.resize(mLeafCount);
616 for (
size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
618 mTree->getNodes(array);
634 size_t getPrefixSum(
size_t*& offsets,
size_t& size,
size_t grainSize=1)
const
636 if (offsets ==
nullptr || size < mLeafCount) {
638 offsets =
new size_t[mLeafCount];
642 if ( grainSize > 0 ) {
643 PrefixSum tmp(this->leafRange( grainSize ), offsets, prefix);
645 for (
size_t i=0; i<mLeafCount; ++i) {
647 prefix += mLeafs[i]->onVoxelCount();
659 if (mTask) mTask(const_cast<LeafManager*>(
this), r);
669 using value_type = LeafType*;
671 MyArray(value_type* array) : ptr(array) {}
672 void push_back(value_type leaf) { *ptr++ = leaf; }
677 const size_t leafCount = mTree->leafCount();
678 if (leafCount != mLeafCount) {
680 mLeafs = (leafCount == 0) ?
nullptr :
new LeafType*[leafCount];
681 mLeafCount = leafCount;
687 void initAuxBuffers(
bool serial)
689 const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
690 if (auxBufferCount != mAuxBufferCount) {
691 delete [] mAuxBuffers;
692 mAuxBuffers = (auxBufferCount == 0) ?
nullptr :
new NonConstBufferType[auxBufferCount];
693 mAuxBufferCount = auxBufferCount;
695 this->syncAllBuffers(serial);
698 void cook(
size_t grainsize)
701 tbb::parallel_for(this->getRange(grainsize), *
this);
703 (*this)(this->getRange());
707 void doSwapLeafBuffer(
const RangeType& r,
size_t auxBufferIdx)
709 LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
710 r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
713 void doSwapAuxBuffer(
const RangeType& r,
size_t auxBufferIdx1,
size_t auxBufferIdx2)
715 for (
size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
716 mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
720 void doSyncAuxBuffer(
const RangeType& r,
size_t auxBufferIdx)
722 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
723 mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
727 void doSyncAllBuffers1(
const RangeType& r)
729 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
730 mAuxBuffers[n] = mLeafs[n]->buffer();
734 void doSyncAllBuffers2(
const RangeType& r)
736 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
737 const BufferType& leafBuffer = mLeafs[n]->buffer();
738 mAuxBuffers[2*n ] = leafBuffer;
739 mAuxBuffers[2*n+1] = leafBuffer;
743 void doSyncAllBuffersN(
const RangeType& r)
745 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
746 const BufferType& leafBuffer = mLeafs[n]->buffer();
747 for (
size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
753 template<
typename LeafOp>
754 struct LeafTransformer
756 LeafTransformer(
const LeafOp &leafOp) : mLeafOp(leafOp)
759 void run(
const LeafRange &range,
bool threaded)
const
761 threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
763 void operator()(
const LeafRange &range)
const
765 for (
typename LeafRange::Iterator it = range.begin(); it; ++it) mLeafOp(*it, it.pos());
767 const LeafOp mLeafOp;
772 template<
typename LeafOp>
775 LeafReducer(LeafOp &leafOp) : mLeafOp(&leafOp), mOwnsOp(false)
778 LeafReducer(
const LeafReducer &other, tbb::split)
779 : mLeafOp(new LeafOp(*(other.mLeafOp),
tbb::split())), mOwnsOp(true)
782 ~LeafReducer() {
if (mOwnsOp)
delete mLeafOp; }
783 void run(
const LeafRange& range,
bool threaded)
785 threaded ? tbb::parallel_reduce(range, *
this) : (*this)(range);
787 void operator()(
const LeafRange& range)
789 LeafOp &op = *mLeafOp;
790 for (
typename LeafRange::Iterator it = range.begin(); it; ++it) op(*it, it.pos());
792 void join(
const LeafReducer& other) { mLeafOp->join(*(other.mLeafOp)); }
800 PrefixSum(
const LeafRange& r,
size_t* offsets,
size_t& prefix)
803 tbb::parallel_for( r, *
this);
804 for (
size_t i=0, leafCount = r.size(); i<leafCount; ++i) {
805 size_t tmp = offsets[i];
810 inline void operator()(
const LeafRange& r)
const {
811 for (
typename LeafRange::Iterator i = r.begin(); i; ++i) {
812 mOffsets[i.pos()] = i->onVoxelCount();
818 using FuncType =
typename std::function<void (LeafManager*,
const RangeType&)>;
821 size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
823 NonConstBufferType* mAuxBuffers;
825 const bool mIsMaster;
830 template<
typename TreeT>
849 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
typename LeafType::Buffer NonConstBufferType
Definition: LeafManager.h:119
BufferType & buffer(size_t bufferIdx)
Return the nth buffer for the leaf node to which this iterator is pointing, where n = bufferIdx and n...
Definition: LeafManager.h:146
LeafType LeafNodeType
Definition: LeafManager.h:117
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:327
bool syncAuxBuffer(size_t bufferIdx, bool serial=false)
Sync up the specified auxiliary buffer with the corresponding leaf node buffer.
Definition: LeafManager.h:435
void getNodes(ArrayT &array) const
Insert node pointers of the specified type into the array.
Definition: LeafManager.h:606
LeafManager(TreeType &tree, size_t auxBuffersPerLeaf=0, bool serial=false)
Constructor from a tree reference and an auxiliary buffer count.
Definition: LeafManager.h:217
Iterator begin() const
Definition: LeafManager.h:180
RootNodeType & root()
Return a reference to the root node associated with this manager.
Definition: LeafManager.h:351
TreeT TreeType
Definition: LeafManager.h:112
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:80
const LeafManager & leafManager() const
Definition: LeafManager.h:188
void removeAuxBuffers()
Remove the auxiliary buffers, but don't rebuild the leaf array.
Definition: LeafManager.h:312
bool empty() const
Definition: LeafManager.h:190
bool isValid() const
Return true if the position of this iterator is in a valid range.
Definition: LeafManager.h:153
bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial=false)
Swap any two buffers for each leaf node.
Definition: LeafManager.h:411
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:120
typename TreeT::LeafCIter LeafIterType
Definition: LeafManager.h:68
static void doSwapLeafBuffer(const RangeT &, size_t, LeafT **, BufT *, size_t)
Definition: LeafManager.h:838
void rebuild(TreeType &tree, size_t auxBuffersPerLeaf, bool serial=false)
Definition: LeafManager.h:295
typename CopyConstness< TreeType, NonConstLeafType >::Type LeafType
Definition: LeafManager.h:116
void rebuild(bool serial=false)
(Re)initialize by resizing (if necessary) and repopulating the leaf array and by deleting existing au...
Definition: LeafManager.h:278
void rebuild(TreeType &tree, bool serial=false)
Definition: LeafManager.h:290
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
Definition: LeafManager.h:129
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:382
typename TreeType::LeafNodeType NonConstLeafType
Definition: LeafManager.h:115
bool test() const
Return true if this iterator is not yet exhausted.
Definition: LeafManager.h:155
LeafType & operator*() const
Return a reference to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:141
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:358
tbb::blocked_range< size_t > RangeType
Definition: LeafManager.h:121
TreeType & tree()
Return a reference to the tree associated with this manager.
Definition: LeafManager.h:345
size_t size() const
Definition: LeafManager.h:184
Definition: Exceptions.h:92
bool operator!=(const Iterator &other) const
Definition: LeafManager.h:160
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:385
BufferType & getBuffer(size_t leafIdx, size_t bufferIdx) const
Return the leaf or auxiliary buffer for the leaf node at index leafIdx. If bufferIdx is zero,...
Definition: LeafManager.h:370
Index32 Index
Definition: Types.h:61
Definition: LeafManager.h:78
bool is_divisible() const
Definition: LeafManager.h:192
Iterator end() const
Definition: LeafManager.h:182
LeafRange(LeafRange &r, tbb::split)
Definition: LeafManager.h:194
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:81
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:342
uint64_t Index64
Definition: Types.h:60
size_t auxBufferCount() const
Return the total number of allocated auxiliary buffers.
Definition: LeafManager.h:322
LeafType * operator->() const
Return a pointer to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:143
void getNodes(ArrayT &array)
Insert pointers to nodes of the specified type into the array.
Definition: LeafManager.h:584
typename TreeT::ValueType ValueType
Definition: LeafManager.h:113
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
size_t getPrefixSum(size_t *&offsets, size_t &size, size_t grainSize=1) const
Generate a linear array of prefix sums of offsets into the active voxels in the leafs....
Definition: LeafManager.h:634
LeafRange(size_t begin, size_t end, const LeafManager &leafManager, size_t grainSize=1)
Definition: LeafManager.h:172
Useful traits for Tree types.
Definition: LeafManager.h:62
bool empty() const
Return true if this iterator is exhausted.
Definition: LeafManager.h:159
Definition: LeafManager.h:126
size_t pos() const
Return the index into the leaf array of the current leaf node.
Definition: LeafManager.h:151
const LeafRange & leafRange() const
Definition: LeafManager.h:165
bool operator==(const Iterator &other) const
Definition: LeafManager.h:164
LeafManager(const LeafManager &other)
Definition: LeafManager.h:253
typename leafmgr::TreeTraits< TreeT >::LeafIterType LeafIterType
Definition: LeafManager.h:118
typename TreeT::RootNodeType RootNodeType
Definition: LeafManager.h:114
void reduce(LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager....
Definition: LeafManager.h:572
size_t auxBuffersPerLeaf() const
Return the number of auxiliary buffers per leaf node.
Definition: LeafManager.h:324
static void doSwapLeafBuffer(const RangeT &r, size_t auxBufferIdx, LeafT **leafs, BufT *bufs, size_t bufsPerLeaf)
Definition: LeafManager.h:84
Iterator & operator++()
Advance to the next leaf node.
Definition: LeafManager.h:139
LeafManager(TreeType &tree, LeafType **begin, LeafType **end, size_t auxBuffersPerLeaf=0, bool serial=false)
Construct directly from an existing array of leafnodes.
Definition: LeafManager.h:233
void operator()(const RangeType &r) const
Used internally by tbb::parallel_for() - never call it directly!
Definition: LeafManager.h:657
typename TreeT::LeafIter LeafIterType
Definition: LeafManager.h:64
typename ManagerT::BufferType BufT
Definition: LeafManager.h:836
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
typename std::remove_const< ToType >::type Type
Definition: Types.h:348
const RootNodeType & root() const
Return a const reference to root node associated with this manager.
Definition: LeafManager.h:348
Index64 activeLeafVoxelCount() const
Return the number of active voxels in the leaf nodes.
Definition: LeafManager.h:331
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:835
Definition: Exceptions.h:40
bool swapLeafBuffer(size_t bufferIdx, bool serial=false)
Swap each leaf node's buffer with the nth corresponding auxiliary buffer, where n = bufferIdx.
Definition: LeafManager.h:399
typename ManagerT::BufferType BufT
Definition: LeafManager.h:82
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:645
size_t grainsize() const
Definition: LeafManager.h:186
bool syncAllBuffers(bool serial=false)
Sync up all auxiliary buffers with their corresponding leaf node buffers.
Definition: LeafManager.h:447
Iterator(const LeafRange &range, size_t pos)
Definition: LeafManager.h:132
bool isConstTree() const
Return true if the tree associated with this manager is immutable.
Definition: LeafManager.h:354
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:834
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
virtual ~LeafManager()
Definition: LeafManager.h:265
void rebuildLeafArray()
Remove the auxiliary buffers and rebuild the leaf array.
Definition: LeafManager.h:315