15#ifndef OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED 
   16#define OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED 
   21#include <tbb/blocked_range.h> 
   22#include <tbb/parallel_for.h> 
   23#include <tbb/parallel_reduce.h> 
   53template<
typename ManagerT>
 
   56    using RangeT = 
typename ManagerT::RangeType;
 
   57    using LeafT = 
typename ManagerT::LeafType;
 
   58    using BufT = 
typename ManagerT::BufferType;
 
   61                                        LeafT** leafs, 
BufT* bufs, 
size_t bufsPerLeaf)
 
   63        for (
size_t n = r.begin(), m = r.end(), N = bufsPerLeaf; n != m; ++n) {
 
   64            leafs[n]->swap(bufs[n * N + auxBufferIdx]);
 
 
 
   84template<
typename TreeT>
 
  124                return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
 
 
  127            size_t pos()
 const { 
return mPos; }
 
  129            bool isValid()
 const { 
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
 
  131            bool test()
 const { 
return mPos < mRange.mEnd; }
 
  133            operator bool()
 const { 
return this->
test(); }
 
  138                return (mPos != other.mPos) || (&mRange != &other.mRange);
 
 
 
  151            , mGrainSize(grainSize)
 
 
  160        size_t size()
 const { 
return mEnd - mBegin; }
 
  166        bool empty()
 const {
return !(mBegin < mEnd);}
 
  173            , mGrainSize(r.mGrainSize)
 
  174            , mLeafManager(r.mLeafManager)
 
 
  179        size_t mEnd, mBegin, mGrainSize;
 
  185            size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
 
 
  208        , mLeafCount(end-begin)
 
  211        , mLeafPtrs(new 
LeafType*[mLeafCount])
 
  212        , mLeafs(mLeafPtrs.get())
 
  214        size_t n = mLeafCount;
 
  215        LeafType **target = mLeafs, **source = begin;
 
  216        while (n--) *target++ = *source++;
 
 
  225        , mLeafCount(other.mLeafCount)
 
  226        , mAuxBufferCount(other.mAuxBufferCount)
 
  227        , mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf)
 
  228        , mLeafs(other.mLeafs)
 
  229        , mAuxBuffers(other.mAuxBuffers)
 
 
  241        this->initLeafArray(serial);
 
  242        this->initAuxBuffers(serial);
 
 
  270        this->initAuxBuffers(serial);
 
 
  279        this->initLeafArray(serial);
 
 
  296                for (
const auto& 
leaf: range) { sum += 
leaf.onVoxelCount(); }
 
 
  334        OPENVDB_ASSERT(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
 
  335        return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
 
  336             : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
 
 
  348        return LeafRange(0, mLeafCount, *
this, grainsize);
 
 
  362        namespace ph = std::placeholders;
 
  363        if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->
isConstTree()) 
return false;
 
  364        mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, bufferIdx - 1);
 
  365        this->cook(serial ? 0 : 512);
 
 
  372    bool swapBuffer(
size_t bufferIdx1, 
size_t bufferIdx2, 
bool serial = 
false)
 
  374        namespace ph = std::placeholders;
 
  375        const size_t b1 = std::min(bufferIdx1, bufferIdx2);
 
  376        const size_t b2 = std::max(bufferIdx1, bufferIdx2);
 
  377        if (b1 == b2 || b2 > mAuxBuffersPerLeaf) 
return false;
 
  380            mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, b2-1);
 
  382            mTask = std::bind(&LeafManager::doSwapAuxBuffer, ph::_1, ph::_2, b1-1, b2-1);
 
  384        this->cook(serial ? 0 : 512);
 
 
  398        namespace ph = std::placeholders;
 
  399        if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf) 
