Added the ability to release OpenGL objects in PagedLOD subgrphs that are no longer being rendered.

This commit is contained in:
Robert Osfield 2008-10-07 11:35:41 +00:00
parent 6ec4c64914
commit 8c98220878
6 changed files with 142 additions and 3 deletions

View File

@ -63,6 +63,7 @@ class OSG_EXPORT PagedLOD : public LOD
float _priorityScale; float _priorityScale;
double _timeStamp; double _timeStamp;
int _frameNumber; int _frameNumber;
int _frameNumberOfLastReleaseGLObjects;
osg::ref_ptr<osg::Referenced> _databaseRequest; osg::ref_ptr<osg::Referenced> _databaseRequest;
}; };
@ -122,6 +123,10 @@ class OSG_EXPORT PagedLOD : public LOD
* Return true if children are removed, false otherwise. */ * Return true if children are removed, false otherwise. */
virtual bool removeExpiredChildren(double expiryTime, int expiryFrame, NodeList& removedChildren); virtual bool removeExpiredChildren(double expiryTime, int expiryFrame, NodeList& removedChildren);
/** Release the GL Objects of the children from the PagedLOD which haven't been visited since specified expiry time and expiry frame number.
* Return true if any children have release called upon them, false otherwise. */
virtual bool releaseGLObjectsOnExpiredChildren(double releaseTime, int releaseFrame);
protected : protected :
virtual ~PagedLOD(); virtual ~PagedLOD();

View File

@ -216,6 +216,24 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
* before being removed.*/ * before being removed.*/
int getExpiryFrames() const { return _expiryFrames; } int getExpiryFrames() const { return _expiryFrames; }
/** Set the amount of time that a subgraph's OpenGL objects will be kept without being visited in the cull traversal
* before being released.*/
void setReleaseDelay(double releaseDelay);
/** Get the amount of time that a subgraph's OpenGL objects will be kept without being visited in the cull traversal
* before being released.*/
double getReleaseDelay() const { return _releaseDelay; }
/** Set the number of frames that a subgraph's OpenGL objects will be kept without being visited in the cull traversal
* before being released.*/
void setReleaseFrames(int releaseFrames) { _releaseFrames = releaseFrames; }
/** Get the number of frames that a subgraph's OpenGL objects will be kept without being visited in the cull traversal
* before being released.*/
int getReleaseFrames() const { return _releaseFrames; }
/** Set whether the removed subgraphs should be deleted in the database thread or not.*/ /** Set whether the removed subgraphs should be deleted in the database thread or not.*/
void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; } void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; }
@ -534,6 +552,9 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
double _expiryDelay; double _expiryDelay;
int _expiryFrames; int _expiryFrames;
double _releaseDelay;
int _releaseFrames;
ActiveGraphicsContexts _activeGraphicsContexts; ActiveGraphicsContexts _activeGraphicsContexts;
// CompileGraphicsContexts _compileGraphicsContexts; // CompileGraphicsContexts _compileGraphicsContexts;

View File

