From 9f8a4be2cdd9633f68065c592460570a30594c46 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 3 Mar 2010 16:40:19 +0000 Subject: [PATCH] Refactored DatabasePager so that it nolonger takes ref_ptr, but instead uses a custom version of observer_ptr<>. This change should make it possible to delete PagedLOD's independantly from the DatabasePager, and also prevent issues of consistency of the pager when subgraphs when are cached elsewhere in the application such as in the Registry filecache. --- include/osgDB/DatabasePager | 39 ++-- src/osgDB/DatabasePager.cpp | 451 +++++++++++++++--------------------- 2 files changed, 210 insertions(+), 280 deletions(-) diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index fb9bb5304..63f17846e 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -279,11 +280,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** Merge the changes to the scene graph by calling calling removeExpiredSubgraphs then addLoadedDataToSceneGraph. * Note, must only be called from single thread update phase. */ - virtual void updateSceneGraph(const osg::FrameStamp& frameStamp) - { - removeExpiredSubgraphs(frameStamp); - addLoadedDataToSceneGraph(frameStamp); - } + virtual void updateSceneGraph(const osg::FrameStamp& frameStamp); /** Turn the compilation of rendering objects for specified graphics context on (true) or off(false). */ void setCompileGLObjectsForContextID(unsigned int contextID, bool on); @@ -332,7 +329,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** Reset the Stats variables.*/ void resetStats(); - typedef std::list< osg::ref_ptr > PagedLODList; typedef std::set< osg::ref_ptr > StateSetList; typedef std::vector< osg::ref_ptr > DrawableList; typedef std::pair DataToCompile; @@ -349,6 +345,28 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl struct RequestQueue; + struct PagedLODObserver : public osg::observer_ptr + { + typedef osg::observer_ptr BaseClass; + + PagedLODObserver(osg::PagedLOD* plod):BaseClass(plod) {} + PagedLODObserver(const PagedLODObserver& plodObserver):BaseClass(plodObserver) {} + + PagedLODObserver& operator = (const PagedLODObserver& rhs) + { + (*static_cast(this)) = rhs; + return *this; + } + + virtual void objectDeleted(void* ptr) + { + BaseClass::objectDeleted(ptr); + } + }; + + typedef std::list< PagedLODObserver > PagedLODList; + + struct DatabaseRequest : public osg::Referenced { DatabaseRequest(): @@ -442,8 +460,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl class FindCompileableGLObjectsVisitor; friend class FindCompileableGLObjectsVisitor; - class MarkPagedLODsVisitor; - + class CountPagedLODsVisitor; class FindPagedLODsVisitor; friend class FindPagedLODsVisitor; @@ -547,12 +564,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl * note, should be only be called from the update thread. */ virtual void removeExpiredSubgraphs(const osg::FrameStamp &frameStamp); - /** Old expiry delay based removeExpiredSubgraphs. */ - virtual void expiry_removeExpiredSubgraphs(const osg::FrameStamp &frameStamp); - - /** New capped based removeExpiredSubgraphs. */ - virtual void capped_removeExpiredSubgraphs(const osg::FrameStamp &frameStamp); - /** Add the loaded data to the scene graph.*/ void addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp); diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index f1b285f11..b74e0aa13 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -217,7 +217,7 @@ public: { case DatabasePager::DO_NOT_MODIFY_DRAWABLE_SETTINGS: // do nothing, leave settings as they came in from loaded database. - // OSG_NOTIFY(osg::NOTICE)<<"DO_NOT_MODIFY_DRAWABLE_SETTINGS"<setUseDisplayList(true); @@ -226,12 +226,12 @@ public: case DatabasePager::USE_VERTEX_BUFFER_OBJECTS: drawable->setUseDisplayList(true); drawable->setUseVertexBufferObjects(true); - // OSG_NOTIFY(osg::NOTICE)<<"USE_VERTEX_BUFFER_OBJECTS"<setUseDisplayList(false); drawable->setUseVertexBufferObjects(false); - // OSG_NOTIFY(osg::NOTICE)<<"USE_VERTEX_ARRAYS"<_requestList.size()= "<_requestList.size()<<" to delete = "<_childrenToDeleteList.size()<_requestList.size()= "<_requestList.size()<<" to delete = "<_childrenToDeleteList.size()<_fileName<_fileName<add(databaseRequest.get()); databaseRequest = 0; } @@ -608,7 +608,7 @@ void DatabasePager::DatabaseThread::run() // load the data, note safe to write to the databaseRequest since once // it is created this thread is the only one to write to the _loadedModel pointer. - //OSG_NOTIFY(osg::NOTICE)<<"In DatabasePager thread readNodeFile("<_fileName<<")"<_fileName<<")"<tick(); @@ -630,7 +630,7 @@ void DatabasePager::DatabaseThread::run() if ((_pager->_frameNumber-databaseRequest->_frameNumberLastRequest)>1) { - OSG_NOTIFY(osg::INFO)<<_name<<": Warning DatabaseRquest no longer required."<_loadedModel = 0; } @@ -638,12 +638,12 @@ void DatabasePager::DatabaseThread::run() osg::RefNodePath refNodePath; if (!databaseRequest->_observerNodePath.getRefNodePath(refNodePath)) { - OSG_NOTICE<<_name<<": Warning node in parental chain has been deleted, discarding load."<_loadedModel = 0; } - //OSG_NOTIFY(osg::NOTICE)<<" node read in "<delta_m(before,osg::Timer::instance()->tick())<<" ms"<delta_m(before,osg::Timer::instance()->tick())<<" ms"<_dataToCompileList->_requestList.end(); ++citr) { - OSG_NOTIFY(osg::INFO)<<_name<<": pruning from compile list"<_loadedModel = 0; (*citr)->_requestQueue = 0; } @@ -778,7 +778,7 @@ void DatabasePager::DatabaseThread::run() } } - // OSG_NOTIFY(osg::NOTICE)<<"Done compiling in paging thread"<getOptions(); - // OSG_NOTIFY(osg::NOTICE)<<"Using options from Registry "<_requestQueue; if (requestQueue) @@ -1312,7 +1312,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou if (databaseRequestRef->referenceCount()==1) { - OSG_NOTIFY(osg::INFO)<<"DatabasePager::requestNodeFile("<_frameNumberFirstRequest = frameNumber; databaseRequest->_timestampFirstRequest = timestamp; @@ -1333,7 +1333,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou if (!foundEntry) { - OSG_NOTIFY(osg::INFO)<<"In DatabasePager::requestNodeFile("< lock(_fileRequestQueue->_requestMutex); @@ -1397,15 +1397,15 @@ void DatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp) { if (framestamp) { - //OSG_NOTIFY(osg::INFO) << "signalBeginFrame "<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber(); - } //else OSG_NOTIFY(osg::INFO) << "signalBeginFrame >>>>>>>>>>>>>>>>"<>>>>>>>>>>>>>>>"< lock(*osg::Observer::getGlobalObserverMutex()); + + removeExpiredSubgraphs(frameStamp); + +#ifdef UPDATE_TIMING + timeFor_removeExpiredSubgraphs = timer.elapsedTime_m(); +#endif + + addLoadedDataToSceneGraph(frameStamp); + +#ifdef UPDATE_TIMING + timeFor_addLoadedDataToSceneGraph = timer.elapsedTime_m() - timeFor_removeExpiredSubgraphs; +#endif + + } + +#ifdef UPDATE_TIMING + double elapsedTime = timer.elapsedTime_m(); + if (elapsedTime>0.2) + { + OSG_NOTICE<<"DatabasePager::updateSceneGraph() total time = "<tick(); + osg::Timer_t before = osg::Timer::instance()->tick(), mid, last; RequestQueue::RequestList localFileLoadedList; @@ -1445,7 +1481,7 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) localFileLoadedList.swap(_dataToMergeList->_requestList); } - osg::Timer_t mid = osg::Timer::instance()->tick(); + mid = osg::Timer::instance()->tick(); // add the loaded data into the scene graph. for(RequestQueue::RequestList::iterator itr=localFileLoadedList.begin(); @@ -1457,13 +1493,12 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) osg::RefNodePath refNodePath; if (databaseRequest->_observerNodePath.getRefNodePath(refNodePath)) { - // OSG_NOTIFY(osg::NOTICE)<<"Merging "<<_frameNumber-(*itr)->_frameNumberLastRequest<_frameNumberLastRequest<_groupForAddingLoadedSubgraph; if (osgDB::Registry::instance()->getSharedStateManager()) osgDB::Registry::instance()->getSharedStateManager()->share(databaseRequest->_loadedModel.get()); - registerPagedLODs(databaseRequest->_loadedModel.get(), frameStamp.getFrameNumber()); osg::PagedLOD* plod = dynamic_cast(group); if (plod) @@ -1483,7 +1518,9 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) group->addChild(databaseRequest->_loadedModel.get()); - // OSG_NOTIFY(osg::NOTICE)<<"merged subgraph"<_fileName<<" after "<_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0<_fileName<<" after "<_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0<_timestampFirstRequest; @@ -1501,10 +1538,10 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) // reset the loadedModel pointer databaseRequest->_loadedModel = 0; - // OSG_NOTIFY(osg::NOTICE)<<"curr = "<delta_m(mid,last)<<"ms"<< " objects"<0) - { - capped_removeExpiredSubgraphs(frameStamp); - } - else - { - expiry_removeExpiredSubgraphs(frameStamp); - } -} - -void DatabasePager::capped_removeExpiredSubgraphs(const osg::FrameStamp& frameStamp) { static double s_total_iter_stage_a = 0.0; static double s_total_time_stage_a = 0.0; @@ -1571,32 +1590,34 @@ void DatabasePager::capped_removeExpiredSubgraphs(const osg::FrameStamp& frameSt osg::Timer_t startTick = osg::Timer::instance()->tick(); - unsigned int numPagedLODs = _activePagedLODList.size() + _inactivePagedLODList.size(); - - PagedLODList::iterator itr = _activePagedLODList.begin(); for(PagedLODList::iterator itr = _activePagedLODList.begin(); itr != _activePagedLODList.end(); ) { osg::PagedLOD* plod = itr->get(); - - int delta = frameStamp.getFrameNumber() - plod->getFrameNumberOfLastTraversal(); - if (delta>1) + if (plod) { - if (_releaseDelay!=DBL_MAX) + int delta = frameStamp.getFrameNumber() - plod->getFrameNumberOfLastTraversal(); + if (delta>1) { - plod->releaseGLObjects(); - OSG_NOTIFY(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs(), releasing gl objects"<releaseGLObjects(); + } - _inactivePagedLODList.push_back(plod); - - itr = _activePagedLODList.erase(itr); + _inactivePagedLODList.push_back(plod); + + itr = _activePagedLODList.erase(itr); + } + else + { + ++itr; + } } else { - ++itr; + itr = _activePagedLODList.erase(itr); } } @@ -1605,21 +1626,28 @@ void DatabasePager::capped_removeExpiredSubgraphs(const osg::FrameStamp& frameSt ) { osg::PagedLOD* plod = itr->get(); - - int delta = frameStamp.getFrameNumber() - plod->getFrameNumberOfLastTraversal(); - if (delta>1) + if (plod) { - ++itr; + int delta = frameStamp.getFrameNumber() - plod->getFrameNumberOfLastTraversal(); + if (delta>1) + { + ++itr; + } + else + { + _activePagedLODList.push_back(plod); + + itr = _inactivePagedLODList.erase(itr); + } } else { - _activePagedLODList.push_back(plod); - itr = _inactivePagedLODList.erase(itr); } } int inactivePLOD = _inactivePagedLODList.size(); + unsigned int numPagedLODs = _activePagedLODList.size() + _inactivePagedLODList.size(); osg::Timer_t end_a_Tick = osg::Timer::instance()->tick(); @@ -1648,47 +1676,51 @@ void DatabasePager::capped_removeExpiredSubgraphs(const osg::FrameStamp& frameSt double expiryTime = frameStamp.getReferenceTime() - 0.1; int expiryFrame = frameStamp.getFrameNumber() - 1; - MarkPagedLODsVisitor markerVistor("NeedToRemove"); + CountPagedLODsVisitor countPagedLODsVisitor; for(PagedLODList::iterator itr = _inactivePagedLODList.begin(); - itr!=_inactivePagedLODList.end() && markerVistor._numPagedLODsMarkedget(); - - osg::NodeList localChildrenRemoved; - plod->removeExpiredChildren(expiryTime, expiryFrame, localChildrenRemoved); - if (!localChildrenRemoved.empty()) + if (plod) { - for(osg::NodeList::iterator critr = localChildrenRemoved.begin(); - critr!=localChildrenRemoved.end(); - ++critr) + osg::NodeList localChildrenRemoved; + plod->removeExpiredChildren(expiryTime, expiryFrame, localChildrenRemoved); + if (!localChildrenRemoved.empty()) { - (*critr)->accept(markerVistor); + for(osg::NodeList::iterator critr = localChildrenRemoved.begin(); + critr!=localChildrenRemoved.end(); + ++critr) + { + (*critr)->accept(countPagedLODsVisitor); + } + + std::copy(localChildrenRemoved.begin(),localChildrenRemoved.end(),std::back_inserter(childrenRemoved)); } - - std::copy(localChildrenRemoved.begin(),localChildrenRemoved.end(),std::back_inserter(childrenRemoved)); } } for(PagedLODList::iterator itr = _activePagedLODList.begin(); - itr!=_activePagedLODList.end() && markerVistor._numPagedLODsMarkedget(); - - osg::NodeList localChildrenRemoved; - plod->removeExpiredChildren(expiryTime, expiryFrame, localChildrenRemoved); - if (!localChildrenRemoved.empty()) + if (plod) { - for(osg::NodeList::iterator critr = localChildrenRemoved.begin(); - critr!=localChildrenRemoved.end(); - ++critr) + osg::NodeList localChildrenRemoved; + plod->removeExpiredChildren(expiryTime, expiryFrame, localChildrenRemoved); + if (!localChildrenRemoved.empty()) { - (*critr)->accept(markerVistor); + for(osg::NodeList::iterator critr = localChildrenRemoved.begin(); + critr!=localChildrenRemoved.end(); + ++critr) + { + (*critr)->accept(countPagedLODsVisitor); + } + + std::copy(localChildrenRemoved.begin(),localChildrenRemoved.end(),std::back_inserter(childrenRemoved)); } - - std::copy(localChildrenRemoved.begin(),localChildrenRemoved.end(),std::back_inserter(childrenRemoved)); } } @@ -1701,7 +1733,7 @@ void DatabasePager::capped_removeExpiredSubgraphs(const osg::FrameStamp& frameSt - //OSG_NOTIFY(osg::NOTICE)<<"numToPrune "<delta_m(before,osg::Timer::instance()->tick())<<" ms "<get(); - if (plod && plod->getName() != markerVistor._marker) - { - ++itr; - - ++numSkipped; - - // OSG_NOTIFY(osg::NOTICE)<<"skipping"<updateBlock(); @@ -1772,108 +1768,12 @@ void DatabasePager::capped_removeExpiredSubgraphs(const osg::FrameStamp& frameSt s_total_time_stage_c += time_c; if (s_total_max_stage_ctick(); - - double expiryTime = frameStamp.getReferenceTime() - _expiryDelay; - int expiryFrame = frameStamp.getFrameNumber() - _expiryFrames; - - double releaseTime = frameStamp.getReferenceTime() - _releaseDelay; - int releaseFrame = frameStamp.getFrameNumber() - _releaseFrames; - - osg::NodeList childrenRemoved; - - for(PagedLODList::iterator itr = _activePagedLODList.begin(); - itr!=_activePagedLODList.end(); - ++itr) - { - osg::PagedLOD* plod = itr->get(); - - - if (_releaseDelay!=DBL_MAX && plod->releaseGLObjectsOnExpiredChildren(releaseTime, releaseFrame)) - { - OSG_NOTIFY(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs(), releasing gl objects"<removeExpiredChildren(expiryTime, expiryFrame, childrenRemoved); - } - - if (!childrenRemoved.empty()) - { - MarkPagedLODsVisitor markerVistor("NeedToRemove"); - for(osg::NodeList::iterator critr = childrenRemoved.begin(); - critr!=childrenRemoved.end(); - ++critr) - { - (*critr)->accept(markerVistor); - } - - // OSG_NOTIFY(osg::NOTICE)<<"Children to remove "< lock(_fileRequestQueue->_childrenToDeleteListMutex); - for (osg::NodeList::iterator critr = childrenRemoved.begin(); - critr!=childrenRemoved.end(); - ++critr) - { - _fileRequestQueue->_childrenToDeleteList.push_back(critr->get()); - } - - _fileRequestQueue->updateBlock(); - } - - // OSG_NOTIFY(osg::NOTICE)<<" time 2 "<delta_m(before,osg::Timer::instance()->tick())<<" ms "<get(); - if (plod && plod->getName() != markerVistor._marker) - { - ++itr; - } - else - { - PagedLODList::iterator itr_to_erase = itr; - ++itr; - - _activePagedLODList.erase(itr_to_erase); - } - } - - childrenRemoved.clear(); - - - } - - osg::Timer_t endTick = osg::Timer::instance()->tick(); - double time = osg::Timer::instance()->delta_m(startTick,endTick); - - s_total_iter += 1.0; - s_total_time += time; - if (s_total_maxgetObservers(); + for(osg::ObserverSet::Observers::const_iterator itr = observers.begin(); + itr != observers.end() && needsToBeInserted; + ++itr) + { + if (dynamic_cast(*itr)) + { + needsToBeInserted = false; + } + } + } + + if (needsToBeInserted) + { + _activePagedLODList.push_back(&plod); + } + traverse(plod); } - + DatabasePager::PagedLODList& _activePagedLODList; int _frameNumber; - + protected: - + FindPagedLODsVisitor& operator = (const FindPagedLODsVisitor&) { return *this; } }; void DatabasePager::registerPagedLODs(osg::Node* subgraph, int frameNumber) { if (!subgraph) return; - FindPagedLODsVisitor fplv(_activePagedLODList, frameNumber); subgraph->accept(fplv); } @@ -1944,7 +1863,7 @@ DatabasePager::CompileOperation::CompileOperation(osgDB::DatabasePager* database void DatabasePager::CompileOperation::operator () (osg::GraphicsContext* context) { - // OSG_NOTIFY(osg::NOTICE)<<"Background thread compiling"<compileAllGLObjects(*(context->getState())); @@ -1965,7 +1884,7 @@ void DatabasePager::compileAllGLObjects(osg::State& state) void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) { - // OSG_NOTIFY(osg::NOTICE)<<"DatabasePager::compileGLObjects "<<_frameNumber<get(), state.getContextID()) || (sharedManager && sharedManager->isShared(itr->get()))) { @@ -2052,7 +1971,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) if (!dtc.second.empty() && (compileAll || ((elapsedTime+estimatedDrawableDuration)get(), state.getContextID())) { elapsedTime = timer.delta_s(start_tick,timer.tick()); @@ -2085,7 +2004,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) dwlist.erase(dwlist.begin(),itr); } - //OSG_NOTIFY(osg::INFO)<<"Checking if compiled"< 0) - //OSG_NOTIFY(osg::NOTICE)<< _frameNumber << "compiled " << numObjectsCompiled << " objects" << std::endl; + //OSG_NOTICE<< _frameNumber << "compiled " << numObjectsCompiled << " objects" << std::endl; if (allCompiled) { // we've compiled all of the current databaseRequest so we can now pop it off the // to compile list and place it on the merge list. - // OSG_NOTIFY(osg::NOTICE)<<"All compiled"< lock(_dataToCompileList->_requestMutex); @@ -2140,7 +2059,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) } else { - // OSG_NOTIFY(osg::NOTICE)<<"Not all compiled"<