From Maceij Krol, "I have implement frame based expiration of PagedLOD children.
New attribute DatabasePager::_expiryFrames sets number of frames a PagedLOD child is kept in memory. The attribute is set with DatabasePager::setExpiryFrames method or OSG_EXPIRY_FRAMES environmental variable. New attribute PagedLOD::PerRangeData::_ frameNumber contains frame number of last cull traversal. Children of PagedLOD are expired when time _AND_ number of frames since last cull traversal exceed OSG_EXPIRY_DELAY _AND_ OSG_EXPIRY_FRAMES respectively. By default OSG_EXPIRY_FRAMES = 1 which means that nodes from last cull/rendering traversal will not be expired even if last cull time exceeds OSG_EXPIRY_DELAY. Setting OSG_EXPIRY_FRAMES = 0 revokes previous behaviour of PagedLOD. Setting OSG_EXPIRY_FRAMES > 0 fixes problems of children reloading in lazy rendering applications. Required behaviour is achieved by manipulating OSG_EXPIRY_DELAY and OSG_EXPIRY_FRAMES together. Two interface changes are made: DatabasePager::updateSceneGraph(double currentFrameTime) is replaced by DatabasePager::updateSceneGraph(const osg::FrameStamp &frameStamp). The previous method is in #if 0 clause in the header file. Robert, decide if You want to include it. PagedLOD::removeExpiredChildren(double expiryTime, NodeList &removedChildren) is deprecated (warning is printed), when subclassing use PagedLOD::removeExpiredChildren(double expiryTime, int expiryFrame, NodeList &removedChildren) instead. "
This commit is contained in:
@@ -62,6 +62,7 @@ class OSG_EXPORT PagedLOD : public LOD
|
||||
float _priorityOffset;
|
||||
float _priorityScale;
|
||||
double _timeStamp;
|
||||
int _frameNumber;
|
||||
osg::ref_ptr<osg::Referenced> _databaseRequest;
|
||||
};
|
||||
|
||||
@@ -85,6 +86,10 @@ class OSG_EXPORT PagedLOD : public LOD
|
||||
double getTimeStamp(unsigned int childNo) const { return _perRangeDataList[childNo]._timeStamp; }
|
||||
unsigned int getNumTimeStamps() const { return _perRangeDataList.size(); }
|
||||
|
||||
void setFrameNumber(unsigned int childNo, int frameNumber) { expandPerRangeDataTo(childNo); _perRangeDataList[childNo]._frameNumber=frameNumber; }
|
||||
double getFrameNumber(unsigned int childNo) const { return _perRangeDataList[childNo]._frameNumber; }
|
||||
unsigned int getNumFrameNumbers() const { return _perRangeDataList.size(); }
|
||||
|
||||
|
||||
/** Return the DatabaseRequest object used by the DatabasePager to keep track of file load requests
|
||||
* being carried on behalf of the DatabasePager.
|
||||
@@ -111,13 +116,11 @@ class OSG_EXPORT PagedLOD : public LOD
|
||||
/** Get the number of children that the PagedLOD must keep around, even if they are older than their expiry time.*/
|
||||
unsigned int getNumChildrenThatCannotBeExpired() const { return _numChildrenThatCannotBeExpired; }
|
||||
|
||||
/** Remove the children from the PagedLOD which haven't been visited since specified expiry time.
|
||||
/** Remove the children from the PagedLOD which haven't been visited since specified expiry time and expiry frame number.
|
||||
* The removed children are added to the removeChildren list passed into the method,
|
||||
* this allows the children to be deleted later at the caller's discretion.
|
||||
* Return true if children are removed, false otherwise. */
|
||||
virtual bool removeExpiredChildren(double expiryTime,NodeList& removedChildren);
|
||||
|
||||
|
||||
virtual bool removeExpiredChildren(double expiryTime, int expiryFrame, NodeList& removedChildren);
|
||||
|
||||
protected :
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <osg/PagedLOD>
|
||||
#include <osg/Drawable>
|
||||
#include <osg/GraphicsThread>
|
||||
#include <osg/FrameStamp>
|
||||
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Mutex>
|
||||
@@ -207,6 +208,14 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
* before being removed.*/
|
||||
double getExpiryDelay() const { return _expiryDelay; }
|
||||
|
||||
/** Set the number of frames that a subgraph will be kept without being visited in the cull traversal
|
||||
* before being removed.*/
|
||||
void setExpiryFrames(int expiryFrames) { _expiryFrames = expiryFrames; }
|
||||
|
||||
/** Get the number of frames that a subgraph will be kept without being visited in the cull traversal
|
||||
* before being removed.*/
|
||||
int getExpiryFrames() const { return _expiryFrames; }
|
||||
|
||||
/** Set whether the removed subgraphs should be deleted in the database thread or not.*/
|
||||
void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; }
|
||||
|
||||
@@ -247,12 +256,12 @@ 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(double currentFrameTime)
|
||||
virtual void updateSceneGraph(const osg::FrameStamp &frameStamp)
|
||||
{
|
||||
removeExpiredSubgraphs(currentFrameTime);
|
||||
addLoadedDataToSceneGraph(currentFrameTime);
|
||||
removeExpiredSubgraphs(frameStamp);
|
||||
addLoadedDataToSceneGraph(frameStamp);
|
||||
}
|
||||
|
||||
|
||||
/** Turn the compilation of rendering objects for specified graphics context on (true) or off(false). */
|
||||
void setCompileGLObjectsForContextID(unsigned int contextID, bool on);
|
||||
|
||||
@@ -487,10 +496,10 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
/** Iterate through the active PagedLOD nodes children removing
|
||||
* children which havn't been visited since specified expiryTime.
|
||||
* note, should be only be called from the update thread. */
|
||||
virtual void removeExpiredSubgraphs(double currentFrameTime);
|
||||
virtual void removeExpiredSubgraphs(const osg::FrameStamp &frameStamp);
|
||||
|
||||
/** Add the loaded data to the scene graph.*/
|
||||
void addLoadedDataToSceneGraph(double currentFrameTime);
|
||||
void addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp);
|
||||
|
||||
|
||||
bool _done;
|
||||
@@ -523,6 +532,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
PagedLODList _pagedLODList;
|
||||
|
||||
double _expiryDelay;
|
||||
int _expiryFrames;
|
||||
|
||||
ActiveGraphicsContexts _activeGraphicsContexts;
|
||||
// CompileGraphicsContexts _compileGraphicsContexts;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/observer_ptr>
|
||||
#include <osg/OperationThread>
|
||||
#include <osg/FrameStamp>
|
||||
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
@@ -84,7 +85,7 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler
|
||||
virtual bool requiresUpdateSceneGraph() const;
|
||||
|
||||
/** Merge the changes to the scene graph. */
|
||||
virtual void updateSceneGraph(double currentFrameTime);
|
||||
virtual void updateSceneGraph(const osg::FrameStamp &frameStamp);
|
||||
|
||||
int cancel();
|
||||
|
||||
|
||||
@@ -22,13 +22,15 @@ using namespace osg;
|
||||
PagedLOD::PerRangeData::PerRangeData():
|
||||
_priorityOffset(0.0f),
|
||||
_priorityScale(1.0f),
|
||||
_timeStamp(0.0f) {}
|
||||
_timeStamp(0.0f),
|
||||
_frameNumber(0) {}
|
||||
|
||||
PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd):
|
||||
_filename(prd._filename),
|
||||
_priorityOffset(prd._priorityOffset),
|
||||
_priorityScale(prd._priorityScale),
|
||||
_timeStamp(prd._timeStamp),
|
||||
_frameNumber(prd._frameNumber),
|
||||
_databaseRequest(prd._databaseRequest) {}
|
||||
|
||||
PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData& prd)
|
||||
@@ -38,6 +40,7 @@ PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData&
|
||||
_priorityOffset = prd._priorityOffset;
|
||||
_priorityScale = prd._priorityScale;
|
||||
_timeStamp = prd._timeStamp;
|
||||
_frameNumber = prd._frameNumber;
|
||||
_databaseRequest = prd._databaseRequest;
|
||||
return *this;
|
||||
}
|
||||
@@ -114,6 +117,7 @@ void PagedLOD::traverse(NodeVisitor& nv)
|
||||
if (nv.getFrameStamp()) setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
|
||||
|
||||
double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
|
||||
int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0;
|
||||
bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
|
||||
|
||||
switch(nv.getTraversalMode())
|
||||
@@ -154,7 +158,11 @@ void PagedLOD::traverse(NodeVisitor& nv)
|
||||
{
|
||||
if (i<_children.size())
|
||||
{
|
||||
if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;
|
||||
if (updateTimeStamp)
|
||||
{
|
||||
_perRangeDataList[i]._timeStamp=timeStamp;
|
||||
_perRangeDataList[i]._frameNumber=frameNumber;
|
||||
}
|
||||
|
||||
_children[i]->accept(nv);
|
||||
lastChildTraversed = (int)i;
|
||||
@@ -173,7 +181,11 @@ void PagedLOD::traverse(NodeVisitor& nv)
|
||||
// select the last valid child.
|
||||
if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
|
||||
{
|
||||
if (updateTimeStamp) _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
|
||||
if (updateTimeStamp)
|
||||
{
|
||||
_perRangeDataList[numChildren-1]._timeStamp=timeStamp;
|
||||
_perRangeDataList[numChildren-1]._frameNumber=frameNumber;
|
||||
}
|
||||
_children[numChildren-1]->accept(nv);
|
||||
}
|
||||
|
||||
@@ -261,12 +273,14 @@ bool PagedLOD::removeChildren( unsigned int pos,unsigned int numChildrenToRemove
|
||||
return Group::removeChildren(pos,numChildrenToRemove);
|
||||
}
|
||||
|
||||
bool PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
|
||||
bool PagedLOD::removeExpiredChildren(double expiryTime, int expiryFrame, NodeList& removedChildren)
|
||||
{
|
||||
if (_children.size()>_numChildrenThatCannotBeExpired)
|
||||
{
|
||||
if (!_perRangeDataList[_children.size()-1]._filename.empty() && _perRangeDataList[_children.size()-1]._timeStamp<expiryTime)
|
||||
{
|
||||
if (!_perRangeDataList[_children.size()-1]._filename.empty() &&
|
||||
_perRangeDataList[_children.size()-1]._timeStamp<expiryTime &&
|
||||
_perRangeDataList[_children.size()-1]._frameNumber<expiryFrame)
|
||||
{
|
||||
osg::Node* nodeToRemove = _children[_children.size()-1].get();
|
||||
removedChildren.push_back(nodeToRemove);
|
||||
return Group::removeChildren(_children.size()-1,1);
|
||||
|
||||
@@ -45,6 +45,7 @@ static osg::ApplicationUsageProxy DatabasePager_e2(osg::ApplicationUsage::ENVIRO
|
||||
static osg::ApplicationUsageProxy DatabasePager_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DATABASE_PAGER_DRAWABLE <mode>","Set the drawable policy for setting of loaded drawable to specified type. mode can be one of DoNotModify, DisplayList, VBO or VertexArrays>.");
|
||||
static osg::ApplicationUsageProxy DatabasePager_e4(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DATABASE_PAGER_PRIORITY <mode>", "Set the thread priority to DEFAULT, MIN, LOW, NOMINAL, HIGH or MAX.");
|
||||
static osg::ApplicationUsageProxy DatabasePager_e7(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EXPIRY_DELAY <float> ","Set the length of time a PagedLOD child is kept in memory, without being used, before its tagged as expired, and ear marked to deletion.");
|
||||
static osg::ApplicationUsageProxy DatabasePager_e8(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EXPIRY_FRAMES <int> ","Set number of frames a PagedLOD child is kept in memory, without being used, before its tagged as expired, and ear marked to deletion.");
|
||||
// Convert function objects that take pointer args into functions that a
|
||||
// reference to an osg::ref_ptr. This is quite useful for doing STL
|
||||
// operations on lists of ref_ptr. This code assumes that a function
|
||||
@@ -901,6 +902,13 @@ DatabasePager::DatabasePager()
|
||||
osg::notify(osg::NOTICE)<<"Expiry delay = "<<_expiryDelay<<std::endl;
|
||||
}
|
||||
|
||||
_expiryFrames = 1; // Last frame will not be expired
|
||||
if( (ptr = getenv("OSG_EXPIRY_FRAMES")) != 0)
|
||||
{
|
||||
_expiryFrames = atoi(ptr);
|
||||
osg::notify(osg::NOTICE)<<"Expiry frames = "<<_expiryFrames<<std::endl;
|
||||
}
|
||||
|
||||
_doPreCompile = true;
|
||||
if( (ptr = getenv("OSG_DO_PRE_COMPILE")) != 0)
|
||||
{
|
||||
@@ -977,6 +985,7 @@ DatabasePager::DatabasePager(const DatabasePager& rhs)
|
||||
_deleteRemovedSubgraphsInDatabaseThread = rhs._deleteRemovedSubgraphsInDatabaseThread;
|
||||
|
||||
_expiryDelay = rhs._expiryDelay;
|
||||
_expiryFrames = rhs._expiryFrames;
|
||||
_doPreCompile = rhs._doPreCompile;
|
||||
_targetFrameRate = rhs._targetFrameRate;
|
||||
_minimumTimeAvailableForGLCompileAndDeletePerFrame = rhs._minimumTimeAvailableForGLCompileAndDeletePerFrame;
|
||||
@@ -1287,8 +1296,10 @@ bool DatabasePager::requiresUpdateSceneGraph() const
|
||||
}
|
||||
|
||||
|
||||
void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
|
||||
void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp)
|
||||
{
|
||||
double timeStamp = frameStamp.getReferenceTime();
|
||||
int frameNumber = frameStamp.getFrameNumber();
|
||||
|
||||
// osg::Timer_t before = osg::Timer::instance()->tick();
|
||||
|
||||
@@ -1321,7 +1332,8 @@ void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
|
||||
osg::PagedLOD* plod = dynamic_cast<osg::PagedLOD*>(group.get());
|
||||
if (plod)
|
||||
{
|
||||
plod->setTimeStamp(plod->getNumChildren(),timeStamp);
|
||||
plod->setTimeStamp(plod->getNumChildren(), timeStamp);
|
||||
plod->setFrameNumber(plod->getNumChildren(), frameNumber);
|
||||
plod->getDatabaseRequest(plod->getNumChildren()) = 0;
|
||||
}
|
||||
else
|
||||
@@ -1375,11 +1387,12 @@ public:
|
||||
std::string _marker;
|
||||
};
|
||||
|
||||
void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
|
||||
void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp)
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<"DatabasePager::new_removeExpiredSubgraphs()"<<std::endl;
|
||||
|
||||
double expiryTime = currentFrameTime - _expiryDelay;
|
||||
double expiryTime = frameStamp.getReferenceTime() - _expiryDelay;
|
||||
int expiryFrame = frameStamp.getFrameNumber() - _expiryFrames;
|
||||
|
||||
osg::NodeList childrenRemoved;
|
||||
|
||||
@@ -1388,7 +1401,7 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
|
||||
++itr)
|
||||
{
|
||||
osg::PagedLOD* plod = itr->get();
|
||||
plod->removeExpiredChildren(expiryTime,childrenRemoved);
|
||||
plod->removeExpiredChildren(expiryTime, expiryFrame, childrenRemoved);
|
||||
}
|
||||
|
||||
if (!childrenRemoved.empty())
|
||||
@@ -1445,7 +1458,7 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
|
||||
osgDB::Registry::instance()->getSharedStateManager()->prune();
|
||||
|
||||
// update the Registry object cache.
|
||||
osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(currentFrameTime);
|
||||
osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(frameStamp.getReferenceTime());
|
||||
osgDB::Registry::instance()->removeExpiredObjectsInCache(expiryTime);
|
||||
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ bool ImagePager::requiresUpdateSceneGraph() const
|
||||
return !(_completedQueue->_requestList.empty());
|
||||
}
|
||||
|
||||
void ImagePager::updateSceneGraph(double currentFrameTime)
|
||||
void ImagePager::updateSceneGraph(const osg::FrameStamp &frameStamp)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_completedQueue->_requestMutex);
|
||||
|
||||
|
||||
@@ -971,13 +971,13 @@ void CompositeViewer::updateTraversal()
|
||||
if (scene->getDatabasePager())
|
||||
{
|
||||
// synchronize changes required by the DatabasePager thread to the scene graph
|
||||
scene->getDatabasePager()->updateSceneGraph(_frameStamp->getReferenceTime());
|
||||
scene->getDatabasePager()->updateSceneGraph(*_frameStamp);
|
||||
}
|
||||
|
||||
if (scene->getImagePager())
|
||||
{
|
||||
// synchronize changes required by the DatabasePager thread to the scene graph
|
||||
scene->getImagePager()->updateSceneGraph(_frameStamp->getReferenceTime());
|
||||
scene->getImagePager()->updateSceneGraph(*_frameStamp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -889,13 +889,13 @@ void Viewer::updateTraversal()
|
||||
if (_scene->getDatabasePager())
|
||||
{
|
||||
// synchronize changes required by the DatabasePager thread to the scene graph
|
||||
_scene->getDatabasePager()->updateSceneGraph(_frameStamp->getReferenceTime());
|
||||
_scene->getDatabasePager()->updateSceneGraph(*_frameStamp);
|
||||
}
|
||||
|
||||
if (_scene->getImagePager())
|
||||
{
|
||||
// synchronize changes required by the DatabasePager thread to the scene graph
|
||||
_scene->getImagePager()->updateSceneGraph(_frameStamp->getReferenceTime());
|
||||
_scene->getImagePager()->updateSceneGraph(*_frameStamp);
|
||||
}
|
||||
|
||||
if (_updateOperations.valid())
|
||||
|
||||
Reference in New Issue
Block a user