Various improvements to database paing.

This commit is contained in:
Robert Osfield 2004-09-21 17:26:08 +00:00
parent eea9ddccf5
commit 0d884d66eb
14 changed files with 330 additions and 77 deletions

View File

@ -22,6 +22,7 @@
namespace osg {
class Vec2f;
class Vec3f;
class Vec4f;
@ -115,6 +116,9 @@ class SG_EXPORT Drawable : public Object
{
public:
static unsigned int s_numberNewDrawablesInLastFrame;
static unsigned int s_numberDeletedDrawablesInLastFrame;
Drawable();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
@ -230,7 +234,7 @@ class SG_EXPORT Drawable : public Object
inline bool getUseDisplayList() const { return _useDisplayList; }
/** When set to true, ignore the setUseDisplayList() settings, and hints to the drawImplementation
method to use OpenGL vertex buffer objects for rendering..*/
method to use OpenGL vertex buffer objects for rendering.*/
void setUseVertexBufferObjects(bool flag);
/** Return whether OpenGL vertex buffer objects should be used when supported by OpenGL driver.*/
@ -241,6 +245,11 @@ class SG_EXPORT Drawable : public Object
void dirtyDisplayList();
/** Return the estimated size of GLObjects (display lists/vertex buffer objects) that are associated with this drawable.
* This size is used a hint for reuse of deleteed display lists/vertex buffer objects. */
virtual unsigned int getGLObjectSizeHint() const { return 0; }
/** draw OpenGL primitives.
* If the drawable has _useDisplayList set to true then use an OpenGL display
@ -343,12 +352,13 @@ class SG_EXPORT Drawable : public Object
virtual void drawImplementation(State& state) const = 0;
static GLuint generateDisplayList(unsigned int contextID, unsigned int sizeHint = 0);
/** use deleteDisplayList instead of glDeleteList to allow
* OpenGL display list to be cached until they can be deleted
* by the OpenGL context in which they were created, specified
* by contextID.*/
static void deleteDisplayList(unsigned int contextID,GLuint globj);
static void deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint = 0);
/** flush all the cached display list which need to be deleted
* in the OpenGL context related to contextID.*/
@ -754,7 +764,7 @@ inline void Drawable::draw(State& state) const
else if (_useDisplayList)
{
#ifdef USE_SEPARATE_COMPILE_AND_EXECUTE
globj = glGenLists( 1 );
globj = generateDisplayList(contextID, getGLObjectSizeHint()); // glGenLists( 1 );
glNewList( globj, GL_COMPILE );
if (_drawCallback.valid())
_drawCallback->drawImplementation(state,this);
@ -764,7 +774,7 @@ inline void Drawable::draw(State& state) const
glCallList( globj);
#else
globj = glGenLists( 1 );
globj = generateDisplayList(contextID, getGLObjectSizeHint()); // glGenLists( 1 );
glNewList( globj, GL_COMPILE_AND_EXECUTE );
if (_drawCallback.valid())
_drawCallback->drawImplementation(state,this);

View File

@ -330,6 +330,10 @@ class SG_EXPORT Geometry : public Drawable
const osg::Geometry* getInternalOptimizedGeometry() const { return _internalOptimizedGeometry.get(); }
/** Return the estimated size of GLObjects (display lists/vertex buffer objects) that are associated with this drawable.
* This size is used a hint for reuse of deleteed display lists/vertex buffer objects. */
virtual unsigned int getGLObjectSizeHint() const;
/** Draw Geometry directly ignoring an OpenGL display list which could be attached.
* This is the internal draw method which does the drawing itself,
* and is the method to override when deriving from Geometry for user-drawn objects.

View File

@ -71,7 +71,7 @@ class SG_EXPORT Group : public Node
/** Replace specified Node with another Node.
* Equivalent to setChild(getChildIndex(orignChild),node)
* See docs for setChild for futher details on implementation.
*/
*/
virtual bool replaceChild( Node *origChild, Node* newChild );
/** Return the number of chilren nodes. */

View File

@ -77,6 +77,15 @@ class SG_EXPORT PagedLOD : public LOD
unsigned int getNumTimeStamps() const { return _perRangeDataList.size(); }
/** Set the frame number of the last time that this PageLOD node was traversed.
* Note, this frame number is automatically set by the traverse() method for all traversals (update, cull etc.).
*/
inline void setFrameNumberOfLastTraversal(int frameNumber) { _frameNumberOfLastTraversal=frameNumber; }
/** Get the frame number of the last time that this PageLOD node was traversed.*/
inline int getFrameNumberOfLastTraversal() const { return _frameNumberOfLastTraversal; }
/** Set the number of children that the PagedLOD must keep around, even if they are older than their expiry time.*/
inline void setNumChildrenThatCannotBeExpired(unsigned int num) { _numChildrenThatCannotBeExpired = num; }
@ -84,9 +93,12 @@ class SG_EXPORT PagedLOD : public LOD
unsigned int getNumChildrenThatCannotBeExpired() const { return _numChildrenThatCannotBeExpired; }
/** Remove the children from the PagedLOD which haven't been visited since specified expiry time.
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.*/
virtual void removeExpiredChildren(double expiryTime,NodeList& removedChildren);
* 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. */
bool removeExpiredChildren(double expiryTime,NodeList& removedChildren);
protected :
@ -100,8 +112,8 @@ class SG_EXPORT PagedLOD : public LOD
void expandPerRangeDataTo(unsigned int pos);
unsigned int _numChildrenThatCannotBeExpired;
int _frameNumberOfLastTraversal;
unsigned int _numChildrenThatCannotBeExpired;
PerRangeDataList _perRangeDataList;
};

View File

@ -333,7 +333,7 @@ class SG_EXPORT DrawElementsUByte : public PrimitiveSet, public VectorUByte
typedef osg::buffered_value<GLuint> GLObjectList;
mutable GLObjectList _vboList;
virtual ~DrawElementsUByte() {}
virtual ~DrawElementsUByte();
};
@ -381,7 +381,7 @@ class SG_EXPORT DrawElementsUShort : public PrimitiveSet, public VectorUShort
typedef osg::buffered_value<GLuint> GLObjectList;
mutable GLObjectList _vboList;
virtual ~DrawElementsUShort() {}
virtual ~DrawElementsUShort();
};
class SG_EXPORT DrawElementsUInt : public PrimitiveSet, public VectorUInt
@ -425,10 +425,10 @@ class SG_EXPORT DrawElementsUInt : public PrimitiveSet, public VectorUInt
protected:
virtual ~DrawElementsUInt();
typedef osg::buffered_value<GLuint> GLObjectList;
mutable GLObjectList _vboList;
virtual ~DrawElementsUInt() {}
};
}

