diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index cc1482b18..6e5e51b7e 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -81,6 +81,33 @@ public: virtual void traverse(const LLOctreeNode* node); }; +struct OctreeGuard +{ + template + OctreeGuard(const LLOctreeNode* node) + {mNode = (void*)node;getNodes().push_back(this);} + ~OctreeGuard() + {llassert_always(getNodes().back() == this); getNodes().pop_back();} + template + static bool checkGuarded(const LLOctreeNode* node) + { + for(std::vector::const_iterator it=getNodes().begin();it != getNodes().end();++it) + { + if((*it)->mNode == node) + { + OCT_ERRS << "!!! MANIPULATING OCTREE BRANCH DURING ITERATION !!!" << llendl; + return true; + } + } + return false; + } + static std::vector& getNodes() + { + static std::vector gNodes; + return gNodes; + } + void* mNode; +}; template class LLOctreeNode : public LLTreeNode { @@ -246,8 +273,8 @@ public: U32 getElementCount() const { return mElementCount; } bool isEmpty() const { return mElementCount == 0; } - element_list& getData() { return mData; } - const element_list& getData() const { return mData; } + //element_list& getData() { return mData; } + //const element_list& getData() const { return mData; } element_iter getDataBegin() { return mData; } element_iter getDataEnd() { return mDataEnd; } const_element_iter getDataBegin() const { return mData; } @@ -317,6 +344,7 @@ public: virtual bool insert(T* data) { + OctreeGuard::checkGuarded(this); if (data == NULL || data->getBinIndex() != -1) { OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; @@ -433,7 +461,7 @@ public: void _remove(T* data, S32 i) { //precondition -- mElementCount > 0, idx is in range [0, mElementCount) - + OctreeGuard::checkGuarded(this); mElementCount--; data->setBinIndex(-1); @@ -463,6 +491,7 @@ public: bool remove(T* data) { + OctreeGuard::checkGuarded(this); S32 i = data->getBinIndex(); if (i >= 0 && i < (S32)mElementCount) @@ -508,6 +537,7 @@ public: void removeByAddress(T* data) { + OctreeGuard::checkGuarded(this); for (U32 i = 0; i < mElementCount; ++i) { if (mData[i] == data) @@ -527,6 +557,7 @@ public: void clearChildren() { + OctreeGuard::checkGuarded(this); mChildCount = 0; U32* foo = (U32*) mChildMap; @@ -587,6 +618,7 @@ public: OCT_ERRS <<"Octree node has too many children... why?" << llendl; } #endif + OctreeGuard::checkGuarded(this); mChildMap[child->getOctant()] = mChildCount; @@ -606,6 +638,8 @@ public: void removeChild(S32 index, BOOL destroy = FALSE) { + OctreeGuard::checkGuarded(this); + for (U32 i = 0; i < this->getListenerCount(); i++) { oct_listener* listener = getOctListener(i); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 20c390931..99dfb11e1 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1276,6 +1276,7 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); setState(DEAD); + {OctreeGuard guard(mOctreeNode); for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -1284,6 +1285,7 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) drawable->setSpatialGroup(NULL); } } + } //clean up avatar attachment stats LLSpatialBridge* bridge = mSpatialPartition->asBridge(); @@ -1363,6 +1365,7 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) } + OctreeGuard guard(mOctreeNode); for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -2065,6 +2068,7 @@ public: { LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; + OctreeGuard guard(branch); for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -2189,6 +2193,7 @@ public: LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); + {OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -2197,6 +2202,7 @@ public: gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE); } } + } for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) { @@ -2502,6 +2508,7 @@ void renderOctree(LLSpatialGroup* group) gGL.flush(); glLineWidth(1.f); gGL.flush(); + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -3358,6 +3365,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) void renderPhysicsShapes(LLSpatialGroup* group) { + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -3885,6 +3893,7 @@ public: } } + {OctreeGuard guard(branch); for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -3980,7 +3989,7 @@ public: } } } - } + }} for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -4070,6 +4079,7 @@ public: return; } + OctreeGuard guard(branch); for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4293,6 +4303,7 @@ public: virtual void visit(const LLSpatialGroup::OctreeNode* branch) { + OctreeGuard guard(branch); for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { check(*i); @@ -4303,6 +4314,7 @@ public: { node->accept(this); + OctreeGuard guard(node); for (U32 i = 0; i < node->getChildCount(); i++) { const LLSpatialGroup::OctreeNode* child = node->getChild(i); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 890a52f0d..e6b018087 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -332,7 +332,7 @@ public: void dirtyMesh() { setState(MESH_DIRTY); } //octree wrappers to make code more readable - element_list& getData() { return mOctreeNode->getData(); } + //element_list& getData() { return mOctreeNode->getData(); } element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 6434dd619..9e9b0c8a3 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -645,6 +645,7 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count mFaceList.clear(); LLViewerCamera* camera = LLViewerCamera::getInstance(); + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 0a5a76900..f8c1f84a7 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -557,6 +557,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co mFaceList.clear(); LLViewerCamera* camera = LLViewerCamera::getInstance(); + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 1e1ca8bad..c7a7c44b0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3494,6 +3494,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); //get all the faces into a list + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -3900,6 +3901,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (!LLPipeline::sDelayVBUpdate) { //drawables have been rebuilt, clear rebuild status + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -3940,6 +3942,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) std::set mapped_buffers; + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -4012,6 +4015,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; warningsCount = 1; } + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -4484,6 +4488,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun //for each drawable + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 12f7c170e..a7657a4ab 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2820,6 +2820,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) else { group->setVisible(); + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { markVisible(*i, camera); @@ -2908,6 +2909,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT); if (!sSkipUpdate && group->changeLOD()) { + OctreeGuard guard(group->mOctreeNode); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; @@ -3044,6 +3046,7 @@ void forAllDrawables(LLCullResult::sg_iterator begin, { for (LLCullResult::sg_iterator i = begin; i != end; ++i) { + OctreeGuard guard((*i)->mOctreeNode); for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { func(*j);