OpenVDB  7.2.1
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 {
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>
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>
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;
94  using NonConstBufferType = typename LeafType::Buffer;
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 
233  virtual ~LeafManager() { }
234 
240  void rebuild(bool serial=false)
241  {
242  this->initLeafArray(serial);
243  this->initAuxBuffers(serial);
244  }
246  void rebuild(size_t auxBuffersPerLeaf, bool serial=false)
248  {
249  mAuxBuffersPerLeaf = auxBuffersPerLeaf;
250  this->rebuild(serial);
251  }
252  void rebuild(TreeType& tree, bool serial=false)
253  {
254  mTree = &tree;
255  this->rebuild(serial);
256  }
257  void rebuild(TreeType& tree, size_t auxBuffersPerLeaf, bool serial=false)
258  {
259  mTree = &tree;
260  mAuxBuffersPerLeaf = auxBuffersPerLeaf;
261  this->rebuild(serial);
262  }
264  void rebuildAuxBuffers(size_t auxBuffersPerLeaf, bool serial=false)
269  {
270  mAuxBuffersPerLeaf = auxBuffersPerLeaf;
271  this->initAuxBuffers(serial);
272  }
274  void removeAuxBuffers() { this->rebuildAuxBuffers(0); }
275 
277  void rebuildLeafArray(bool serial = false)
278  {
279  this->removeAuxBuffers();
280  this->initLeafArray(serial);
281  }
282 
284  size_t auxBufferCount() const { return mAuxBufferCount; }
286  size_t auxBuffersPerLeaf() const { return mAuxBuffersPerLeaf; }
287 
289  size_t leafCount() const { return mLeafCount; }
290 
294  {
295  return tbb::parallel_reduce(this->leafRange(), Index64(0),
296  [] (const LeafRange& range, Index64 sum) -> Index64 {
297  for (const auto& leaf: range) { sum += leaf.onVoxelCount(); }
298  return sum;
299  },
300  [] (Index64 n, Index64 m) -> Index64 { return n + m; });
301  }
302 
304  const TreeType& tree() const { return *mTree; }
305 
307  TreeType& tree() { return *mTree; }
308 
310  const RootNodeType& root() const { return mTree->root(); }
311 
313  RootNodeType& root() { return mTree->root(); }
314 
316  bool isConstTree() const { return this->IsConstTree; }
317 
320  LeafType& leaf(size_t leafIdx) const { assert(leafIdx<mLeafCount); return *mLeafs[leafIdx]; }
321 
332  BufferType& getBuffer(size_t leafIdx, size_t bufferIdx) const
333  {
334  assert(leafIdx < mLeafCount);
335  assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
336  return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
337  : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
338  }
339 
344  RangeType getRange(size_t grainsize = 1) const { return RangeType(0, mLeafCount, grainsize); }
345 
347  LeafRange leafRange(size_t grainsize = 1) const
348  {
349  return LeafRange(0, mLeafCount, *this, grainsize);
350  }
351 
361  bool swapLeafBuffer(size_t bufferIdx, bool serial = false)
362  {
363  namespace ph = std::placeholders;
364  if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree()) return false;
365  mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, bufferIdx - 1);
366  this->cook(serial ? 0 : 512);
367  return true;//success
368  }
373  bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial = false)
374  {
375  namespace ph = std::placeholders;
376  const size_t b1 = std::min(bufferIdx1, bufferIdx2);
377  const size_t b2 = std::max(bufferIdx1, bufferIdx2);
378  if (b1 == b2 || b2 > mAuxBuffersPerLeaf) return false;
379  if (b1 == 0) {
380  if (this->isConstTree()) return false;
381  mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, b2-1);
382  } else {
383  mTask = std::bind(&LeafManager::doSwapAuxBuffer, ph::_1, ph::_2, b1-1, b2-1);
384  }
385  this->cook(serial ? 0 : 512);
386  return true;//success
387  }
388 
397  bool syncAuxBuffer(size_t bufferIdx, bool serial = false)
398  {
399  namespace ph = std::placeholders;
400  if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf) return false;
401  mTask = std::bind(&LeafManager::doSyncAuxBuffer, ph::_1, ph::_2, bufferIdx - 1);
402  this->cook(serial ? 0 : 64);
403  return true;//success
404  }
405 
409  bool syncAllBuffers(bool serial = false)
410  {
411  namespace ph = std::placeholders;
412  switch (mAuxBuffersPerLeaf) {
413  case 0: return false;//nothing to do
414  case 1: mTask = std::bind(&LeafManager::doSyncAllBuffers1, ph::_1, ph::_2); break;
415  case 2: mTask = std::bind(&LeafManager::doSyncAllBuffers2, ph::_1, ph::_2); break;
416  default: mTask = std::bind(&LeafManager::doSyncAllBuffersN, ph::_1, ph::_2); break;
417  }
418  this->cook(serial ? 0 : 64);
419  return true;//success
420  }
421 
484  template<typename LeafOp>
485  void foreach(const LeafOp& op, bool threaded = true, size_t grainSize=1)
486  {
487  LeafTransformer<LeafOp> transform(op);
488  transform.run(this->leafRange(grainSize), threaded);
489  }
490 
533  template<typename LeafOp>
534  void reduce(LeafOp& op, bool threaded = true, size_t grainSize=1)
535  {
536  LeafReducer<LeafOp> transform(op);
537  transform.run(this->leafRange(grainSize), threaded);
538  }
539 
540  template<typename ArrayT>
541  [[deprecated("Use Tree::getNodes()")]] void getNodes(ArrayT& array)
542  {
543  using T = typename ArrayT::value_type;
544  static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array");
545  using LeafT = typename std::conditional<std::is_const<
546  typename std::remove_pointer<T>::type>::value, const LeafType, LeafType>::type;
547 
549  if (std::is_same<T, LeafT*>::value) {
550  array.resize(mLeafCount);
551  for (size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
552  } else {
553  mTree->getNodes(array);
554  }
556  }
557 
558  template<typename ArrayT>
559  [[deprecated("Use Tree::getNodes()")]] void getNodes(ArrayT& array) const
560  {
561  using T = typename ArrayT::value_type;
562  static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array");
563  static_assert(std::is_const<typename std::remove_pointer<T>::type>::value,
564  "argument to getNodes() must be an array of const node pointers");
565 
567  if (std::is_same<T, const LeafType*>::value) {
568  array.resize(mLeafCount);
569  for (size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
570  } else {
571  mTree->getNodes(array);
572  }
574  }
575 
587  size_t getPrefixSum(size_t*& offsets, size_t& size, size_t grainSize=1) const
588  {
589  if (offsets == nullptr || size < mLeafCount) {
590  delete [] offsets;
591  offsets = new size_t[mLeafCount];
592  size = mLeafCount;
593  }
594  size_t prefix = 0;
595  if ( grainSize > 0 ) {
596  PrefixSum tmp(this->leafRange( grainSize ), offsets, prefix);
597  } else {// serial
598  for (size_t i=0; i<mLeafCount; ++i) {
599  offsets[i] = prefix;
600  prefix += mLeafs[i]->onVoxelCount();
601  }
602  }
603  return prefix;
604  }
605 
607  // All methods below are for internal use only and should never be called directly
608 
610  void operator()(const RangeType& r) const
611  {
612  if (mTask) mTask(const_cast<LeafManager*>(this), r);
613  else OPENVDB_THROW(ValueError, "task is undefined");
614  }
615 
616 private:
617 
618  void initLeafArray(bool serial = false)
619  {
620  // Build an array of all nodes that have leaf nodes as their immediate children
621 
622  using NodeChainT = typename NodeChain<RootNodeType, RootNodeType::LEVEL>::Type;
623  using NonConstLeafParentT = typename NodeChainT::template Get</*Level=*/1>;
624  using LeafParentT = typename CopyConstness<TreeType, NonConstLeafParentT>::Type;
625 
626  std::deque<LeafParentT*> leafParents;
627  mTree->getNodes(leafParents);
628 
629  // Compute the leaf counts for each node
630 
631  std::vector<Index32> leafCounts;
632  if (serial) {
633  leafCounts.reserve(leafParents.size());
634  for (LeafParentT* leafParent : leafParents) {
635  leafCounts.push_back(leafParent->childCount());
636  }
637  } else {
638  leafCounts.resize(leafParents.size());
639  tbb::parallel_for(
640  // with typical node sizes and SSE enabled, there are only a handful
641  // of instructions executed per-operation with a default grainsize
642  // of 1, so increase to 64 to reduce parallel scheduling overhead
643  tbb::blocked_range<size_t>(0, leafParents.size(), /*grainsize=*/64),
644  [&](tbb::blocked_range<size_t>& range)
645  {
646  for (size_t i = range.begin(); i < range.end(); i++) {
647  leafCounts[i] = leafParents[i]->childCount();
648  }
649  }
650  );
651  }
652 
653  // Turn leaf counts into a cumulative histogram and obtain total leaf count
654 
655  for (size_t i = 1; i < leafCounts.size(); i++) {
656  leafCounts[i] += leafCounts[i-1];
657  }
658 
659  const size_t leafCount = leafCounts.empty() ? 0 : leafCounts.back();
660 
661  // Allocate (or deallocate) the leaf pointer array
662 
663  if (leafCount != mLeafCount) {
664  if (leafCount > 0) {
665  mLeafPtrs.reset(new LeafType*[leafCount]);
666  mLeafs = mLeafPtrs.get();
667  } else {
668  mLeafPtrs.reset();
669  mLeafs = nullptr;
670  }
671  mLeafCount = leafCount;
672  }
673 
674  if (mLeafCount == 0) return;
675 
676  // Populate the leaf node pointers
677 
678  if (serial) {
679  LeafType** leafPtr = mLeafs;
680  for (LeafParentT* leafParent : leafParents) {
681  for (auto iter = leafParent->beginChildOn(); iter; ++iter) {
682  *leafPtr++ = &iter.getValue();
683  }
684  }
685  } else {
686  tbb::parallel_for(
687  tbb::blocked_range<size_t>(0, leafParents.size()),
688  [&](tbb::blocked_range<size_t>& range)
689  {
690  size_t i = range.begin();
691  LeafType** leafPtr = mLeafs;
692  if (i > 0) leafPtr += leafCounts[i-1];
693  for ( ; i < range.end(); i++) {
694  for (auto iter = leafParents[i]->beginChildOn(); iter; ++iter) {
695  *leafPtr++ = &iter.getValue();
696  }
697  }
698  }
699  );
700  }
701  }
702 
703  void initAuxBuffers(bool serial)
704  {
705  const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
706  if (auxBufferCount != mAuxBufferCount) {
707  if (auxBufferCount > 0) {
708  mAuxBufferPtrs.reset(new NonConstBufferType[auxBufferCount]);
709  mAuxBuffers = mAuxBufferPtrs.get();
710  } else {
711  mAuxBufferPtrs.reset();
712  mAuxBuffers = nullptr;
713  }
714  mAuxBufferCount = auxBufferCount;
715  }
716  this->syncAllBuffers(serial);
717  }
718 
719  void cook(size_t grainsize)
720  {
721  if (grainsize>0) {
722  tbb::parallel_for(this->getRange(grainsize), *this);
723  } else {
724  (*this)(this->getRange());
725  }
726  }
727 
728  void doSwapLeafBuffer(const RangeType& r, size_t auxBufferIdx)
729  {
730  LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
731  r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
732  }
733 
734  void doSwapAuxBuffer(const RangeType& r, size_t auxBufferIdx1, size_t auxBufferIdx2)
735  {
736  for (size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
737  mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
738  }
739  }
740 
741  void doSyncAuxBuffer(const RangeType& r, size_t auxBufferIdx)
742  {
743  for (size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
744  mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
745  }
746  }
747 
748  void doSyncAllBuffers1(const RangeType& r)
749  {
750  for (size_t n = r.begin(), m = r.end(); n != m; ++n) {
751  mAuxBuffers[n] = mLeafs[n]->buffer();
752  }
753  }
754 
755  void doSyncAllBuffers2(const RangeType& r)
756  {
757  for (size_t n = r.begin(), m = r.end(); n != m; ++n) {
758  const BufferType& leafBuffer = mLeafs[n]->buffer();
759  mAuxBuffers[2*n ] = leafBuffer;
760  mAuxBuffers[2*n+1] = leafBuffer;
761  }
762  }
763 
764  void doSyncAllBuffersN(const RangeType& r)
765  {
766  for (size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
767  const BufferType& leafBuffer = mLeafs[n]->buffer();
768  for (size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
769  }
770  }
771 
774  template<typename LeafOp>
775  struct LeafTransformer
776  {
777  LeafTransformer(const LeafOp &leafOp) : mLeafOp(leafOp)
778  {
779  }
780  void run(const LeafRange &range, bool threaded) const
781  {
782  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
783  }
784  void operator()(const LeafRange &range) const
785  {
786  for (typename LeafRange::Iterator it = range.begin(); it; ++it) mLeafOp(*it, it.pos());
787  }
788  const LeafOp mLeafOp;
789  };// LeafTransformer
790 
793  template<typename LeafOp>
794  struct LeafReducer
795  {
796  LeafReducer(LeafOp &leafOp) : mLeafOp(&leafOp)
797  {
798  }
799  LeafReducer(const LeafReducer &other, tbb::split)
800  : mLeafOpPtr(std::make_unique<LeafOp>(*(other.mLeafOp), tbb::split()))
801  , mLeafOp(mLeafOpPtr.get())
802  {
803  }
804  void run(const LeafRange& range, bool threaded)
805  {
806  threaded ? tbb::parallel_reduce(range, *this) : (*this)(range);
807  }
808  void operator()(const LeafRange& range)
809  {
810  LeafOp &op = *mLeafOp;//local registry
811  for (typename LeafRange::Iterator it = range.begin(); it; ++it) op(*it, it.pos());
812  }
813  void join(const LeafReducer& other) { mLeafOp->join(*(other.mLeafOp)); }
814  std::unique_ptr<LeafOp> mLeafOpPtr;
815  LeafOp *mLeafOp = nullptr;
816  };// LeafReducer
817 
818  // Helper class to compute a prefix sum of offsets to active voxels
819  struct PrefixSum
820  {
821  PrefixSum(const LeafRange& r, size_t* offsets, size_t& prefix)
822  : mOffsets(offsets)
823  {
824  tbb::parallel_for( r, *this);
825  for (size_t i=0, leafCount = r.size(); i<leafCount; ++i) {
826  size_t tmp = offsets[i];
827  offsets[i] = prefix;
828  prefix += tmp;
829  }
830  }
831  inline void operator()(const LeafRange& r) const {
832  for (typename LeafRange::Iterator i = r.begin(); i; ++i) {
833  mOffsets[i.pos()] = i->onVoxelCount();
834  }
835  }
836  size_t* mOffsets;
837  };// PrefixSum
838 
839  using FuncType = typename std::function<void (LeafManager*, const RangeType&)>;
840 
841  TreeType* mTree;
842  size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
843  std::unique_ptr<LeafType*[]> mLeafPtrs;
844  LeafType** mLeafs = nullptr;//array of LeafNode pointers
845  std::unique_ptr<NonConstBufferType[]> mAuxBufferPtrs;
846  NonConstBufferType* mAuxBuffers = nullptr;//array of auxiliary buffers
847  FuncType mTask = nullptr;
848 };//end of LeafManager class
849 
850 
851 // Partial specializations of LeafManager methods for const trees
852 template<typename TreeT>
853 struct LeafManagerImpl<LeafManager<const TreeT> >
854 {
856  using RangeT = typename ManagerT::RangeType;
857  using LeafT = typename ManagerT::LeafType;
858  using BufT = typename ManagerT::BufferType;
859 
860  static inline void doSwapLeafBuffer(const RangeT&, size_t /*auxBufferIdx*/,
861  LeafT**, BufT*, size_t /*bufsPerLeaf*/)
862  {
863  // Buffers can't be swapped into const trees.
864  }
865 };
866 
867 } // namespace tree
868 } // namespace OPENVDB_VERSION_NAME
869 } // namespace openvdb
870 
871 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
openvdb::v7_2::tree::LeafManager::getRange
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:344
Types.h
openvdb::v7_2::tree::LeafManager::removeAuxBuffers
void removeAuxBuffers()
Remove the auxiliary buffers, but don't rebuild the leaf array.
Definition: LeafManager.h:274
openvdb::v7_2::tree::LeafManager::activeLeafVoxelCount
Index64 activeLeafVoxelCount() const
Return the number of active voxels in the leaf nodes.
Definition: LeafManager.h:293
RootNode.h
The root node of an OpenVDB tree.
openvdb::v7_2::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:361
openvdb::v7_2::tree::leafmgr::TreeTraits::LeafIterType
typename TreeT::LeafIter LeafIterType
Definition: LeafManager.h:39
openvdb::v7_2::tree::LeafManager::LeafRange::grainsize
size_t grainsize() const
Definition: LeafManager.h:161
openvdb::v7_2::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:534
openvdb::v7_2::tree::LeafManager::getNodes
void getNodes(ArrayT &array)
Definition: LeafManager.h:541
openvdb::v7_2::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::v7_2::tree::LeafManager::NonConstLeafType
typename TreeType::LeafNodeType NonConstLeafType
Definition: LeafManager.h:90
openvdb::v7_2::tree::LeafManagerImpl< LeafManager< const TreeT > >::doSwapLeafBuffer
static void doSwapLeafBuffer(const RangeT &, size_t, LeafT **, BufT *, size_t)
Definition: LeafManager.h:860
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator
Definition: LeafManager.h:105
openvdb::v7_2::tree::LeafManager::leafRange
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:347
openvdb::v7_2::tree::LeafManager::BufferType
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:95
openvdb::v7_2::tree::LeafManager::TreeType
TreeT TreeType
Definition: LeafManager.h:87
openvdb::v7_2::tree::LeafManager::NonConstBufferType
typename LeafType::Buffer NonConstBufferType
Definition: LeafManager.h:94
openvdb::v7_2::tree::LeafManager::LeafRange::begin
Iterator begin() const
Definition: LeafManager.h:155
openvdb::v7_2::tools::composite::min
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
tbb
Definition: Coord.h:16
openvdb::v7_2::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::v7_2::tree::LeafManager::tree
TreeType & tree()
Return a reference to the tree associated with this manager.
Definition: LeafManager.h:307
openvdb::v7_2::tree::LeafManager::syncAllBuffers
bool syncAllBuffers(bool serial=false)
Sync up all auxiliary buffers with their corresponding leaf node buffers.
Definition: LeafManager.h:409
openvdb::v7_2::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::v7_2::tree::LeafManager::LeafIterType
typename leafmgr::TreeTraits< TreeT >::LeafIterType LeafIterType
Definition: LeafManager.h:93
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:82
openvdb::v7_2::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::v7_2::tree::LeafManager::auxBufferCount
size_t auxBufferCount() const
Return the total number of allocated auxiliary buffers.
Definition: LeafManager.h:284
openvdb::v7_2::tree::LeafManager::rebuild
void rebuild(TreeType &tree, size_t auxBuffersPerLeaf, bool serial=false)
Definition: LeafManager.h:257
openvdb::v7_2::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
openvdb::v7_2::tree::LeafManager::LeafRange::leafManager
const LeafManager & leafManager() const
Definition: LeafManager.h:163
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::Iterator
Iterator(const Iterator &)=default
openvdb::v7_2::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:320
openvdb::v7_2::tree::LeafManager::RangeType
tbb::blocked_range< size_t > RangeType
Definition: LeafManager.h:96
openvdb::v7_2::Index64
uint64_t Index64
Definition: openvdb/Types.h:31
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::operator=
Iterator & operator=(const Iterator &)=default
openvdb::v7_2::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:397
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::operator!=
bool operator!=(const Iterator &other) const
Definition: LeafManager.h:135
openvdb::v7_2::tree::LeafManager::LeafRange::LeafRange
LeafRange(size_t begin, size_t end, const LeafManager &leafManager, size_t grainSize=1)
Definition: LeafManager.h:147
openvdb::v7_2::tree::LeafManager::RootNodeType
typename TreeT::RootNodeType RootNodeType
Definition: LeafManager.h:89
openvdb::v7_2::tree::LeafManager::tree
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:304
openvdb::v7_2::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:332
openvdb::v7_2::tree::LeafManagerImpl< LeafManager< const TreeT > >::RangeT
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:856
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::test
bool test() const
Return true if this iterator is not yet exhausted.
Definition: LeafManager.h:130
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::operator==
bool operator==(const Iterator &other) const
Definition: LeafManager.h:139
openvdb::v7_2::tree::LeafManagerImpl::LeafT
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:56
openvdb::v7_2::tree::LeafManager::rebuild
void rebuild(TreeType &tree, bool serial=false)
Definition: LeafManager.h:252
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::operator++
Iterator & operator++()
Advance to the next leaf node.
Definition: LeafManager.h:114
openvdb::v7_2::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:240
openvdb::v7_2::tree::LeafManager::LeafRange::size
size_t size() const
Definition: LeafManager.h:159
OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:105
openvdb::v7_2::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::v7_2::tree::leafmgr::TreeTraits< const TreeT >::LeafIterType
typename TreeT::LeafCIter LeafIterType
Definition: LeafManager.h:43
openvdb::v7_2::tree::LeafManager::ValueType
typename TreeT::ValueType ValueType
Definition: LeafManager.h:88
openvdb::v7_2::tree::LeafManager::~LeafManager
virtual ~LeafManager()
Definition: LeafManager.h:233
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:147
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::leafRange
const LeafRange & leafRange() const
Definition: LeafManager.h:140
openvdb::v7_2::tree::LeafManagerImpl::doSwapLeafBuffer
static void doSwapLeafBuffer(const RangeT &r, size_t auxBufferIdx, LeafT **leafs, BufT *bufs, size_t bufsPerLeaf)
Definition: LeafManager.h:59
openvdb::v7_2::tree::leafmgr::TreeTraits
Useful traits for Tree types.
Definition: LeafManager.h:37
std
Definition: Coord.h:587
openvdb::v7_2::CopyConstness::Type
typename std::remove_const< ToType >::type Type
Definition: openvdb/Types.h:299
openvdb::v7_2::tree::LeafManager::LeafNodeType
LeafType LeafNodeType
Definition: LeafManager.h:92
openvdb::v7_2::tree::LeafManager::LeafRange::end
Iterator end() const
Definition: LeafManager.h:157
openvdb::v7_2::tree::LeafManager::operator()
void operator()(const RangeType &r) const
Used internally by tbb::parallel_for() - never call it directly!
Definition: LeafManager.h:610
openvdb::v7_2::tree::LeafManagerImpl::BufT
typename ManagerT::BufferType BufT
Definition: LeafManager.h:57
openvdb::v7_2::tree::LeafManager::LeafRange::empty
bool empty() const
Definition: LeafManager.h:165
openvdb::v7_2::tree::LeafManagerImpl< LeafManager< const TreeT > >::BufT
typename ManagerT::BufferType BufT
Definition: LeafManager.h:858
openvdb::v7_2::tree::LeafManager::isConstTree
bool isConstTree() const
Return true if the tree associated with this manager is immutable.
Definition: LeafManager.h:316
openvdb::v7_2::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:587
openvdb::v7_2::tree::LeafManager::LeafManager
LeafManager(const LeafManager &other)
Definition: LeafManager.h:222
openvdb::v7_2::tree::LeafManager::LeafRange::Iterator::Iterator
Iterator(const LeafRange &range, size_t pos)
Definition: LeafManager.h:107
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:95
openvdb::v7_2::tree::LeafManager::LeafType
typename CopyConstness< TreeType, NonConstLeafType >::Type LeafType
Definition: LeafManager.h:91
OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:106
openvdb::v7_2::tree::LeafManager::root
RootNodeType & root()
Return a reference to the root node associated with this manager.
Definition: LeafManager.h:313
openvdb::v7_2::tree::LeafManager::rebuildLeafArray
void rebuildLeafArray(bool serial=false)
Remove the auxiliary buffers and rebuild the leaf array.
Definition: LeafManager.h:277
openvdb::v7_2::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::v7_2::tree::LeafManager::LeafRange::Iterator::empty
bool empty() const
Return true if this iterator is exhausted.
Definition: LeafManager.h:134
openvdb::v7_2::tree::NodeChain::Type
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:993
openvdb::v7_2::tree::LeafManager::LeafRange::LeafRange
LeafRange(LeafRange &r, tbb::split)
Definition: LeafManager.h:169
openvdb::v7_2::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::v7_2::ValueError
Definition: openvdb/Exceptions.h:65
openvdb::v7_2::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::v7_2::tree::LeafManager::auxBuffersPerLeaf
size_t auxBuffersPerLeaf() const
Return the number of auxiliary buffers per leaf node.
Definition: LeafManager.h:286
openvdb
Definition: openvdb/Exceptions.h:13
openvdb::v7_2::tree::LeafManager::LeafRange
Definition: LeafManager.h:102
openvdb::v7_2::tree::LeafManagerImpl
Definition: LeafManager.h:54
openvdb::v7_2::tree::LeafManager::getNodes
void getNodes(ArrayT &array) const
Definition: LeafManager.h:559
openvdb::v7_2::tree::LeafManagerImpl::RangeT
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:55
openvdb::v7_2::tree::LeafManager::leafCount
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:289
openvdb::v7_2::Index
Index32 Index
Definition: openvdb/Types.h:32
openvdb::v7_2::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:373
openvdb::v7_2::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::v7_2::tree::LeafManager::root
const RootNodeType & root() const
Return a const reference to root node associated with this manager.
Definition: LeafManager.h:310
openvdb::v7_2::tree::LeafManager::LeafRange::is_divisible
bool is_divisible() const
Definition: LeafManager.h:167
openvdb::v7_2::tree::LeafManagerImpl< LeafManager< const TreeT > >::LeafT
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:857
openvdb::v7_2::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:604