View File

@ -162,6 +162,7 @@
namespace osg {
/** Texture pure virtual base class that encapsulates OpenGl texture
* functionality common to the various types of OSG textures.
*/
@ -170,6 +171,10 @@ class SG_EXPORT Texture : public osg::StateAttribute
public :
static unsigned int s_numberTextureReusedLastInLastFrame;
static unsigned int s_numberNewTextureInLastFrame;
static unsigned int s_numberDeletedTextureInLastFrame;
Texture();
/** Copy constructor using CopyOp to manage deep vs shallow copy. */

View File

@ -28,7 +28,7 @@
#include <osgDB/Export>
#include <map>
#include <set>
#include <list>
namespace osgDB {
@ -211,7 +211,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
public:
typedef std::set< osg::ref_ptr<osg::PagedLOD> > PagedLODList;
typedef std::list< osg::ref_ptr<osg::PagedLOD> > PagedLODList;
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList;
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
@ -288,7 +288,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
OpenThreads::Mutex _dataToMergeListMutex;
PagedLODList _pagedLODList;
PagedLODList _activePagedLODList;
PagedLODList _inactivePagedLODList;
double _expiryDelay;

View File

@ -33,6 +33,9 @@
using namespace osg;
unsigned int Drawable::s_numberNewDrawablesInLastFrame = 0;
unsigned int Drawable::s_numberDeletedDrawablesInLastFrame = 0;
// static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context
// is set. Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
@ -45,7 +48,23 @@ typedef std::map<GLuint,DisplayListList> DeletedDisplayListCache;
static DeletedDisplayListCache s_deletedDisplayListCache;
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj)
GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint)
{
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
#endif
DisplayListList& dll = s_deletedDisplayListCache[contextID];
if (dll.empty()) return glGenLists( 1 );
else
{
notify(NOTICE)<<"reusing display list "<<std::endl;
GLuint globj = dll.back();
dll.pop_back();
return globj;
}
}
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint)
{
if (globj!=0)
{
@ -88,11 +107,14 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentT
ditr = dll.erase(ditr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
++Drawable::s_numberDeletedDrawablesInLastFrame;
}
}
}
elapsedTime = timer.delta_s(start_tick,timer.tick());
if (noDeleted!=0) notify(INFO)<<"Number display lists deleted = "<<noDeleted<<std::endl;
if (noDeleted) notify(NOTICE)<<"Number display lists deleted = "<<noDeleted<<" elapsed time"<<elapsedTime<<std::endl;
availableTime -= elapsedTime;
}
@ -363,7 +385,7 @@ void Drawable::dirtyDisplayList()
{
if (_globjList[i] != 0)
{
Drawable::deleteDisplayList(i,_globjList[i]);
Drawable::deleteDisplayList(i,_globjList[i], getGLObjectSizeHint());
_globjList[i] = 0;
}
}

