OpenVDB: LeafManager.h Source File

OpenVDB 8.1.0

LeafManager.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
14
15 #ifndef OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
16 #define OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
17
18 #include <openvdb/Types.h>
19 #include <openvdb/tree/RootNode.h> // for NodeChain
20 #include <tbb/blocked_range.h>
21 #include <tbb/parallel_for.h>
22 #include <tbb/parallel_reduce.h>
23 #include <deque>
24 #include <functional>
25 #include <type_traits>
26
27
28 namespace openvdb {
29 OPENVDB_USE_VERSION_NAMESPACE
30 namespace OPENVDB_VERSION_NAME {
31 namespace tree {
32
33 namespace leafmgr {
34
36 template<typename TreeT> struct TreeTraits {
38 static const bool IsConstTree = false;
39 using LeafIterType = typename TreeT::LeafIter;
40 };
41 template<typename TreeT> struct TreeTraits<const TreeT> {
42 static const bool IsConstTree = true;
43 using LeafIterType = typename TreeT::LeafCIter;
44 };
46
47 } // namespace leafmgr
48
49
52 template<typename ManagerT>
53 struct LeafManagerImpl
54 {
55 using RangeT = typename ManagerT::RangeType;
56 using LeafT = typename ManagerT::LeafType;
57 using BufT = typename ManagerT::BufferType;
58
59 static inline void doSwapLeafBuffer(const RangeT& r, size_t auxBufferIdx,
60 LeafT** leafs, BufT* bufs, size_t bufsPerLeaf)
61 {
62 for (size_t n = r.begin(), m = r.end(), N = bufsPerLeaf; n != m; ++n) {
63 leafs[n]->swap(bufs[n * N + auxBufferIdx]);
64 }
65 }
66 };
67
68
70
71
83 template<typename TreeT>
84 class LeafManager
85 {
86 public:
87 using TreeType = TreeT;
88 using ValueType = typename TreeT::ValueType;
89 using RootNodeType = typename TreeT::RootNodeType;
90 using NonConstLeafType = typename TreeType::LeafNodeType;
91 using LeafType = typename CopyConstness<TreeType, NonConstLeafType>::Type;
92 using LeafNodeType = LeafType;
93 using LeafIterType = typename leafmgr::TreeTraits<TreeT>::LeafIterType;
94 using NonConstBufferType = typename LeafType::Buffer;
95 using BufferType = typename CopyConstness<TreeType, NonConstBufferType>::Type;
96 using RangeType = tbb::blocked_range<size_t>; // leaf index range
97 static const Index DEPTH = 2; // root + leaf nodes
98
99 static const bool IsConstTree = leafmgr::TreeTraits<TreeT>::IsConstTree;
100
101 class LeafRange
102 {
103 public:
104 class Iterator
105 {
106 public:
107 Iterator(const LeafRange& range, size_t pos): mRange(range), mPos(pos)
108 {
109 assert(this->isValid());
110 }
111 Iterator(const Iterator&) = default;
112 Iterator& operator=(const Iterator&) = default;
114 Iterator& operator++() { ++mPos; return *this; }
116 LeafType& operator*() const { return mRange.mLeafManager.leaf(mPos); }
118 LeafType* operator->() const { return &(this->operator*()); }
121 BufferType& buffer(size_t bufferIdx)
122 {
123 return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
124 }
126 size_t pos() const { return mPos; }
128 bool isValid() const { return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
130 bool test() const { return mPos < mRange.mEnd; }
132 operator bool() const { return this->test(); }
134 bool empty() const { return !this->test(); }
135 bool operator!=(const Iterator& other) const
136 {
137 return (mPos != other.mPos) || (&mRange != &other.mRange);
138 }
139 bool operator==(const Iterator& other) const { return !(*this != other); }
140 const LeafRange& leafRange() const { return mRange; }
141
142 private:
143 const LeafRange& mRange;
144 size_t mPos;
145 };// end Iterator
146
147 LeafRange(size_t begin, size_t end, const LeafManager& leafManager, size_t grainSize=1)
148 : mEnd(end)
149 , mBegin(begin)
150 , mGrainSize(grainSize)
151 , mLeafManager(leafManager)
152 {
153 }
154
155 Iterator begin() const {return Iterator(*this, mBegin);}
156
157 Iterator end() const {return Iterator(*this, mEnd);}
158
159 size_t size() const { return mEnd - mBegin; }
160
161 size_t grainsize() const { return mGrainSize; }
162
163 const LeafManager& leafManager() const { return mLeafManager; }
164
165 bool empty() const {return !(mBegin < mEnd);}
166
167 bool is_divisible() const {return mGrainSize < this->size();}
168
169 LeafRange(LeafRange& r, tbb::split)
170 : mEnd(r.mEnd)
171 , mBegin(doSplit(r))
172 , mGrainSize(r.mGrainSize)
173 , mLeafManager(r.mLeafManager)
174 {
175 }
176
177 private:
178 size_t mEnd, mBegin, mGrainSize;
179 const LeafManager& mLeafManager;
180
181 static size_t doSplit(LeafRange& r)
182 {
183 assert(r.is_divisible());
184 size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
185 r.mEnd = middle;
186 return middle;
187 }
188 };// end of LeafRange
189
192 LeafManager(TreeType& tree, size_t auxBuffersPerLeaf=0, bool serial=false)
193 : mTree(&tree)
194 , mLeafCount(0)
195 , mAuxBufferCount(0)
196 , mAuxBuffersPerLeaf(auxBuffersPerLeaf)
197 {
198 this->rebuild(serial);
199 }
200
204 LeafManager(TreeType& tree, LeafType** begin, LeafType** end,
205 size_t auxBuffersPerLeaf=0, bool serial=false)
206 : mTree(&tree)
207 , mLeafCount(end-begin)
208 , mAuxBufferCount(0)
209 , mAuxBuffersPerLeaf(auxBuffersPerLeaf)
210 , mLeafPtrs(new LeafType*[mLeafCount])
211 , mLeafs(mLeafPtrs.get())
212 {
213 size_t n = mLeafCount;
214 LeafType **target = mLeafs, **source = begin;
215 while (n--) *target++ = *source++;
216 if (auxBuffersPerLeaf) this->initAuxBuffers(serial);
217 }
218
222 LeafManager(const LeafManager& other)
223 : mTree(other.mTree)
224 , mLeafCount(other.mLeafCount)
225 , mAuxBufferCount(other.mAuxBufferCount)
226 , mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf)
227 , mLeafs(other.mLeafs)
228 , mAuxBuffers(other.mAuxBuffers)
229 , mTask(other.mTask)
230 {
231 }
232
238 void rebuild(bool serial=false)
239 {
240 this->initLeafArray(serial);
241 this->initAuxBuffers(serial);
242 }
244 void rebuild(size_t auxBuffersPerLeaf, bool serial=false)
246 {
247 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
248 this->rebuild(serial);
249 }
250 void rebuild(TreeType& tree, bool serial=false)
251 {
252 mTree = &tree;
253 this->rebuild(serial);
254 }
255 void rebuild(TreeType& tree, size_t auxBuffersPerLeaf, bool serial=false)
256 {
257 mTree = &tree;
258 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
259 this->rebuild(serial);
260 }
262 void rebuildAuxBuffers(size_t auxBuffersPerLeaf, bool serial=false)
267 {
268 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
269 this->initAuxBuffers(serial);
270 }
272 void removeAuxBuffers() { this->rebuildAuxBuffers(0); }
273
275 void rebuildLeafArray(bool serial = false)
276 {
277 this->removeAuxBuffers();
278 this->initLeafArray(serial);
279 }
280
282 size_t auxBufferCount() const { return mAuxBufferCount; }
284 size_t auxBuffersPerLeaf() const { return mAuxBuffersPerLeaf; }
285
287 size_t leafCount() const { return mLeafCount; }
288
291 Index64 activeLeafVoxelCount() const
292 {
293 return tbb::parallel_reduce(this->leafRange(), Index64(0),
294 [] (const LeafRange& range, Index64 sum) -> Index64 {
295 for (const auto& leaf: range) { sum += leaf.onVoxelCount(); }
296 return sum;
297 },
298 [] (Index64 n, Index64 m) -> Index64 { return n + m; });
299 }
300
302 const TreeType& tree() const { return *mTree; }
303
305 TreeType& tree() { return *mTree; }
306
308 const RootNodeType& root() const { return mTree->root(); }
309
311 RootNodeType& root() { return mTree->root(); }
312
314 bool isConstTree() const { return this->IsConstTree; }
315
318 LeafType& leaf(size_t leafIdx) const { assert(leafIdx<mLeafCount); return *mLeafs[leafIdx]; }
319
330 BufferType& getBuffer(size_t leafIdx, size_t bufferIdx) const
331 {
332 assert(leafIdx < mLeafCount);
333 assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
334 return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
335 : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
336 }
337
342 RangeType getRange(size_t grainsize = 1) const { return RangeType(0, mLeafCount, grainsize); }
343
345 LeafRange leafRange(size_t grainsize = 1) const
346 {
347 return LeafRange(0, mLeafCount, *this, grainsize);
348 }
349
359 bool swapLeafBuffer(size_t bufferIdx, bool serial = false)
360 {
361 namespace ph = std::placeholders;
362 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree()) return false;
363 mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, bufferIdx - 1);
364 this->cook(serial ? 0 : 512);
365 return true;//success
366 }
371 bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial = false)
372 {
373 namespace ph = std::placeholders;
374 const size_t b1 = std::min(bufferIdx1, bufferIdx2);
375 const size_t b2 = std::max(bufferIdx1, bufferIdx2);
376 if (b1 == b2 || b2 > mAuxBuffersPerLeaf) return false;
377 if (b1 == 0) {
378 if (this->isConstTree()) return false;
379 mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, b2-1);
380 } else {
381 mTask = std::bind(&LeafManager::doSwapAuxBuffer, ph::_1, ph::_2, b1-1, b2-1);
382 }
383 this->cook(serial ? 0 : 512);
384 return true;//success
385 }
386
395 bool syncAuxBuffer(size_t bufferIdx, bool serial = false)
396 {
397 namespace ph = std::placeholders;
398 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf) return false;
399 mTask = std::bind(&LeafManager::doSyncAuxBuffer, ph::_1, ph::_2, bufferIdx - 1);
400 this->cook(serial ? 0 : 64);
401 return true;//success
402 }
403
407 bool syncAllBuffers(bool serial = false)
408 {
409 namespace ph = std::placeholders;
410 switch (mAuxBuffersPerLeaf) {
411 case 0: return false;//nothing to do
412 case 1: mTask = std::bind(&LeafManager::doSyncAllBuffers1, ph::_1, ph::_2); break;
413 case 2: mTask = std::bind(&LeafManager::doSyncAllBuffers2, ph::_1, ph::_2); break;
414 default: mTask = std::bind(&LeafManager::doSyncAllBuffersN, ph::_1, ph::_2); break;
415 }
416 this->cook(serial ? 0 : 64);
417 return true;//success
418 }
419
482 template<typename LeafOp>
483 void foreach(const LeafOp& op, bool threaded = true, size_t grainSize=1)
484 {
485 LeafTransformer<LeafOp> transform(op);
486 transform.run(this->leafRange(grainSize), threaded);
487 }
488
531 template<typename LeafOp>
532 void reduce(LeafOp& op, bool threaded = true, size_t grainSize=1)
533 {
534 LeafReducer<LeafOp> transform(op);
535 transform.run(this->leafRange(grainSize), threaded);
536 }
537
538 template<typename ArrayT>
539 OPENVDB_DEPRECATED_MESSAGE("Use Tree::getNodes()") void getNodes(ArrayT& array)
540 {
541 using T = typename ArrayT::value_type;
542 static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array");
543 using LeafT = typename std::conditional<std::is_const<
544 typename std::remove_pointer<T>::type>::value, const LeafType, LeafType>::type;
545
546 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
547 if (std::is_same<T, LeafT*>::value) {
548 array.resize(mLeafCount);
549 for (size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
550 } else {
551 mTree->getNodes(array);
552 }
553 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
554 }
555
556 template<typename ArrayT>
557 OPENVDB_DEPRECATED_MESSAGE("Use Tree::getNodes()") void getNodes(ArrayT& array) const
558 {
559 using T = typename ArrayT::value_type;
560 static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array");
561 static_assert(std::is_const<typename std::remove_pointer<T>::type>::value,
562 "argument to getNodes() must be an array of const node pointers");
563
564 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
565 if (std::is_same<T, const LeafType*>::value) {
566 array.resize(mLeafCount);
567 for (size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
568 } else {
569 mTree->getNodes(array);
570 }
571 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
572 }
573
585 size_t getPrefixSum(size_t*& offsets, size_t& size, size_t grainSize=1) const
586 {
587 if (offsets == nullptr || size < mLeafCount) {
588 delete [] offsets;
589 offsets = new size_t[mLeafCount];
590 size = mLeafCount;
591 }
592 size_t prefix = 0;
593 if ( grainSize > 0 ) {
594 PrefixSum tmp(this->leafRange( grainSize ), offsets, prefix);
595 } else {// serial
596 for (size_t i=0; i<mLeafCount; ++i) {
597 offsets[i] = prefix;
598 prefix += mLeafs[i]->onVoxelCount();
599 }
600 }
601 return prefix;
602 }
603
605 // All methods below are for internal use only and should never be called directly
606
608 void operator()(const RangeType& r) const
609 {
610 if (mTask) mTask(const_cast<LeafManager*>(this), r);
611 else OPENVDB_THROW(ValueError, "task is undefined");
612 }
613
614 private:
615
616 void initLeafArray(bool serial = false)
617 {
618 // Build an array of all nodes that have leaf nodes as their immediate children
619
620 using NodeChainT = typename NodeChain<RootNodeType, RootNodeType::LEVEL>::Type;
621 using NonConstLeafParentT = typename NodeChainT::template Get</*Level=*/1>;
622 using LeafParentT = typename CopyConstness<TreeType, NonConstLeafParentT>::Type;
623
624 std::deque<LeafParentT*> leafParents;
625 mTree->getNodes(leafParents);
626
627 // Compute the leaf counts for each node
628
629 std::vector<Index32> leafCounts;
630 if (serial) {
631 leafCounts.reserve(leafParents.size());
632 for (LeafParentT* leafParent : leafParents) {
633 leafCounts.push_back(leafParent->childCount());
634 }
635 } else {
636 leafCounts.resize(leafParents.size());
637 tbb::parallel_for(
638 // with typical node sizes and SSE enabled, there are only a handful
639 // of instructions executed per-operation with a default grainsize
640 // of 1, so increase to 64 to reduce parallel scheduling overhead
641 tbb::blocked_range<size_t>(0, leafParents.size(), /*grainsize=*/64),
642 [&](tbb::blocked_range<size_t>& range)
643 {
644 for (size_t i = range.begin(); i < range.end(); i++) {
645 leafCounts[i] = leafParents[i]->childCount();
646 }
647 }
648 );
649 }
650
651 // Turn leaf counts into a cumulative histogram and obtain total leaf count
652
653 for (size_t i = 1; i < leafCounts.size(); i++) {
654 leafCounts[i] += leafCounts[i-1];
655 }
656
657 const size_t leafCount = leafCounts.empty() ? 0 : leafCounts.back();
658
659 // Allocate (or deallocate) the leaf pointer array
660
661 if (leafCount != mLeafCount) {
662 if (leafCount > 0) {
663 mLeafPtrs.reset(new LeafType*[leafCount]);
664 mLeafs = mLeafPtrs.get();
665 } else {
666 mLeafPtrs.reset();
667 mLeafs = nullptr;
668 }
669 mLeafCount = leafCount;
670 }
671
672 if (mLeafCount == 0) return;
673
674 // Populate the leaf node pointers
675
676 if (serial) {
677 LeafType** leafPtr = mLeafs;
678 for (LeafParentT* leafParent : leafParents) {
679 for (auto iter = leafParent->beginChildOn(); iter; ++iter) {
680 *leafPtr++ = &iter.getValue();
681 }
682 }
683 } else {
684 tbb::parallel_for(
685 tbb::blocked_range<size_t>(0, leafParents.size()),
686 [&](tbb::blocked_range<size_t>& range)
687 {
688 size_t i = range.begin();
689 LeafType** leafPtr = mLeafs;
690 if (i > 0) leafPtr += leafCounts[i-1];
691 for ( ; i < range.end(); i++) {
692 for (auto iter = leafParents[i]->beginChildOn(); iter; ++iter) {
693 *leafPtr++ = &iter.getValue();
694 }
695 }
696 }
697 );
698 }
699 }
700
701 void initAuxBuffers(bool serial)
702 {
703 const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
704 if (auxBufferCount != mAuxBufferCount) {
705 if (auxBufferCount > 0) {
706 mAuxBufferPtrs.reset(new NonConstBufferType[auxBufferCount]);
707 mAuxBuffers = mAuxBufferPtrs.get();
708 } else {
709 mAuxBufferPtrs.reset();
710 mAuxBuffers = nullptr;
711 }
712 mAuxBufferCount = auxBufferCount;
713 }
714 this->syncAllBuffers(serial);
715 }
716
717 void cook(size_t grainsize)
718 {
719 if (grainsize>0) {
720 tbb::parallel_for(this->getRange(grainsize), *this);
721 } else {
722 (*this)(this->getRange());
723 }
724 }
725
726 void doSwapLeafBuffer(const RangeType& r, size_t auxBufferIdx)
727 {
728 LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
729 r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
730 }
731
732 void doSwapAuxBuffer(const RangeType& r, size_t auxBufferIdx1, size_t auxBufferIdx2)
733 {
734 for (size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
735 mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
736 }
737 }
738
739 void doSyncAuxBuffer(const RangeType& r, size_t auxBufferIdx)
740 {
741 for (size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
742 mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
743 }
744 }
745
746 void doSyncAllBuffers1(const RangeType& r)
747 {
748 for (size_t n = r.begin(), m = r.end(); n != m; ++n) {
749 mAuxBuffers[n] = mLeafs[n]->buffer();
750 }
751 }
752
753 void doSyncAllBuffers2(const RangeType& r)
754 {
755 for (size_t n = r.begin(), m = r.end(); n != m; ++n) {
756 const BufferType& leafBuffer = mLeafs[n]->buffer();
757 mAuxBuffers[2*n ] = leafBuffer;
758 mAuxBuffers[2*n+1] = leafBuffer;
759 }
760 }
761
762 void doSyncAllBuffersN(const RangeType& r)
763 {
764 for (size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
765 const BufferType& leafBuffer = mLeafs[n]->buffer();
766 for (size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
767 }
768 }
769
772 template<typename LeafOp>
773 struct LeafTransformer
774 {
775 LeafTransformer(const LeafOp &leafOp) : mLeafOp(leafOp)
776 {
777 }
778 void run(const LeafRange &range, bool threaded) const
779 {
780 threaded ? tbb::parallel_for(range, *this) : (*this)(range);
781 }
782 void operator()(const LeafRange &range) const
783 {
784 for (typename LeafRange::Iterator it = range.begin(); it; ++it) mLeafOp(*it, it.pos());
785 }
786 const LeafOp mLeafOp;
787 };// LeafTransformer
788
791 template<typename LeafOp>
792 struct LeafReducer
793 {
794 LeafReducer(LeafOp &leafOp) : mLeafOp(&leafOp)
795 {
796 }
797 LeafReducer(const LeafReducer &other, tbb::split)
798 : mLeafOpPtr(std::make_unique<LeafOp>(*(other.mLeafOp), tbb::split()))
799 , mLeafOp(mLeafOpPtr.get())
800 {
801 }
802 void run(const LeafRange& range, bool threaded)
803 {
804 threaded ? tbb::parallel_reduce(range, *this) : (*this)(range);
805 }
806 void operator()(const LeafRange& range)
807 {
808 LeafOp &op = *mLeafOp;//local registry
809 for (typename LeafRange::Iterator it = range.begin(); it; ++it) op(*it, it.pos());
810 }
811 void join(const LeafReducer& other) { mLeafOp->join(*(other.mLeafOp)); }
812 std::unique_ptr<LeafOp> mLeafOpPtr;
813 LeafOp *mLeafOp = nullptr;
814 };// LeafReducer
815
816 // Helper class to compute a prefix sum of offsets to active voxels
817 struct PrefixSum
818 {
819 PrefixSum(const LeafRange& r, size_t* offsets, size_t& prefix)
820 : mOffsets(offsets)
821 {
822 tbb::parallel_for( r, *this);
823 for (size_t i=0, leafCount = r.size(); i<leafCount; ++i) {
824 size_t tmp = offsets[i];
825 offsets[i] = prefix;
826 prefix += tmp;
827 }
828 }
829 inline void operator()(const LeafRange& r) const {
830 for (typename LeafRange::Iterator i = r.begin(); i; ++i) {
831 mOffsets[i.pos()] = i->onVoxelCount();
832 }
833 }
834 size_t* mOffsets;
835 };// PrefixSum
836
837 using FuncType = typename std::function<void (LeafManager*, const RangeType&)>;
838
839 TreeType* mTree;
840 size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
841 std::unique_ptr<LeafType*[]> mLeafPtrs;
842 LeafType** mLeafs = nullptr;//array of LeafNode pointers
843 std::unique_ptr<NonConstBufferType[]> mAuxBufferPtrs;
844 NonConstBufferType* mAuxBuffers = nullptr;//array of auxiliary buffers
845 FuncType mTask = nullptr;
846 };//end of LeafManager class
847
848
849 // Partial specializations of LeafManager methods for const trees
850 template<typename TreeT>
851 struct LeafManagerImpl<LeafManager<const TreeT> >
852 {
853 using ManagerT = LeafManager<const TreeT>;
854 using RangeT = typename ManagerT::RangeType;
855 using LeafT = typename ManagerT::LeafType;
856 using BufT = typename ManagerT::BufferType;
857
858 static inline void doSwapLeafBuffer(const RangeT&, size_t /*auxBufferIdx*/,
859 LeafT**, BufT*, size_t /*bufsPerLeaf*/)
860 {
861 // Buffers can't be swapped into const trees.
862 }
863 };
864
865 } // namespace tree
866 } // namespace OPENVDB_VERSION_NAME
867 } // namespace openvdb
868
869 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:116
OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:115
RootNode.h
The root node of an OpenVDB tree.
openvdb::v8_1::ValueError
Definition: openvdb/Exceptions.h:65
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator
Definition: LeafManager.h:105
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::operator->
LeafType * operator->() const
Return a pointer to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:118
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::operator*
LeafType & operator*() const
Return a reference to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:116
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::leafRange
const LeafRange & leafRange() const
Definition: LeafManager.h:140
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::test
bool test() const
Return true if this iterator is not yet exhausted.
Definition: LeafManager.h:130
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::operator=
Iterator & operator=(const Iterator &)=default
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::isValid
bool isValid() const
Return true if the position of this iterator is in a valid range.
Definition: LeafManager.h:128
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::empty
bool empty() const
Return true if this iterator is exhausted.
Definition: LeafManager.h:134
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::Iterator
Iterator(const LeafRange &range, size_t pos)
Definition: LeafManager.h:107
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::Iterator
Iterator(const Iterator &)=default
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::operator!=
bool operator!=(const Iterator &other) const
Definition: LeafManager.h:135
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::buffer
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:121
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::pos
size_t pos() const
Return the index into the leaf array of the current leaf node.
Definition: LeafManager.h:126
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::operator==
bool operator==(const Iterator &other) const
Definition: LeafManager.h:139
openvdb::v8_1::tree::LeafManager::LeafRange::Iterator::operator++
Iterator & operator++()
Advance to the next leaf node.
Definition: LeafManager.h:114
openvdb::v8_1::tree::LeafManager::LeafRange
Definition: LeafManager.h:102
openvdb::v8_1::tree::LeafManager::LeafRange::LeafRange
LeafRange(size_t begin, size_t end, const LeafManager &leafManager, size_t grainSize=1)
Definition: LeafManager.h:147
openvdb::v8_1::tree::LeafManager::LeafRange::begin
Iterator begin() const
Definition: LeafManager.h:155
openvdb::v8_1::tree::LeafManager::LeafRange::leafManager
const LeafManager & leafManager() const
Definition: LeafManager.h:163
openvdb::v8_1::tree::LeafManager::LeafRange::size
size_t size() const
Definition: LeafManager.h:159
openvdb::v8_1::tree::LeafManager::LeafRange::is_divisible
bool is_divisible() const
Definition: LeafManager.h:167
openvdb::v8_1::tree::LeafManager::LeafRange::end
Iterator end() const
Definition: LeafManager.h:157
openvdb::v8_1::tree::LeafManager::LeafRange::empty
bool empty() const
Definition: LeafManager.h:165
openvdb::v8_1::tree::LeafManager::LeafRange::LeafRange
LeafRange(LeafRange &r, tbb::split)
Definition: LeafManager.h:169
openvdb::v8_1::tree::LeafManager::LeafRange::grainsize
size_t grainsize() const
Definition: LeafManager.h:161
openvdb::v8_1::tree::LeafManager
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
openvdb::v8_1::tree::LeafManager::OPENVDB_DEPRECATED_MESSAGE
OPENVDB_DEPRECATED_MESSAGE("Use Tree::getNodes()") void getNodes(ArrayT &array)
Definition: LeafManager.h:539
openvdb::v8_1::tree::LeafManager::getPrefixSum
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:585
openvdb::v8_1::tree::LeafManager::auxBufferCount
size_t auxBufferCount() const
Return the total number of allocated auxiliary buffers.
Definition: LeafManager.h:282
openvdb::v8_1::tree::LeafManager::BufferType
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:95
openvdb::v8_1::tree::LeafManager::root
RootNodeType & root()
Return a reference to the root node associated with this manager.
Definition: LeafManager.h:311
openvdb::v8_1::tree::LeafManager::ValueType
typename TreeT::ValueType ValueType
Definition: LeafManager.h:88
openvdb::v8_1::tree::LeafManager::LeafIterType
typename leafmgr::TreeTraits< TreeT >::LeafIterType LeafIterType
Definition: LeafManager.h:93
openvdb::v8_1::tree::LeafManager::swapLeafBuffer
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:359
openvdb::v8_1::tree::LeafManager::rebuild
void rebuild(TreeType &tree, bool serial=false)
Definition: LeafManager.h:250
openvdb::v8_1::tree::LeafManager::operator()
void operator()(const RangeType &r) const
Used internally by tbb::parallel_for() - never call it directly!
Definition: LeafManager.h:608
openvdb::v8_1::tree::LeafManager::rebuild
void rebuild(bool serial=false)
(Re)initialize by resizing (if necessary) and repopulating the leaf array and by deleting existing au...
Definition: LeafManager.h:238
openvdb::v8_1::tree::LeafManager::swapBuffer
bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial=false)
Swap any two buffers for each leaf node.
Definition: LeafManager.h:371
openvdb::v8_1::tree::LeafManager::getRange
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:342
openvdb::v8_1::tree::LeafManager::syncAuxBuffer
bool syncAuxBuffer(size_t bufferIdx, bool serial=false)
Sync up the specified auxiliary buffer with the corresponding leaf node buffer.
Definition: LeafManager.h:395
openvdb::v8_1::tree::LeafManager::syncAllBuffers
bool syncAllBuffers(bool serial=false)
Sync up all auxiliary buffers with their corresponding leaf node buffers.
Definition: LeafManager.h:407
openvdb::v8_1::tree::LeafManager::OPENVDB_DEPRECATED_MESSAGE
OPENVDB_DEPRECATED_MESSAGE("Use Tree::getNodes()") void getNodes(ArrayT &array) const
Definition: LeafManager.h:557
openvdb::v8_1::tree::LeafManager::LeafManager
LeafManager(const LeafManager &other)
Definition: LeafManager.h:222
openvdb::v8_1::tree::LeafManager::reduce
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:532
openvdb::v8_1::tree::LeafManager::isConstTree
bool isConstTree() const
Return true if the tree associated with this manager is immutable.
Definition: LeafManager.h:314
openvdb::v8_1::tree::LeafManager::RootNodeType
typename TreeT::RootNodeType RootNodeType
Definition: LeafManager.h:89
openvdb::v8_1::tree::LeafManager::LeafManager
LeafManager(TreeType &tree, size_t auxBuffersPerLeaf=0, bool serial=false)
Constructor from a tree reference and an auxiliary buffer count.
Definition: LeafManager.h:192
openvdb::v8_1::tree::LeafManager::auxBuffersPerLeaf
size_t auxBuffersPerLeaf() const
Return the number of auxiliary buffers per leaf node.
Definition: LeafManager.h:284
openvdb::v8_1::tree::LeafManager::NonConstLeafType
typename TreeType::LeafNodeType NonConstLeafType
Definition: LeafManager.h:90
openvdb::v8_1::tree::LeafManager::LeafManager
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:204
openvdb::v8_1::tree::LeafManager::rebuildLeafArray
void rebuildLeafArray(bool serial=false)
Remove the auxiliary buffers and rebuild the leaf array.
Definition: LeafManager.h:275
openvdb::v8_1::tree::LeafManager::tree
TreeType & tree()
Return a reference to the tree associated with this manager.
Definition: LeafManager.h:305
openvdb::v8_1::tree::LeafManager::leafCount
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:287
openvdb::v8_1::tree::LeafManager::rebuild
void rebuild(TreeType &tree, size_t auxBuffersPerLeaf, bool serial=false)
Definition: LeafManager.h:255
openvdb::v8_1::tree::LeafManager::RangeType
tbb::blocked_range< size_t > RangeType
Definition: LeafManager.h:96
openvdb::v8_1::tree::LeafManager::tree
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:302
openvdb::v8_1::tree::LeafManager::getBuffer
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:330
openvdb::v8_1::tree::LeafManager::leaf
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:318
openvdb::v8_1::tree::LeafManager::NonConstBufferType
typename LeafType::Buffer NonConstBufferType
Definition: LeafManager.h:94
openvdb::v8_1::tree::LeafManager::leafRange
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
openvdb::v8_1::tree::LeafManager::root
const RootNodeType & root() const
Return a const reference to root node associated with this manager.
Definition: LeafManager.h:308
openvdb::v8_1::tree::LeafManager::TreeType
TreeT TreeType
Definition: LeafManager.h:87
openvdb::v8_1::tree::LeafManager::LeafType
typename CopyConstness< TreeType, NonConstLeafType >::Type LeafType
Definition: LeafManager.h:91
openvdb::v8_1::tree::LeafManager::activeLeafVoxelCount
Index64 activeLeafVoxelCount() const
Return the number of active voxels in the leaf nodes.
Definition: LeafManager.h:291
openvdb::v8_1::tree::LeafManager::LeafNodeType
LeafType LeafNodeType
Definition: LeafManager.h:92
openvdb::v8_1::tree::LeafManager::removeAuxBuffers
void removeAuxBuffers()
Remove the auxiliary buffers, but don't rebuild the leaf array.
Definition: LeafManager.h:272
openvdb::v8_1::ax::run
void run(const char *ax, openvdb::GridBase &grid)
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
openvdb::v8_1::math::operator*
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:611
openvdb::v8_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
openvdb::v8_1::tools::composite::min
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
openvdb::v8_1::Index
Index32 Index
Definition: openvdb/Types.h:50
openvdb::v8_1::Index64
uint64_t Index64
Definition: openvdb/Types.h:49
openvdb
Definition: openvdb/Exceptions.h:13
std
Definition: Coord.h:587
tbb
Definition: Coord.h:16
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
Types.h
openvdb::v8_1::CopyConstness::Type
typename std::remove_const< ToType >::type Type
Definition: openvdb/Types.h:317
openvdb::v8_1::tree::LeafManagerImpl< LeafManager< const TreeT > >::LeafT
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:855
openvdb::v8_1::tree::LeafManagerImpl< LeafManager< const TreeT > >::RangeT
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:854
openvdb::v8_1::tree::LeafManagerImpl< LeafManager< const TreeT > >::BufT
typename ManagerT::BufferType BufT
Definition: LeafManager.h:856
openvdb::v8_1::tree::LeafManagerImpl< LeafManager< const TreeT > >::doSwapLeafBuffer
static void doSwapLeafBuffer(const RangeT &, size_t, LeafT **, BufT *, size_t)
Definition: LeafManager.h:858
openvdb::v8_1::tree::LeafManagerImpl
Definition: LeafManager.h:54
openvdb::v8_1::tree::LeafManagerImpl::doSwapLeafBuffer
static void doSwapLeafBuffer(const RangeT &r, size_t auxBufferIdx, LeafT **leafs, BufT *bufs, size_t bufsPerLeaf)
Definition: LeafManager.h:59
openvdb::v8_1::tree::LeafManagerImpl::LeafT
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:56
openvdb::v8_1::tree::LeafManagerImpl::RangeT
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:55
openvdb::v8_1::tree::LeafManagerImpl::BufT
typename ManagerT::BufferType BufT
Definition: LeafManager.h:57
openvdb::v8_1::tree::NodeChain::Type
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:998
openvdb::v8_1::tree::leafmgr::TreeTraits< const TreeT >::LeafIterType
typename TreeT::LeafCIter LeafIterType
Definition: LeafManager.h:43
openvdb::v8_1::tree::leafmgr::TreeTraits
Useful traits for Tree types.
Definition: LeafManager.h:37
openvdb::v8_1::tree::leafmgr::TreeTraits::LeafIterType
typename TreeT::LeafIter LeafIterType
Definition: LeafManager.h:39
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:178