@ -23,7 +23,8 @@ PagedLOD::PerRangeData::PerRangeData():
_priorityOffset(0.0f), _priorityOffset(0.0f),
_priorityScale(1.0f), _priorityScale(1.0f),
_timeStamp(0.0f), _timeStamp(0.0f),
_frameNumber(0) {} _frameNumber(0),
_frameNumberOfLastReleaseGLObjects(0) {}
PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd): PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd):
_filename(prd._filename), _filename(prd._filename),
@ -31,6 +32,7 @@ PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd):
_priorityScale(prd._priorityScale), _priorityScale(prd._priorityScale),
_timeStamp(prd._timeStamp), _timeStamp(prd._timeStamp),
_frameNumber(prd._frameNumber), _frameNumber(prd._frameNumber),
_frameNumberOfLastReleaseGLObjects(prd._frameNumberOfLastReleaseGLObjects),
_databaseRequest(prd._databaseRequest) {} _databaseRequest(prd._databaseRequest) {}
PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData& prd) PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData& prd)
@ -41,6 +43,7 @@ PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData&
_priorityScale = prd._priorityScale; _priorityScale = prd._priorityScale;
_timeStamp = prd._timeStamp; _timeStamp = prd._timeStamp;
_frameNumber = prd._frameNumber; _frameNumber = prd._frameNumber;
_frameNumberOfLastReleaseGLObjects = prd._frameNumberOfLastReleaseGLObjects;
_databaseRequest = prd._databaseRequest; _databaseRequest = prd._databaseRequest;
return *this; return *this;
} }
@ -288,3 +291,23 @@ bool PagedLOD::removeExpiredChildren(double expiryTime, int expiryFrame, NodeLis
} }
return false; return false;
} }
bool PagedLOD::releaseGLObjectsOnExpiredChildren(double releaseTime, int releaseFrame)
{
unsigned int numChildrenReleased = 0;
unsigned int numChildren = osg::minimum(_perRangeDataList.size(), _children.size());
for(unsigned int i=_numChildrenThatCannotBeExpired; i<numChildren; ++i)
{
if (_perRangeDataList[i]._frameNumberOfLastReleaseGLObjects != _perRangeDataList[i]._frameNumber &&
_perRangeDataList[i]._timeStamp<releaseTime &&
_perRangeDataList[i]._frameNumber<releaseFrame)
{
_perRangeDataList[i]._frameNumberOfLastReleaseGLObjects = _perRangeDataList[i]._frameNumber;
_children[i]->releaseGLObjects();
++numChildrenReleased;
}
}
return numChildrenReleased>0;
}

View File