View File

@ -743,6 +743,12 @@ bool Geometry::computeFastPathsUsed()
return _fastPath;
}
unsigned int Geometry::getGLObjectSizeHint() const
{
// do a very simply mapping of display list size proportional to vertex datasize.
return _vertexData.array.valid() ? _vertexData.array->getNumElements() : 0;
}
void Geometry::drawImplementation(State& state) const
{
if (_internalOptimizedGeometry.valid())

View File

@ -25,6 +25,7 @@ PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData&
PagedLOD::PagedLOD()
{
_frameNumberOfLastTraversal = 0;
_centerMode = USER_DEFINED_CENTER;
_radius = -1;
_numChildrenThatCannotBeExpired = 0;
@ -32,6 +33,7 @@ PagedLOD::PagedLOD()
PagedLOD::PagedLOD(const PagedLOD& plod,const CopyOp& copyop):
LOD(plod,copyop),
_frameNumberOfLastTraversal(plod._frameNumberOfLastTraversal),
_numChildrenThatCannotBeExpired(plod._numChildrenThatCannotBeExpired),
_perRangeDataList(plod._perRangeDataList)
{
@ -40,6 +42,9 @@ PagedLOD::PagedLOD(const PagedLOD& plod,const CopyOp& copyop):
void PagedLOD::traverse(NodeVisitor& nv)
{
// set the frame number of the traversal so that external nodes can find out how active this
// node is.
if (nv.getFrameStamp()) setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
@ -179,7 +184,7 @@ bool PagedLOD::removeChild( Node *child )
return Group::removeChild(child);
}
void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
bool PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
{
if (_children.size()>_numChildrenThatCannotBeExpired)
{
@ -187,7 +192,8 @@ void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren
{
osg::Node* nodeToRemove = _children[_children.size()-1].get();
removedChildren.push_back(nodeToRemove);
Group::removeChild(nodeToRemove);
return Group::removeChild(nodeToRemove);
}
}
return false;
}

View File

@ -77,6 +77,18 @@ unsigned int DrawArrayLengths::getNumIndices() const
return count;
}
DrawElementsUByte::~DrawElementsUByte()
{
for(unsigned int i=0;i<_vboList.size();++i)
{
if (_vboList[i] != 0)
{
Drawable::deleteVertexBufferObject(i,_vboList[i]);
_vboList[i] = 0;
}
}
}
void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
@ -125,6 +137,18 @@ void DrawElementsUByte::offsetIndices(int offset)
}
DrawElementsUShort::~DrawElementsUShort()
{
for(unsigned int i=0;i<_vboList.size();++i)
{
if (_vboList[i] != 0)
{
Drawable::deleteVertexBufferObject(i,_vboList[i]);
_vboList[i] = 0;
}
}
}
void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
@ -173,6 +197,18 @@ void DrawElementsUShort::offsetIndices(int offset)
}
DrawElementsUInt::~DrawElementsUInt()
{
for(unsigned int i=0;i<_vboList.size();++i)
{
if (_vboList[i] != 0)
{
Drawable::deleteVertexBufferObject(i,_vboList[i]);
_vboList[i] = 0;
}
}
}
void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)

