44 #ifndef OPENVDB_TREE_LEAF_MANAGER_HAS_BEEN_INCLUDED
45 #define OPENVDB_TREE_LEAF_MANAGER_HAS_BEEN_INCLUDED
49 #include <boost/shared_ptr.hpp>
50 #include <boost/static_assert.hpp>
51 #include <boost/bind.hpp>
52 #include <boost/function.hpp>
53 #include <tbb/blocked_range.h>
54 #include <tbb/parallel_for.h>
55 #include <openvdb/Types.h>
73 template<
typename TreeT>
78 typedef typename TreeType::LeafNodeType
LeafType;
80 typedef typename tbb::blocked_range<size_t>
RangeType;
88 mAuxBuffersPerLeaf(auxBuffersPerLeaf),
94 this->rebuild(serial);
100 mLeafCount(other.mLeafCount),
101 mAuxBufferCount(other.mAuxBufferCount),
102 mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf),
104 mAuxBuffers(other.mAuxBuffers),
114 delete [] mAuxBuffers;
122 void rebuild(
bool serial=
false)
125 this->initAuxBuffers(serial);
129 void rebuild(
size_t auxBuffersPerLeaf,
bool serial=
false)
131 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
132 this->rebuild(serial);
139 this->rebuild(serial);
143 void rebuild(
TreeType& tree,
size_t auxBuffersPerLeaf,
bool serial=
false)
146 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
147 this->rebuild(serial);
154 void rebuildAuxBuffers(
size_t auxBuffersPerLeaf,
bool serial=
false)
156 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
157 this->initAuxBuffers(serial);
165 this->removeAuxBuffers();
195 assert(leafId < mLeafCount);
196 assert(bufferId==0 || bufferId -1 < mAuxBuffersPerLeaf);
197 return bufferId == 0 ?
mLeafs[leafId]->buffer() :
198 mAuxBuffers[ leafId*mAuxBuffersPerLeaf + bufferId -1 ];
204 return RangeType(0, mLeafCount, grainsize);
215 bool swapLeafBuffer(
size_t bufferId,
bool serial =
false)
217 if (bufferId == 0 || bufferId > mAuxBuffersPerLeaf)
return false;
218 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, bufferId-1);
219 this->cook(serial ? 0 : 512);
222 bool swapBuffer(
size_t bufferId1,
size_t bufferId2,
bool serial =
false)
224 const size_t b1 =
std::min(bufferId1,bufferId2);
225 const size_t b2 =
std::max(bufferId1,bufferId2);
226 if (b1==b2 || b2 > mAuxBuffersPerLeaf)
return false;
228 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, b2-1);
230 mTask = boost::bind(&LeafManager::doSwapAuxBuffer, _1, _2, b1-1, b2-1);
232 this->cook(serial ? 0 : 512);
244 bool syncAuxBuffer(
size_t bufferId,
bool serial =
false)
246 if (bufferId==0 || bufferId > mAuxBuffersPerLeaf)
return false;
247 mTask = boost::bind(&LeafManager::doSyncAuxBuffer, _1, _2, bufferId - 1);
248 this->cook(serial ? 0 : 64);
255 bool syncAllBuffers(
bool serial =
false)
257 switch (mAuxBuffersPerLeaf) {
261 mTask = boost::bind(&LeafManager::doSyncAllBuffers1, _1, _2);
break;
263 mTask = boost::bind(&LeafManager::doSyncAllBuffers2, _1, _2);
break;
265 mTask = boost::bind(&LeafManager::doSyncAllBuffersN, _1, _2);
267 this->cook(serial ? 0 : 64);
277 if (mTask) mTask(const_cast<LeafManager*>(
this), r);
285 const size_t leafCount = mTree->leafCount();
286 if (leafCount != mLeafCount) {
288 mLeafs = (leafCount == 0) ? NULL :
new LeafType*[leafCount];
289 mLeafCount = leafCount;
291 typename TreeType::LeafIter iter = mTree->beginLeaf();
292 for (
size_t n = 0; n != leafCount; ++n, ++iter)
mLeafs[n] = iter.getLeaf();
294 void initAuxBuffers(
bool serial)
296 const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
297 if (auxBufferCount != mAuxBufferCount) {
298 delete [] mAuxBuffers;
299 mAuxBuffers = (auxBufferCount == 0) ? NULL :
new BufferType[auxBufferCount];
300 mAuxBufferCount = auxBufferCount;
302 this->syncAllBuffers(serial);
304 void cook(
size_t grainsize)
307 tbb::parallel_for(this->getRange(grainsize), *
this);
309 (*this)(this->getRange());
312 void doSwapLeafBuffer(
const RangeType& r,
size_t auxBufferId)
314 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
315 mLeafs[n]->swap(mAuxBuffers[ n*N + auxBufferId ]);
318 void doSwapAuxBuffer(
const RangeType& r,
size_t auxBufferId1,
size_t auxBufferId2)
320 for (
size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
321 mAuxBuffers[n + auxBufferId1].swap(mAuxBuffers[n + auxBufferId2]);
324 void doSyncAuxBuffer(
const RangeType& r,
size_t auxBufferId)
326 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
327 mAuxBuffers[ n*N + auxBufferId ] =
mLeafs[n]->buffer();
330 void doSyncAllBuffers1(
const RangeType& r)
332 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) mAuxBuffers[n] =
mLeafs[n]->buffer();
334 void doSyncAllBuffers2(
const RangeType& r)
336 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
337 const BufferType& leafBuffer =
mLeafs[n]->buffer();
338 mAuxBuffers[2*n ] = leafBuffer;
339 mAuxBuffers[2*n+1] = leafBuffer;
342 void doSyncAllBuffersN(
const RangeType& r)
344 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
345 const BufferType& leafBuffer =
mLeafs[n]->buffer();
346 for (
size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
349 typedef typename boost::function<void (LeafManager*, const RangeType&)> FuncType;
352 size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
354 BufferType* mAuxBuffers;
356 const bool mIsMaster;
363 #endif // OPENVDB_TREE_LEAF_MANAGER_HAS_BEEN_INCLUDED