@ -46,6 +46,8 @@ static osg::ApplicationUsageProxy DatabasePager_e3(osg::ApplicationUsage::ENVIRO
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_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_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."); 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.");
static osg::ApplicationUsageProxy DatabasePager_e9(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RELEASE_DELAY <float> ","Set the length of time a PagedLOD child's OpenGL objects are kept in memory, without being used, before be released (setting to OFF disables this feature.)");
static osg::ApplicationUsageProxy DatabasePager_e10(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_RELEASE_FRAMES <int> ","Set number of frames a PagedLOD child's OpenGL objects are kept in memory, without being used, before be released.");
// Convert function objects that take pointer args into functions that a // Convert function objects that take pointer args into functions that a
// reference to an osg::ref_ptr. This is quite useful for doing STL // 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 // operations on lists of ref_ptr. This code assumes that a function
@ -880,8 +882,6 @@ DatabasePager::DatabasePager()
} }
} }
_changeAutoUnRef = true;
_valueAutoUnRef = true;
_changeAnisotropy = false; _changeAnisotropy = false;
_valueAnisotropy = 1.0f; _valueAnisotropy = 1.0f;
@ -911,6 +911,31 @@ DatabasePager::DatabasePager()
osg::notify(osg::NOTICE)<<"Expiry frames = "<<_expiryFrames<<std::endl; osg::notify(osg::NOTICE)<<"Expiry frames = "<<_expiryFrames<<std::endl;
} }
if( (ptr = getenv("OSG_RELEASE_DELAY")) != 0)
{
if (strcmp(ptr,"OFF")==0 || strcmp(ptr,"Off")==0 || strcmp(ptr,"off")==0)
{
setReleaseDelay(DBL_MAX);
}
else
{
setReleaseDelay(atof(ptr));
}
osg::notify(osg::NOTICE)<<"Release delay = "<<_releaseDelay<<std::endl;
}
else
{
setReleaseDelay(DBL_MAX);
}
_releaseFrames = 1; // Last frame will not be release
if( (ptr = getenv("OSG_RELEASE_FRAMES")) != 0)
{
_releaseFrames = atoi(ptr);
osg::notify(osg::NOTICE)<<"Release frames = "<<_releaseFrames<<std::endl;
}
_doPreCompile = true; _doPreCompile = true;
if( (ptr = getenv("OSG_DO_PRE_COMPILE")) != 0) if( (ptr = getenv("OSG_DO_PRE_COMPILE")) != 0)
{ {
@ -988,6 +1013,10 @@ DatabasePager::DatabasePager(const DatabasePager& rhs)
_expiryDelay = rhs._expiryDelay; _expiryDelay = rhs._expiryDelay;
_expiryFrames = rhs._expiryFrames; _expiryFrames = rhs._expiryFrames;
_releaseDelay = rhs._releaseDelay;
_releaseFrames = rhs._releaseFrames;
_doPreCompile = rhs._doPreCompile; _doPreCompile = rhs._doPreCompile;
_targetFrameRate = rhs._targetFrameRate; _targetFrameRate = rhs._targetFrameRate;
_minimumTimeAvailableForGLCompileAndDeletePerFrame = rhs._minimumTimeAvailableForGLCompileAndDeletePerFrame; _minimumTimeAvailableForGLCompileAndDeletePerFrame = rhs._minimumTimeAvailableForGLCompileAndDeletePerFrame;
@ -1029,6 +1058,23 @@ DatabasePager* DatabasePager::create()
new DatabasePager; new DatabasePager;
} }
void DatabasePager::setReleaseDelay(double releaseDelay)
{
_releaseDelay = releaseDelay;
if (_releaseDelay==DBL_MAX)
{
_changeAutoUnRef = true;
_valueAutoUnRef = true;
}
else
{
// when GLObject release is used make sure Images aren't unref'd as they may be needed later.
_changeAutoUnRef = true;
_valueAutoUnRef = false;
}
}
int DatabasePager::setSchedulePriority(OpenThreads::Thread::ThreadPriority priority) int DatabasePager::setSchedulePriority(OpenThreads::Thread::ThreadPriority priority)
{ {
int result = 0; int result = 0;
@ -1393,9 +1439,14 @@ void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp)
{ {
// osg::notify(osg::NOTICE)<<"DatabasePager::new_removeExpiredSubgraphs()"<<std::endl; // osg::notify(osg::NOTICE)<<"DatabasePager::new_removeExpiredSubgraphs()"<<std::endl;
double expiryTime = frameStamp.getReferenceTime() - _expiryDelay; double expiryTime = frameStamp.getReferenceTime() - _expiryDelay;
int expiryFrame = frameStamp.getFrameNumber() - _expiryFrames; int expiryFrame = frameStamp.getFrameNumber() - _expiryFrames;
double releaseTime = frameStamp.getReferenceTime() - _releaseDelay;
int releaseFrame = frameStamp.getFrameNumber() - _releaseFrames;
osg::NodeList childrenRemoved; osg::NodeList childrenRemoved;
for(PagedLODList::iterator itr = _pagedLODList.begin(); for(PagedLODList::iterator itr = _pagedLODList.begin();
@ -1403,6 +1454,13 @@ void DatabasePager::removeExpiredSubgraphs(const osg::FrameStamp &frameStamp)
++itr) ++itr)
{ {
osg::PagedLOD* plod = itr->get(); osg::PagedLOD* plod = itr->get();
if (_releaseDelay!=DBL_MAX && plod->releaseGLObjectsOnExpiredChildren(releaseTime, releaseFrame))
{
osg::notify(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs(), releasing gl objects"<<std::endl;
}
plod->removeExpiredChildren(expiryTime, expiryFrame, childrenRemoved); plod->removeExpiredChildren(expiryTime, expiryFrame, childrenRemoved);
} }

View File

@ -213,6 +213,11 @@ BEGIN_OBJECT_REFLECTOR(osg::PagedLOD)
__bool__removeExpiredChildren__double__int__NodeList_R1, __bool__removeExpiredChildren__double__int__NodeList_R1,
"Remove the children from the PagedLOD which haven't been visited since specified expiry time and expiry frame number. ", "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. "); "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. ");
I_Method2(bool, releaseGLObjectsOnExpiredChildren, IN, double, releaseTime, IN, int, releaseFrame,
Properties::VIRTUAL,
__bool__releaseGLObjectsOnExpiredChildren__double__int,
"Release the GL Objects of the children from the PagedLOD which haven't been visited since specified expiry time and expiry frame number. ",
"Return true if any children have release called upon them, false otherwise. ");
I_ProtectedMethod1(void, expandPerRangeDataTo, IN, unsigned int, pos, I_ProtectedMethod1(void, expandPerRangeDataTo, IN, unsigned int, pos,
Properties::NON_VIRTUAL, Properties::NON_VIRTUAL,
Properties::NON_CONST, Properties::NON_CONST,
@ -280,6 +285,7 @@ BEGIN_VALUE_REFLECTOR(osg::PagedLOD::PerRangeData)
I_PublicMemberProperty(float, _priorityScale); I_PublicMemberProperty(float, _priorityScale);
I_PublicMemberProperty(double, _timeStamp); I_PublicMemberProperty(double, _timeStamp);
I_PublicMemberProperty(int, _frameNumber); I_PublicMemberProperty(int, _frameNumber);
I_PublicMemberProperty(int, _frameNumberOfLastReleaseGLObjects);
I_PublicMemberProperty(osg::ref_ptr< osg::Referenced >, _databaseRequest); I_PublicMemberProperty(osg::ref_ptr< osg::Referenced >, _databaseRequest);
END_REFLECTOR END_REFLECTOR

View File

@ -214,6 +214,26 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager)
__int__getExpiryFrames, __int__getExpiryFrames,
"Get the number of frames that a subgraph will be kept without being visited in the cull traversal before being removed. ", "Get the number of frames that a subgraph will be kept without being visited in the cull traversal before being removed. ",
""); "");
I_Method1(void, setReleaseDelay, IN, double, releaseDelay,
Properties::NON_VIRTUAL,
__void__setReleaseDelay__double,
"Set the amount of time that a subgraph's OpenGL objects will be kept without being visited in the cull traversal before being released. ",
"");
I_Method0(double, getReleaseDelay,
Properties::NON_VIRTUAL,
__double__getReleaseDelay,
"Get the amount of time that a subgraph's OpenGL objects will be kept without being visited in the cull traversal before being released. ",
"");
I_Method1(void, setReleaseFrames, IN, int, releaseFrames,
Properties::NON_VIRTUAL,
__void__setReleaseFrames__int,
"Set the number of frames that a subgraph's OpenGL objects will be kept without being visited in the cull traversal before being released. ",
"");
I_Method0(int, getReleaseFrames,
Properties::NON_VIRTUAL,
__int__getReleaseFrames,
"Get the number of frames that a subgraph's OpenGL objects will be kept without being visited in the cull traversal before being released. ",
"");
I_Method1(void, setDeleteRemovedSubgraphsInDatabaseThread, IN, bool, flag, I_Method1(void, setDeleteRemovedSubgraphsInDatabaseThread, IN, bool, flag,
Properties::NON_VIRTUAL, Properties::NON_VIRTUAL,
__void__setDeleteRemovedSubgraphsInDatabaseThread__bool, __void__setDeleteRemovedSubgraphsInDatabaseThread__bool,
@ -415,6 +435,12 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager)
I_SimpleProperty(double, MinimumTimeToMergeTile, I_SimpleProperty(double, MinimumTimeToMergeTile,
__double__getMinimumTimeToMergeTile, __double__getMinimumTimeToMergeTile,
0); 0);
I_SimpleProperty(double, ReleaseDelay,
__double__getReleaseDelay,
__void__setReleaseDelay__double);
I_SimpleProperty(int, ReleaseFrames,
__int__getReleaseFrames,
__void__setReleaseFrames__int);
I_SimpleProperty(OpenThreads::Thread::ThreadPriority, SchedulePriority, I_SimpleProperty(OpenThreads::Thread::ThreadPriority, SchedulePriority,
0, 0,
__int__setSchedulePriority__OpenThreads_Thread_ThreadPriority); __int__setSchedulePriority__OpenThreads_Thread_ThreadPriority);