return false;
 
  400        mTask = std::bind(&LeafManager::doSyncAuxBuffer, ph::_1, ph::_2, bufferIdx - 1);
 
  401        this->cook(serial ? 0 : 64);
 
 
  410        namespace ph = std::placeholders;
 
  411        switch (mAuxBuffersPerLeaf) {
 
  412            case 0: 
return false;
 
  413            case 1: mTask = std::bind(&LeafManager::doSyncAllBuffers1, ph::_1, ph::_2); 
break;
 
  414            case 2: mTask = std::bind(&LeafManager::doSyncAllBuffers2, ph::_1, ph::_2); 
break;
 
  415            default: mTask = std::bind(&LeafManager::doSyncAllBuffersN, ph::_1, ph::_2); 
break;
 
  417        this->cook(serial ? 0 : 64);
 
 
  483    template<
typename LeafOp>
 
  484    void foreach(
const LeafOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
 
  486        LeafTransformer<LeafOp> transform(op);
 
  487        transform.run(this->
leafRange(grainSize), threaded);
 
 
  532    template<
typename LeafOp>
 
  533    void reduce(LeafOp& op, 
bool threaded = 
true, 
size_t grainSize=1)
 
  535        LeafReducer<LeafOp> transform(op);
 
  536        transform.run(this->
leafRange(grainSize), threaded);
 
 
  550    size_t getPrefixSum(
size_t*& offsets, 
size_t& size, 
size_t grainSize=1)
 const 
  552        if (offsets == 
nullptr || size < mLeafCount) {
 
  554            offsets = 
new size_t[mLeafCount];
 
  558        if ( grainSize > 0 ) {
 
  559            PrefixSum tmp(this->
leafRange( grainSize ), offsets, prefix);
 
  561            for (
size_t i=0; i<mLeafCount; ++i) {
 
  563                prefix += mLeafs[i]->onVoxelCount();
 
 
  575        if (mTask) mTask(
const_cast<LeafManager*
>(
this), r);
 
 
  581    void initLeafArray(
bool serial = 
false)
 
  586        using NonConstLeafParentT = 
typename NodeChainT::template Get<1>;
 
  589        std::deque<LeafParentT*> leafParents;
 
  590        if constexpr(std::is_same<NonConstLeafParentT, RootNodeType>::value) {
 
  591            leafParents.emplace_back(&mTree->root());
 
  594            mTree->getNodes(leafParents);
 
  599        std::vector<Index64> leafCounts;
 
  601            leafCounts.reserve(leafParents.size());
 
  602            for (LeafParentT* leafParent : leafParents) {
 
  603                leafCounts.push_back(leafParent->childCount());
 
  606            leafCounts.resize(leafParents.size());
 
  611                tbb::blocked_range<size_t>(0, leafParents.size(), 64),
 
  612                [&](tbb::blocked_range<size_t>& range)
 
  614                    for (size_t i = range.begin(); i < range.end(); i++) {
 
  615                        leafCounts[i] = leafParents[i]->childCount();
 
  623        for (
size_t i = 1; i < leafCounts.size(); i++) {
 
  624            leafCounts[i] += leafCounts[i-1];
 
  627        const size_t leafCount = leafCounts.empty() ? 0 : leafCounts.back();
 
  631        if (leafCount != mLeafCount) {
 
  633                mLeafPtrs.reset(
new LeafType*[leafCount]);
 
  634                mLeafs = mLeafPtrs.get();
 
  639            mLeafCount = leafCount;
 
  642        if (mLeafCount == 0)    
return;
 
  647            LeafType** leafPtr = mLeafs;
 
  648            for (LeafParentT* leafParent : leafParents) {
 
  649                for (
auto iter = leafParent->beginChildOn(); iter; ++iter) {
 
  650                    *leafPtr++ = &iter.getValue();
 
  655                tbb::blocked_range<size_t>(0, leafParents.size()),
 
  656                [&](tbb::blocked_range<size_t>& range)
 
  658                    size_t i = range.begin();
 
  659                    LeafType** leafPtr = mLeafs;
 
  660                    if (i > 0)  leafPtr += leafCounts[i-1];
 
  661                    for ( ; i < range.end(); i++) {
 
  662                        for (auto iter = leafParents[i]->beginChildOn(); iter; ++iter) {
 
  663                            *leafPtr++ = &iter.getValue();
 
  671    void initAuxBuffers(
bool serial)
 
  673        const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
 
  674        if (auxBufferCount != mAuxBufferCount) {
 
  675            if (auxBufferCount > 0) {
 
  676                mAuxBufferPtrs.reset(
new NonConstBufferType[auxBufferCount]);
 
  677                mAuxBuffers = mAuxBufferPtrs.get();
 
  679                mAuxBufferPtrs.reset();
 
  680                mAuxBuffers = 
nullptr;
 
  682            mAuxBufferCount = auxBufferCount;
 
  684        this->syncAllBuffers(serial);
 
  687    void cook(
size_t grainsize)
 
  690            tbb::parallel_for(this->getRange(grainsize), *
this);
 
  692            (*this)(this->getRange());
 
  696    void doSwapLeafBuffer(
const RangeType& r, 
size_t auxBufferIdx)
 
  698        LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
 
  699            r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
 
  702    void doSwapAuxBuffer(
const RangeType& r, 
size_t auxBufferIdx1, 
size_t auxBufferIdx2)
 
  704        for (
size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
 
  705            mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
 
  709    void doSyncAuxBuffer(
const RangeType& r, 
size_t auxBufferIdx)
 
  711        for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
 
  712            mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
 
  716    void doSyncAllBuffers1(
const RangeType& r)
 
  718        for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
 
  719            mAuxBuffers[n] = mLeafs[n]->buffer();
 
  723    void doSyncAllBuffers2(
const RangeType& r)
 
  725        for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
 
  726            const BufferType& leafBuffer = mLeafs[n]->buffer();
 
  727            mAuxBuffers[2*n  ] = leafBuffer;
 
  728            mAuxBuffers[2*n+1] = leafBuffer;
 
  732    void doSyncAllBuffersN(
const RangeType& r)
 
  734        for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
 
  735            const BufferType& leafBuffer = mLeafs[n]->buffer();
 
  736            for (
size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
 
  742    template<
typename LeafOp>
 
  743    struct LeafTransformer
 
  745        LeafTransformer(
const LeafOp &leafOp) : mLeafOp(leafOp)
 
  748        void run(
const LeafRange &range, 
bool threaded)
 const 
  750            threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
 
  752        void operator()(
const LeafRange &range)
 const 
  754            for (
typename LeafRange::Iterator it = range.begin(); it; ++it) mLeafOp(*it, it.pos());
 
  756        const LeafOp mLeafOp;
 
  761    template<
typename LeafOp>
 
  764        LeafReducer(LeafOp &leafOp) : mLeafOp(&leafOp)
 
  767        LeafReducer(
const LeafReducer &other, tbb::split)
 
  768            : mLeafOpPtr(std::make_unique<LeafOp>(*(other.mLeafOp), tbb::
split()))
 
  769            , mLeafOp(mLeafOpPtr.get())
 
  772        void run(
const LeafRange& range, 
bool threaded)
 
  774            threaded ? tbb::parallel_reduce(range, *
this) : (*this)(range);
 
  776        void operator()(
const LeafRange& range)
 
  778            LeafOp &
op = *mLeafOp;
 
  779            for (
typename LeafRange::Iterator it = range.begin(); it; ++it) 
op(*it, it.pos());
 
  781        void join(
const LeafReducer& other) { mLeafOp->join(*(other.mLeafOp)); }
 
  782        std::unique_ptr<LeafOp> mLeafOpPtr;
 
  783        LeafOp *mLeafOp = 
nullptr;
 
  789        PrefixSum(
const LeafRange& r, 
size_t* offsets, 
size_t& prefix)
 
  792            tbb::parallel_for( r, *
this);
 
  793            for (
size_t i=0, leafCount = r.size(); i<leafCount; ++i) {
 
  794                size_t tmp = offsets[i];
 
  799        inline void operator()(
const LeafRange& r)
 const {
 
  800            for (
typename LeafRange::Iterator i = r.begin(); i; ++i) {
 
  801                mOffsets[i.pos()] = i->onVoxelCount();
 
  807    using FuncType = 
typename std::function<void (LeafManager*, 
const RangeType&)>;
 
  810    size_t                              mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
 
  811    std::unique_ptr<LeafType*[]>        mLeafPtrs;
 
  812    LeafType**                          mLeafs = 
nullptr;
 
  813    std::unique_ptr<NonConstBufferType[]> mAuxBufferPtrs;
 
  814    NonConstBufferType*                 mAuxBuffers = 
nullptr;
 
  815    FuncType                            mTask = 
nullptr;
 
 
  820template<
typename TreeT>
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
The root node of an OpenVDB tree.
Definition Exceptions.h:65
Definition LeafManager.h:106
bool test() const
Return true if this iterator is not yet exhausted.
Definition LeafManager.h:131
Iterator & operator=(const Iterator &)=default
bool isValid() const
Return true if the position of this iterator is in a valid range.
Definition LeafManager.h:129
bool empty() const
Return true if this iterator is exhausted.
Definition LeafManager.h:135
Iterator(const LeafRange &range, size_t pos)
Definition LeafManager.h:108
LeafType * operator->() const
Return a pointer to the leaf node to which this iterator is pointing.
Definition LeafManager.h:119
Iterator(const Iterator &)=default
bool operator!=(const Iterator &other) const
Definition LeafManager.h:136
LeafType & operator*() const
Return a reference to the leaf node to which this iterator is pointing.
Definition LeafManager.h:117
size_t pos() const
Return the index into the leaf array of the current leaf node.
Definition LeafManager.h:127
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:122
Iterator & operator++()
Advance to the next leaf node.
Definition LeafManager.h:115
const LeafRange & leafRange() const
Definition LeafManager.h:141
bool operator==(const Iterator &other) const
Definition LeafManager.h:140
Definition LeafManager.h:103
LeafRange(size_t begin, size_t end, const LeafManager &leafManager, size_t grainSize=1)
Definition LeafManager.h:148
Iterator begin() const
Definition LeafManager.h:156
size_t size() const
Definition LeafManager.h:160
bool is_divisible() const
Definition LeafManager.h:168
const LeafManager & leafManager() const
Definition LeafManager.h:164
Iterator end() const
Definition LeafManager.h:158
bool empty() const
Definition LeafManager.h:166
LeafRange(LeafRange &r, tbb::split)
Definition LeafManager.h:170
size_t grainsize() const
Definition LeafManager.h:162
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
const TreeType & tree() const
Definition LeafManager.h:303
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:331
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:550
LeafType & leaf(size_t leafIdx) const
Definition LeafManager.h:319
size_t auxBufferCount() const
Return the total number of allocated auxiliary buffers.
Definition LeafManager.h:283
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition LeafManager.h:96
RootNodeType & root()
Return a reference to the root node associated with this manager.
Definition LeafManager.h:312
TreeType & tree()
Return a reference to the tree associated with this manager.
Definition LeafManager.h:306
typename TopologyT::ValueType ValueType
Definition LeafManager.h:89
typename leafmgr::TreeTraits< TopologyT >::LeafIterType LeafIterType
Definition LeafManager.h:94
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:360
void rebuild(TreeType &tree, bool serial=false)
Definition LeafManager.h:251
void operator()(const RangeType &r) const
Used internally by tbb::parallel_for() - never call it directly!
Definition LeafManager.h:573
void rebuild(bool serial=false)
Definition LeafManager.h:239
bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial=false)
Swap any two buffers for each leaf node.
Definition LeafManager.h:372
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition LeafManager.h:343
bool syncAuxBuffer(size_t bufferIdx, bool serial=false)
Sync up the specified auxiliary buffer with the corresponding leaf node buffer.
Definition LeafManager.h:396
static const Index DEPTH
Definition LeafManager.h:98
bool syncAllBuffers(bool serial=false)
Sync up all auxiliary buffers with their corresponding leaf node buffers.
Definition LeafManager.h:408
LeafManager(const LeafManager &other)
Definition LeafManager.h:223
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:533
bool isConstTree() const
Return true if the tree associated with this manager is immutable.
Definition LeafManager.h:315
typename TopologyT::RootNodeType RootNodeType
Definition LeafManager.h:90
LeafManager(TreeType &tree, size_t auxBuffersPerLeaf=0, bool serial=false)
Constructor from a tree reference and an auxiliary buffer count.
Definition LeafManager.h:193
size_t auxBuffersPerLeaf() const
Definition LeafManager.h:285
typename TreeType::LeafNodeType NonConstLeafType
Definition LeafManager.h:91
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:205
void rebuildLeafArray(bool serial=false)
Remove the auxiliary buffers and rebuild the leaf array.
Definition LeafManager.h:276
size_t leafCount() const
Return the number of leaf nodes.
Definition LeafManager.h:288
void rebuild(TreeType &tree, size_t auxBuffersPerLeaf, bool serial=false)
Definition LeafManager.h:256
tbb::blocked_range< size_t > RangeType
Definition LeafManager.h:97
void rebuildAuxBuffers(size_t auxBuffersPerLeaf, bool serial=false)
Change the number of auxiliary buffers.
Definition LeafManager.h:267
void rebuild(size_t auxBuffersPerLeaf, bool serial=false)
Repopulate the leaf array and delete and reallocate auxiliary buffers.
Definition LeafManager.h:246
typename LeafType::Buffer NonConstBufferType
Definition LeafManager.h:95
LeafRange leafRange(size_t grainsize=1) const
Definition LeafManager.h:346
static const bool IsConstTree
Definition LeafManager.h:100
TopologyT TreeType
Definition LeafManager.h:88
const RootNodeType & root() const
Return a const reference to root node associated with this manager.
Definition LeafManager.h:309
typename CopyConstness< TreeType, NonConstLeafType >::Type LeafType
Definition LeafManager.h:92
Index64 activeLeafVoxelCount() const
Return the number of active voxels in the leaf nodes.
Definition LeafManager.h:292
LeafType LeafNodeType
Definition LeafManager.h:93
void removeAuxBuffers()
Remove the auxiliary buffers, but don't rebuild the leaf array.
Definition LeafManager.h:273
OPENVDB_AX_API void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
void split(ContainerT &out, const std::string &in, const char delim)
Definition Name.h:43
Definition LeafManager.h:34
Index32 Index
Definition Types.h:54
uint64_t Index64
Definition Types.h:53
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
typename std::remove_const< ToType >::type Type
Definition Types.h:439
LeafManager< const TreeT > ManagerT
Definition LeafManager.h:823
typename ManagerT::LeafType LeafT
Definition LeafManager.h:825
typename ManagerT::RangeType RangeT
Definition LeafManager.h:824
typename ManagerT::BufferType BufT
Definition LeafManager.h:826
static void doSwapLeafBuffer(const RangeT &, size_t, LeafT **, BufT *, size_t)
Definition LeafManager.h:828
Definition LeafManager.h:55
static void doSwapLeafBuffer(const RangeT &r, size_t auxBufferIdx, LeafT **leafs, BufT *bufs, size_t bufsPerLeaf)
Definition LeafManager.h:60
typename ManagerT::LeafType LeafT
Definition LeafManager.h:57
typename ManagerT::RangeType RangeT
Definition LeafManager.h:56
typename ManagerT::BufferType BufT
Definition LeafManager.h:58
typename SubtreeT::template Append< HeadT > Type
Definition RootNode.h:1039
typename TreeT::LeafCIter LeafIterType
Definition LeafManager.h:44
static const bool IsConstTree
Definition LeafManager.h:43
Useful traits for Tree types.
Definition LeafManager.h:38
typename TreeT::LeafIter LeafIterType
Definition LeafManager.h:40
static const bool IsConstTree
Definition LeafManager.h:39
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218