diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 55b30abc2..3294356dd 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -148,7 +148,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** Find all PagedLOD nodes in a subgraph and register them with * the DatabasePager so it can keep track of expired nodes. * note, should be only be called from the update thread. */ - virtual void registerPagedLODs(osg::Node* subgraph); + virtual void registerPagedLODs(osg::Node* subgraph, int frameNumber = 0); /** Set whether the database pager should pre compile OpenGL objects before allowing * them to be merged into the scene graph. @@ -272,7 +272,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) + virtual void updateSceneGraph(const osg::FrameStamp& frameStamp) { removeExpiredSubgraphs(frameStamp); addLoadedDataToSceneGraph(frameStamp); @@ -514,6 +514,12 @@ 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); @@ -545,8 +551,11 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl osg::ref_ptr _dataToMergeList; - PagedLODList _pagedLODList; + PagedLODList _activePagedLODList; + PagedLODList _inactivePagedLODList; + unsigned int _maximumNumberOfPageLOD; + double _expiryDelay; int _expiryFrames; diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index b4c26fd1e..5a2d366d9 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -856,6 +856,7 @@ DatabasePager::DatabasePager() { setReleaseDelay(DBL_MAX); } + _releaseFrames = 1; // Last frame will not be release if( (ptr = getenv("OSG_RELEASE_FRAMES")) != 0) @@ -864,6 +865,17 @@ DatabasePager::DatabasePager() osg::notify(osg::NOTICE)<<"Release frames = "<<_releaseFrames<getSharedStateManager()->share(databaseRequest->_loadedModel.get()); - registerPagedLODs(databaseRequest->_loadedModel.get()); + registerPagedLODs(databaseRequest->_loadedModel.get(), frameStamp.getFrameNumber()); osg::ref_ptr group = databaseRequest->_groupForAddingLoadedSubgraph.get(); if (group.valid()) @@ -1349,25 +1364,302 @@ class DatabasePager::MarkPagedLODsVisitor : public osg::NodeVisitor public: MarkPagedLODsVisitor(const std::string& marker): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _marker(marker) + _marker(marker), + _numPagedLODsMarked(0) { } virtual void apply(osg::PagedLOD& plod) { - plod.setName(_marker); + if (plod.getName()!=_marker) + { + ++_numPagedLODsMarked; + plod.setName(_marker); - traverse(plod); + traverse(plod); + } } std::string _marker; + unsigned int _numPagedLODsMarked; }; -void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp) +void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp& frameStamp) +{ + if (_maximumNumberOfPageLOD>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; + static double s_total_max_stage_a = 0.0; + + static double s_total_iter_stage_b = 0.0; + static double s_total_time_stage_b = 0.0; + static double s_total_max_stage_b = 0.0; + + static double s_total_iter_stage_c = 0.0; + static double s_total_time_stage_c = 0.0; + static double s_total_max_stage_c = 0.0; + + osg::Timer_t startTick = osg::Timer::instance()->tick(); + + +#if 1 + + 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 (_releaseDelay!=DBL_MAX) + { + plod->releaseGLObjects(); + osg::notify(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs(), releasing gl objects"<get(); + + int delta = frameStamp.getFrameNumber() - plod->getFrameNumberOfLastTraversal(); + if (delta>1) + { + ++itr; + } + else + { + _activePagedLODList.push_back(plod); + + itr = _inactivePagedLODList.erase(itr); + } + } + + unsigned int inactivePLOD = _inactivePagedLODList.size(); + unsigned int activePLOD = _activePagedLODList.size(); + + PagedLODList& pagedLODList = _inactivePagedLODList; + +#else + + unsigned int inactivePLOD = 0; + unsigned int activePLOD = 0; + + // iterate through the PagedLOD list moving all newly traversed nodes to end of list + // leaving inactive ones in place, so they in effect shuffle to the front, with the least + // recently traversed placed at the front + unsigned int numPagedLODs = _activePagedLODList.size(); + PagedLODList::iterator itr = _activePagedLODList.begin(); + for(unsigned int numIterations = 0; + numIterations < numPagedLODs; + ++numIterations) + { + osg::PagedLOD* plod = itr->get(); + + int delta = frameStamp.getFrameNumber() - plod->getFrameNumberOfLastTraversal(); + if (delta>1) + { + ++inactivePLOD; + ++itr; + } + else + { + ++activePLOD; + + _activePagedLODList.push_back(plod); + + itr = _activePagedLODList.erase(itr); + } + } + + PagedLODList& pagedLODList = _activePagedLODList; +#endif + + osg::Timer_t end_a_Tick = osg::Timer::instance()->tick(); + double time_a = osg::Timer::instance()->delta_m(startTick,end_a_Tick); + + s_total_iter_stage_a += 1.0; + s_total_time_stage_a += time_a; + if (s_total_max_stage_a inactivePLOD) + { + numToPrune = inactivePLOD; + } + + osg::NodeList childrenRemoved; + + double expiryTime = frameStamp.getReferenceTime() - 0.1; + int expiryFrame = frameStamp.getFrameNumber() - 1; + + MarkPagedLODsVisitor markerVistor("NeedToRemove"); + + + for(PagedLODList::iterator itr = pagedLODList.begin(); + itr!=pagedLODList.end() && markerVistor._numPagedLODsMarkedget(); + + osg::NodeList localChildrenRemoved; + plod->removeExpiredChildren(expiryTime, expiryFrame, localChildrenRemoved); + if (!localChildrenRemoved.empty()) + { + for(osg::NodeList::iterator critr = localChildrenRemoved.begin(); + critr!=localChildrenRemoved.end(); + ++critr) + { + (*critr)->accept(markerVistor); + } + + std::copy(localChildrenRemoved.begin(),localChildrenRemoved.end(),std::back_inserter(childrenRemoved)); + } + } + + osg::Timer_t end_b_Tick = osg::Timer::instance()->tick(); + double time_b = osg::Timer::instance()->delta_m(end_a_Tick,end_b_Tick); + + s_total_iter_stage_b += 1.0; + s_total_time_stage_b += time_b; + if (s_total_max_stage_b lock(_fileRequestQueue->_childrenToDeleteListMutex); + for (osg::NodeList::iterator critr = childrenRemoved.begin(); + critr!=childrenRemoved.end(); + ++critr) + { + _fileRequestQueue->_childrenToDeleteList.push_back(critr->get()); + } + + updateBlock = true; + + } + + unsigned int numRemoved = 0; + unsigned int numToRemove = markerVistor._numPagedLODsMarked; + + + // osg::notify(osg::NOTICE)<<"Children to remove "<delta_m(before,osg::Timer::instance()->tick())<<" ms "<get(); + if (plod && plod->getName() != markerVistor._marker) + { + ++itr; + + ++numSkipped; + + //osg::notify(osg::NOTICE)<<"skipping"<updateBlock(); + } + } + + osg::Timer_t end_c_Tick = osg::Timer::instance()->tick(); + double time_c = osg::Timer::instance()->delta_m(end_b_Tick,end_c_Tick); + + s_total_iter_stage_c += 1.0; + s_total_time_stage_c += time_c; + if (s_total_max_stage_ctick(); + + + + osg::notify(osg::INFO)<<"active="<<_activePagedLODList.size()<<" inactive="<<_inactivePagedLODList.size()<<" overall = "<delta_m(startTick,end_c_Tick)<< + " A="<tick(); double expiryTime = frameStamp.getReferenceTime() - _expiryDelay; int expiryFrame = frameStamp.getFrameNumber() - _expiryFrames; @@ -1377,8 +1669,8 @@ void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp) osg::NodeList childrenRemoved; - for(PagedLODList::iterator itr = _pagedLODList.begin(); - itr!=_pagedLODList.end(); + for(PagedLODList::iterator itr = _activePagedLODList.begin(); + itr!=_activePagedLODList.end(); ++itr) { osg::PagedLOD* plod = itr->get(); @@ -1419,8 +1711,8 @@ void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp) } // osg::notify(osg::NOTICE)<<" time 2 "<delta_m(before,osg::Timer::instance()->tick())<<" ms "<get(); @@ -1433,15 +1725,26 @@ void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp) PagedLODList::iterator itr_to_erase = itr; ++itr; - _pagedLODList.erase(itr_to_erase); + _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_max