View File

@ -37,6 +37,10 @@ using namespace osg;
#define GL_STORAGE_SHARED_APPLE 0x85BF
#endif
unsigned int Texture::s_numberTextureReusedLastInLastFrame = 0;
unsigned int Texture::s_numberNewTextureInLastFrame = 0;
unsigned int Texture::s_numberDeletedTextureInLastFrame = 0;
Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(unsigned int /*contextID*/,GLenum target)
{
GLuint id;
@ -45,6 +49,8 @@ Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(uns
return new Texture::TextureObject(id,target);
}
static int s_number = 0;
Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(unsigned int /*contextID*/,
GLenum target,
GLint numMipmapLevels,
@ -54,6 +60,10 @@ Texture::TextureObject* Texture::TextureObjectManager::generateTextureObject(uns
GLsizei depth,
GLint border)
{
++s_number;
++s_numberNewTextureInLastFrame;
// notify(NOTICE)<<"creating new texture object "<<s_number<<std::endl;
// no useable texture object found so return 0
GLuint id;
glGenTextures( 1L, &id );
@ -85,7 +95,9 @@ Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsign
Texture::TextureObject* textureObject = (*itr).release();
tol.erase(itr);
//notify(INFO)<<"reusing texture object "<<textureObject<<std::endl;
// notify(NOTICE)<<"reusing texture object "<<std::endl;
++s_numberTextureReusedLastInLastFrame;
return textureObject;
}
@ -125,11 +137,14 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
unsigned int numObjectsDeleted = 0;
unsigned int maxNumObjectsToDelete = 4;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
unsigned int numTexturesDeleted = 0;
{
#ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
@ -151,16 +166,19 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d
double expiryTime = currentTime-_expiryDelay;
unsigned int numTexturesDeleted = 0;
for(itr=tol.begin();
itr!=tol.end() && elapsedTime<availableTime;
itr!=tol.end() && elapsedTime<availableTime && numObjectsDeleted<maxNumObjectsToDelete;
)
{
if ((*itr)->_timeStamp<expiryTime)
{
--s_number;
++s_numberDeletedTextureInLastFrame;
glDeleteTextures( 1L, &((*itr)->_id));
itr = tol.erase(itr);
++numTexturesDeleted;
++numObjectsDeleted;
}
else
{
@ -169,9 +187,10 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
if (numTexturesDeleted) notify(osg::INFO)<<"Number of Texture's deleted = "<<numTexturesDeleted<<std::endl;
}
}
elapsedTime = timer.delta_s(start_tick,timer.tick());
// if (numTexturesDeleted) notify(osg::NOTICE)<<"Number of Texture's deleted = "<<numTexturesDeleted<<" new total "<<s_number<<" elapsed time"<<elapsedTime<<std::endl;
availableTime -= elapsedTime;
}

View File

@ -1,4 +1,4 @@
#include <osgDB/DatabasePager>
#include <osgDB/DatabasePager>
#include <osgDB/ReadFile>
#include <osg/Geode>
@ -110,7 +110,8 @@ void DatabasePager::clear()
}
// no mutex??
_pagedLODList.clear();
_activePagedLODList.clear();
_inactivePagedLODList.clear();
// ??
// _activeGraphicsContexts
@ -313,6 +314,9 @@ public:
{
apply(drawable->getStateSet());
// drawable->setUseDisplayList(false);
// drawable->setUseVertexBufferObjects(true);
if (drawable->getUseDisplayList() || drawable->getUseVertexBufferObjects())
{
//osg::notify(osg::INFO)<<"Found compilable drawable"<<std::endl;
@ -351,7 +355,7 @@ void DatabasePager::run()
// need to set the texture object manager to be able to reuse textures
// by keeping deleted texture objects around for 10 seconds after being deleted.
osg::Texture::getTextureObjectManager()->setExpiryDelay(10.0f);
osg::Texture::getTextureObjectManager()->setExpiryDelay(30.0f);
bool firstTime = true;
@ -498,12 +502,41 @@ void DatabasePager::run()
firstTime = false;
}
} while (!testCancel());
} while (!testCancel() && !_done);
}
void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
{
static double s_previous = timeStamp;
double timeDelta = timeStamp-s_previous;
if (timeDelta>0.02)
{
std::string str;
if (osg::Texture::s_numberTextureReusedLastInLastFrame > 0) str += " RT ";
if (osg::Texture::s_numberNewTextureInLastFrame > 0) str += " NT ";
if (osg::Texture::s_numberDeletedTextureInLastFrame > 0) str += " DT ";
if (osg::Drawable::s_numberNewDrawablesInLastFrame > 0) str += " ND ";
if (osg::Drawable::s_numberDeletedDrawablesInLastFrame > 0) str += " DD ";
if (str.empty()) str += " ?? ";
osg::notify(osg::NOTICE)<<"addLoadedDataToSceneGraph "<<timeDelta;
osg::notify(osg::NOTICE)<<" ************* FRAME DROP ********** "<<str<<std::dec<<std::endl;
osg::notify(osg::NOTICE)<<"\tosg::Texture::s_numberTextureReusedLastInLastFrame = "<<osg::Texture::s_numberTextureReusedLastInLastFrame<<std::endl;
osg::notify(osg::NOTICE)<<"\tosg::Texture::s_numberNewTextureInLastFrame = "<<osg::Texture::s_numberNewTextureInLastFrame <<std::endl;
osg::notify(osg::NOTICE)<<"\tosg::Texture::s_numberDeletedTextureInLastFrame = "<<osg::Texture::s_numberDeletedTextureInLastFrame <<std::endl;
osg::notify(osg::NOTICE)<<"\tosg::Drawable::s_numberNewDrawablesInLastFrame = "<<osg::Drawable::s_numberNewDrawablesInLastFrame <<std::endl;
osg::notify(osg::NOTICE)<<"\tosg::Drawable::s_numberDeletedDrawablesInLastFrame = "<<osg::Drawable::s_numberDeletedDrawablesInLastFrame <<std::endl;
}
s_previous = timeStamp;
// osg::Timer_t before = osg::Timer::instance()->tick();
DatabaseRequestList localFileLoadedList;
// get the dat for the _dataToCompileList, leaving it empty via a std::vector<>.swap.
@ -538,57 +571,130 @@ void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
}
// osg::notify(osg::NOTICE)<<"Done DatabasePager::addLoadedDataToSceneGraph"<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms objects"<<localFileLoadedList.size()<<std::endl;
osg::Texture::s_numberTextureReusedLastInLastFrame = 0;
osg::Texture::s_numberNewTextureInLastFrame = 0;
osg::Texture::s_numberDeletedTextureInLastFrame = 0;
osg::Drawable::s_numberNewDrawablesInLastFrame = 0;
osg::Drawable::s_numberDeletedDrawablesInLastFrame = 0;
}
/** Helper class used clean up PagedLODList.*/
class CleanUpPagedLODVisitor : public osg::NodeVisitor
{
public:
CleanUpPagedLODVisitor(DatabasePager::PagedLODList& pagedLODList):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_pagedLODList(pagedLODList) {}
virtual void apply(osg::PagedLOD& node)
{
DatabasePager::PagedLODList::iterator pitr = _pagedLODList.find(&node);
if (pitr != _pagedLODList.end()) _pagedLODList.erase(pitr);
traverse(node);
}
DatabasePager::PagedLODList& _pagedLODList;
};
void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
{
// osg::notify(osg::NOTICE)<<"DatabasePager::removeExpiredSubgraphs()"<<std::endl;
//osg::notify(osg::NOTICE)<<"DatabasePager::removeExpiredSubgraphs()"<<std::endl;
// osg::Timer_t before = osg::Timer::instance()->tick();
double expiryTime = currentFrameTime - _expiryDelay;
osg::NodeList childrenRemoved;
//osg::notify(osg::INFO)<<"DatabasePager::removeExpiredSubgraphs("<<expiryTime<<") "<<std::endl;
for(PagedLODList::iterator itr = _pagedLODList.begin();
itr!=_pagedLODList.end();
++itr)
for(PagedLODList::iterator active_itr = _activePagedLODList.begin();
active_itr!=_activePagedLODList.end();
)
{
const osg::PagedLOD* plod = itr->get();
const_cast<osg::PagedLOD*>(plod)->removeExpiredChildren(expiryTime,childrenRemoved);
const osg::PagedLOD* plod = active_itr->get();
bool remove_plod = false;
if (plod->referenceCount()<=1)
{
// prune PageLOD's that are no longer externally referenced
childrenRemoved.push_back(const_cast<osg::PagedLOD*>(plod));
//osg::notify(osg::NOTICE)<<"_activePagedLODList : pruning no longer externally referenced"<<std::endl;
remove_plod = true;
}
else if (plod->getFrameNumberOfLastTraversal()<_frameNumber)
{
// osg::notify(osg::NOTICE)<<"_activePagedLODList : moving PageLOD to inactive list"<<std::endl;
_inactivePagedLODList.push_back(*active_itr);
remove_plod = true;
}
if (remove_plod)
{
PagedLODList::iterator itr_to_erase = active_itr;
++active_itr;
_activePagedLODList.erase(itr_to_erase);
}
else
{
++active_itr;
}
}
unsigned int i = 0;
unsigned int numberOfPagedLODToTest = _inactivePagedLODList.size();
unsigned int targetNumOfInActivePagedLODs = 1000;
unsigned int targetNumOfRemovedChildPagedLODs = 0;
if (_inactivePagedLODList.size()>targetNumOfInActivePagedLODs) targetNumOfRemovedChildPagedLODs = _inactivePagedLODList.size()-targetNumOfInActivePagedLODs;
if (targetNumOfRemovedChildPagedLODs>1) targetNumOfRemovedChildPagedLODs=1;
// filter out singly referenced PagedLOD and move reactivated PagedLOD into the active list
for(PagedLODList::iterator inactive_itr = _inactivePagedLODList.begin();
inactive_itr!=_inactivePagedLODList.end();
)
{
const osg::PagedLOD* plod = inactive_itr->get();
bool remove_plod = false;
if (plod->referenceCount()<=1)
{
// prune PageLOD's that are no longer externally referenced
childrenRemoved.push_back(const_cast<osg::PagedLOD*>(plod));
//osg::notify(osg::NOTICE)<<"_activePagedLODList : pruning no longer externally referenced"<<std::endl;
remove_plod = true;
}
else if (plod->getFrameNumberOfLastTraversal()>=_frameNumber)
{
// osg::notify(osg::NOTICE)<<"_inactivePagedLODList : moving PageLOD to active list"<<std::endl;
// found a reactivated pagedLOD's need to put it back in the active list.
_activePagedLODList.push_back(*inactive_itr);
remove_plod = true;
}
if (remove_plod)
{
PagedLODList::iterator itr_to_erase = inactive_itr;
++inactive_itr;
_inactivePagedLODList.erase(itr_to_erase);
}
else
{
// if (i<numberOfPagedLODToTest)
if (childrenRemoved.size()<targetNumOfRemovedChildPagedLODs)
{
// check for removing expired children.
if (const_cast<osg::PagedLOD*>(plod)->removeExpiredChildren(currentFrameTime,childrenRemoved))
// if (const_cast<osg::PagedLOD*>(plod)->removeExpiredChildren(expiryTime,childrenRemoved))
{
//osg::notify(osg::NOTICE)<<"Some children removed from PLod"<<std::endl;
}
else
{
// osg::notify(osg::NOTICE)<<"no children removed from PLod"<<std::endl;
}
}
++inactive_itr;
++i;
}
}
//osg::notify(osg::NOTICE)<<"_activePagedLODList.size()="<<_activePagedLODList.size()<<"\t_inactivePagedLODList.size()="<<_inactivePagedLODList.size()<<std::endl;
// osg::notify(osg::NOTICE)<<" number stale "<<numberStale<<" number active "<<_pagedLODList.size()-numberStale<<std::endl;
//double t = osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick());
//osg::notify(osg::NOTICE)<<" time 1 "<<t<<" ms "<<_pagedLODList.size()<<" pagedLOD's"<<std::endl;
//osg::notify(osg::NOTICE)<<" average time = "<<t/(double)_pagedLODList.size()<<" ms/per PagedLOD"<<std::endl;
if (!childrenRemoved.empty())
{
// clean up local ref's to paged lods
CleanUpPagedLODVisitor cuplv(_pagedLODList);
for (osg::NodeList::iterator critr = childrenRemoved.begin();
critr!=childrenRemoved.end();
++critr)
{
(*critr)->accept(cuplv);
}
// pass the objects across to the database pager delete list
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_childrenToDeleteListMutex);
@ -604,6 +710,7 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
childrenRemoved.clear();
}
// osg::notify(osg::NOTICE)<<" time 2 "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms "<<std::endl;
if (osgDB::Registry::instance()->getSharedStateManager())
@ -612,6 +719,10 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
// update the Registry object cache.
osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExtenalReferences(currentFrameTime);
osgDB::Registry::instance()->removeExpiredObjectsInCache(expiryTime);
// osg::notify(osg::NOTICE)<<"Done DatabasePager::removeExpiredSubgraphs() "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms "<<std::endl;
}
@ -626,7 +737,7 @@ public:
virtual void apply(osg::PagedLOD& plod)
{
_pagedLODList.insert(&plod);
_pagedLODList.push_back(&plod);
traverse(plod);
}
@ -636,7 +747,7 @@ public:
void DatabasePager::registerPagedLODs(osg::Node* subgraph)
{
FindPagedLODsVisitor fplv(_pagedLODList);
FindPagedLODsVisitor fplv(_activePagedLODList);
if (subgraph) subgraph->accept(fplv);
}
@ -660,6 +771,7 @@ bool DatabasePager::getCompileGLObjectsForContexID(unsigned int contextID)
void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
{
// osg::notify(osg::NOTICE)<<"DatabasePager::compileGLObjects "<<_frameNumber<<std::endl;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
@ -686,6 +798,17 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
}
if (litr != _dataToCompileList.end())
{
if (_deleteRemovedSubgraphsInDatabaseThread)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_childrenToDeleteListMutex);
for(DatabaseRequestList::iterator ditr=litr;
ditr!=_dataToCompileList.end();
++ditr)
{
_childrenToDeleteList.push_back((*ditr)->_loadedModel.get());
}
}
//osg::notify(osg::NOTICE)<<"Pruning "<<_dataToCompileList.size()-i<<std::endl;
_dataToCompileList.erase(litr,_dataToCompileList.end());
}
@ -695,13 +818,16 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
}
};
unsigned int numObjectsCompiled = 0;
unsigned int maxNumObjectsToCompile = 4;
// while there are valid databaseRequest's in the to compile list and there is
// sufficient time left compile each databaseRequest's stateset and drawables.
while (databaseRequest.valid() && elapsedTime<availableTime)
while (databaseRequest.valid() && elapsedTime<availableTime && numObjectsCompiled<maxNumObjectsToCompile)
{
DataToCompileMap& dcm = databaseRequest->_dataToCompileMap;
DataToCompile& dtc = dcm[state.getContextID()];
if (!dtc.first.empty() && (elapsedTime+estimatedTextureDuration)<availableTime)
if (!dtc.first.empty() && (elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<maxNumObjectsToCompile)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
@ -711,7 +837,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
//osg::notify(osg::INFO)<<"Compiling statesets"<<std::endl;
StateSetList::iterator itr=sslist.begin();
for(;
itr!=sslist.end() && (elapsedTime+estimatedTextureDuration)<availableTime;
itr!=sslist.end() && (elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<maxNumObjectsToCompile;
++itr)
{
//osg::notify(osg::INFO)<<" Compiling stateset "<<(*itr).get()<<std::endl;
@ -728,19 +854,21 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
// estimate the duration of the compile based on current compile duration.
estimatedTextureDuration = (elapsedTime-startCompileTime);
++numObjectsCompiled;
}
// remove the compiled stateset from the list.
sslist.erase(sslist.begin(),itr);
}
if (!dtc.second.empty() && (elapsedTime+estimatedDrawableDuration)<availableTime)
if (!dtc.second.empty() && (elapsedTime+estimatedDrawableDuration)<availableTime && numObjectsCompiled<maxNumObjectsToCompile)
{
// we have Drawable's to compile
//osg::notify(osg::INFO)<<"Compiling drawables"<<std::endl;
DrawableList& dwlist = dtc.second;
DrawableList::iterator itr=dwlist.begin();
for(;
itr!=dwlist.end() && (elapsedTime+estimatedDrawableDuration)<availableTime;
itr!=dwlist.end() && (elapsedTime+estimatedDrawableDuration)<availableTime && numObjectsCompiled<maxNumObjectsToCompile;
++itr)
{
//osg::notify(osg::INFO)<<" Compiling drawable "<<(*itr).get()<<std::endl;
@ -750,6 +878,9 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
// estimate the duration of the compile based on current compile duration.
estimatedDrawableDuration = (elapsedTime-startCompileTime);
++numObjectsCompiled;
}
// remove the compiled drawables from the list.
dwlist.erase(dwlist.begin(),itr);
@ -803,6 +934,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime)
availableTime -= elapsedTime;
// osg::notify(osg::NOTICE)<<"elapsedTime="<<elapsedTime<<" time remaining ="<<availableTime<<std::endl;
//osg::notify(osg::NOTICE)<<"estimatedTextureDuration="<<estimatedTextureDuration;
//osg::notify(osg::NOTICE)<<"\testimatedDrawableDuration="<<estimatedDrawableDuration<<std::endl;
}

View File

@ -506,7 +506,7 @@ public:
sh.drawImplementation(camera);
osgDB::DatabasePager* dp = osgDB::Registry::instance()->getDatabasePager();
#if 0
#if 1
double availableTime = 0.0025; // 2.5 ms
// flush deleted GL objects.
@ -531,7 +531,7 @@ public:
virtual void operator()(const Producer::Camera&)
{
#if 0
osgDB::DatabasePager* dp = osgDB::Registry::instance()->getDatabasePager();
double availableTime = 0.0025; // 2.5 ms
@ -541,7 +541,7 @@ public:
// compile any GL objects that are required.
if (dp) dp->compileGLObjects(*(_sceneView->getState()),availableTime);
#endif
}
osg::ref_ptr<osgUtil::SceneView> _sceneView;