From 8c98220878a0c5864c7c3f440a3a6f30167caada Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 7 Oct 2008 11:35:41 +0000 Subject: [PATCH] Added the ability to release OpenGL objects in PagedLOD subgrphs that are no longer being rendered. --- include/osg/PagedLOD | 5 ++ include/osgDB/DatabasePager | 21 +++++++++ src/osg/PagedLOD.cpp | 25 +++++++++- src/osgDB/DatabasePager.cpp | 62 ++++++++++++++++++++++++- src/osgWrappers/osg/PagedLOD.cpp | 6 +++ src/osgWrappers/osgDB/DatabasePager.cpp | 26 +++++++++++ 6 files changed, 142 insertions(+), 3 deletions(-) diff --git a/include/osg/PagedLOD b/include/osg/PagedLOD index bf3cdc138..338625d41 100644 --- a/include/osg/PagedLOD +++ b/include/osg/PagedLOD @@ -63,6 +63,7 @@ class OSG_EXPORT PagedLOD : public LOD float _priorityScale; double _timeStamp; int _frameNumber; + int _frameNumberOfLastReleaseGLObjects; osg::ref_ptr _databaseRequest; }; @@ -122,6 +123,10 @@ class OSG_EXPORT PagedLOD : public LOD * Return true if children are removed, false otherwise. */ 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 : virtual ~PagedLOD(); diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index d0567484c..99df79bce 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -216,6 +216,24 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl * before being removed.*/ 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.*/ void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; } @@ -534,6 +552,9 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl double _expiryDelay; int _expiryFrames; + double _releaseDelay; + int _releaseFrames; + ActiveGraphicsContexts _activeGraphicsContexts; // CompileGraphicsContexts _compileGraphicsContexts; diff --git a/src/osg/PagedLOD.cpp b/src/osg/PagedLOD.cpp index f75746d3c..0b74544de 100644 --- a/src/osg/PagedLOD.cpp +++ b/src/osg/PagedLOD.cpp @@ -23,7 +23,8 @@ PagedLOD::PerRangeData::PerRangeData(): _priorityOffset(0.0f), _priorityScale(1.0f), _timeStamp(0.0f), - _frameNumber(0) {} + _frameNumber(0), + _frameNumberOfLastReleaseGLObjects(0) {} PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd): _filename(prd._filename), @@ -31,6 +32,7 @@ PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd): _priorityScale(prd._priorityScale), _timeStamp(prd._timeStamp), _frameNumber(prd._frameNumber), + _frameNumberOfLastReleaseGLObjects(prd._frameNumberOfLastReleaseGLObjects), _databaseRequest(prd._databaseRequest) {} PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData& prd) @@ -41,6 +43,7 @@ PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData& _priorityScale = prd._priorityScale; _timeStamp = prd._timeStamp; _frameNumber = prd._frameNumber; + _frameNumberOfLastReleaseGLObjects = prd._frameNumberOfLastReleaseGLObjects; _databaseRequest = prd._databaseRequest; return *this; } @@ -288,3 +291,23 @@ bool PagedLOD::removeExpiredChildren(double expiryTime, int expiryFrame, NodeLis } 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; ireleaseGLObjects(); + ++numChildrenReleased; + } + } + return numChildrenReleased>0; +} diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 8a5e8786f..3415041cb 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -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 ", "Set the thread priority to DEFAULT, MIN, LOW, NOMINAL, HIGH or MAX."); static osg::ApplicationUsageProxy DatabasePager_e7(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EXPIRY_DELAY ","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 ","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 ","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 ","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 // 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 @@ -880,8 +882,6 @@ DatabasePager::DatabasePager() } } - _changeAutoUnRef = true; - _valueAutoUnRef = true; _changeAnisotropy = false; _valueAnisotropy = 1.0f; @@ -911,6 +911,31 @@ DatabasePager::DatabasePager() osg::notify(osg::NOTICE)<<"Expiry frames = "<<_expiryFrames<get(); + + + if (_releaseDelay!=DBL_MAX && plod->releaseGLObjectsOnExpiredChildren(releaseTime, releaseFrame)) + { + osg::notify(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs(), releasing gl objects"<removeExpiredChildren(expiryTime, expiryFrame, childrenRemoved); } diff --git a/src/osgWrappers/osg/PagedLOD.cpp b/src/osgWrappers/osg/PagedLOD.cpp index cfb5bf19a..9757867f4 100644 --- a/src/osgWrappers/osg/PagedLOD.cpp +++ b/src/osgWrappers/osg/PagedLOD.cpp @@ -213,6 +213,11 @@ BEGIN_OBJECT_REFLECTOR(osg::PagedLOD) __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. ", "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, Properties::NON_VIRTUAL, Properties::NON_CONST, @@ -280,6 +285,7 @@ BEGIN_VALUE_REFLECTOR(osg::PagedLOD::PerRangeData) I_PublicMemberProperty(float, _priorityScale); I_PublicMemberProperty(double, _timeStamp); I_PublicMemberProperty(int, _frameNumber); + I_PublicMemberProperty(int, _frameNumberOfLastReleaseGLObjects); I_PublicMemberProperty(osg::ref_ptr< osg::Referenced >, _databaseRequest); END_REFLECTOR diff --git a/src/osgWrappers/osgDB/DatabasePager.cpp b/src/osgWrappers/osgDB/DatabasePager.cpp index ff652496c..e17659d86 100644 --- a/src/osgWrappers/osgDB/DatabasePager.cpp +++ b/src/osgWrappers/osgDB/DatabasePager.cpp @@ -214,6 +214,26 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) __int__getExpiryFrames, "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, Properties::NON_VIRTUAL, __void__setDeleteRemovedSubgraphsInDatabaseThread__bool, @@ -415,6 +435,12 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) I_SimpleProperty(double, MinimumTimeToMergeTile, __double__getMinimumTimeToMergeTile, 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, 0, __int__setSchedulePriority__OpenThreads_Thread_ThreadPriority);