Improvements to the handling of deletion of OpenGL rendering objets such as
display lists and textures object such that they can be deleted according to an available amount of time given to do deletes.
This commit is contained in:
@@ -34,15 +34,6 @@
|
||||
|
||||
namespace osgGL2 {
|
||||
|
||||
/** use deleteObject instead of glDeleteObject to allow
|
||||
* GL2 Objects to cached until they can be deleted
|
||||
* by the OpenGL context in which they were created, specified
|
||||
* by contextID.*/
|
||||
extern OSGGL2_EXPORT void DeleteObject(unsigned int contextID, GLhandleARB handle);
|
||||
|
||||
/** flush all the cached glProgramObjects which need to be deleted
|
||||
* in the OpenGL context related to contextID.*/
|
||||
extern OSGGL2_EXPORT void FlushDeletedGL2Objects(unsigned int contextID);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -87,6 +78,16 @@ class OSGGL2_EXPORT ProgramObject : public osg::StateAttribute
|
||||
void dirtyProgramObject();
|
||||
|
||||
void addShader( ShaderObject* shader );
|
||||
|
||||
/** use deleteObject instead of glDeleteObject to allow
|
||||
* GL2 Objects to cached until they can be deleted
|
||||
* by the OpenGL context in which they were created, specified
|
||||
* by contextID.*/
|
||||
static void deleteObject(unsigned int contextID, GLhandleARB handle);
|
||||
|
||||
/** flush all the cached glProgramObjects which need to be deleted
|
||||
* in the OpenGL context related to contextID.*/
|
||||
static void flushDeletedGL2Objects(unsigned int contextID,double currentTime, double& availableTime);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -19,18 +19,19 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/Node>
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
// 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.
|
||||
typedef std::vector<GLuint> DisplayListVector;
|
||||
typedef std::map<GLuint,DisplayListVector> DeletedDisplayListCache;
|
||||
typedef std::list<GLuint> DisplayListList;
|
||||
typedef std::map<GLuint,DisplayListList> DeletedDisplayListCache;
|
||||
static DeletedDisplayListCache s_deletedDisplayListCache;
|
||||
static DeletedDisplayListCache s_deletedVertexBufferObjectCache;
|
||||
|
||||
@@ -45,25 +46,36 @@ void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj)
|
||||
|
||||
/** flush all the cached display list which need to be deleted
|
||||
* in the OpenGL context related to contextID.*/
|
||||
void Drawable::flushDeletedDisplayLists(unsigned int contextID,double currentTime, double& availableTime)
|
||||
void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentTime*/, double& availableTime)
|
||||
{
|
||||
// if no time available don't try to flush objects.
|
||||
if (availableTime<=0.0) return;
|
||||
|
||||
const osg::Timer& timer = *osg::Timer::instance();
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
unsigned int noDeleted = 0;
|
||||
|
||||
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
|
||||
if (citr!=s_deletedDisplayListCache.end())
|
||||
{
|
||||
DisplayListVector displayListSet;
|
||||
displayListSet.reserve(1000);
|
||||
|
||||
// this swap will transfer the content of and empty citr->second
|
||||
// in one quick pointer change.
|
||||
displayListSet.swap(citr->second);
|
||||
|
||||
for(DisplayListVector::iterator gitr=displayListSet.begin();
|
||||
gitr!=displayListSet.end();
|
||||
++gitr)
|
||||
DisplayListList& dll = citr->second;
|
||||
|
||||
for(DisplayListList::iterator ditr=dll.begin();
|
||||
ditr!=dll.end() && elapsedTime<availableTime;
|
||||
)
|
||||
{
|
||||
glDeleteLists(*gitr,1);
|
||||
}
|
||||
glDeleteLists(*ditr,1);
|
||||
ditr = dll.erase(ditr);
|
||||
elapsedTime = timer.delta_s(start_tick,timer.tick());
|
||||
++noDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
if (noDeleted!=0) std::cout<<"Number display lists deleted = "<<noDeleted<<std::endl;
|
||||
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj)
|
||||
@@ -77,27 +89,40 @@ void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj)
|
||||
|
||||
/** flush all the cached display list which need to be deleted
|
||||
* in the OpenGL context related to contextID.*/
|
||||
void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double currentTime, double& availableTime)
|
||||
void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
|
||||
{
|
||||
// if no time available don't try to flush objects.
|
||||
if (availableTime<=0.0) return;
|
||||
|
||||
const osg::Timer& timer = *osg::Timer::instance();
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
|
||||
DeletedDisplayListCache::iterator citr = s_deletedVertexBufferObjectCache.find(contextID);
|
||||
if (citr!=s_deletedVertexBufferObjectCache.end())
|
||||
{
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
|
||||
DisplayListVector displayListSet;
|
||||
displayListSet.reserve(1000);
|
||||
|
||||
// this swap will transfer the content of and empty citr->second
|
||||
// in one quick pointer change.
|
||||
displayListSet.swap(citr->second);
|
||||
|
||||
for(DisplayListVector::iterator gitr=displayListSet.begin();
|
||||
gitr!=displayListSet.end();
|
||||
++gitr)
|
||||
unsigned int noDeleted = 0;
|
||||
|
||||
DisplayListList& dll = citr->second;
|
||||
|
||||
for(DisplayListList::iterator ditr=dll.begin();
|
||||
ditr!=dll.end() && elapsedTime<availableTime;
|
||||
)
|
||||
{
|
||||
extensions->glDeleteBuffers(1,&(*gitr));
|
||||
extensions->glDeleteBuffers(1,&(*ditr));
|
||||
ditr = dll.erase(ditr);
|
||||
elapsedTime = timer.delta_s(start_tick,timer.tick());
|
||||
++noDeleted;
|
||||
}
|
||||
|
||||
if (noDeleted!=0) notify(osg::INFO)<<"Number VBOs deleted = "<<noDeleted<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <osg/State>
|
||||
#include <osg/Notify>
|
||||
#include <osg/GLU>
|
||||
#include <osg/Timer>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
@@ -95,41 +96,53 @@ void Texture::TextureObjectManager::addTextureObjectsFrom(Texture& texture)
|
||||
texture.takeTextureObjects(_textureObjectListMap);
|
||||
}
|
||||
|
||||
void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,double currentTime, double& availbleTime)
|
||||
void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,double currentTime, double& availableTime)
|
||||
{
|
||||
// if no time available don't try to flush objects.
|
||||
if (availableTime<=0.0) return;
|
||||
|
||||
TextureObjectList& tol = _textureObjectListMap[contextID];
|
||||
const osg::Timer& timer = *osg::Timer::instance();
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
// reset the time of any uninitialized objects.
|
||||
TextureObjectList::iterator itr;
|
||||
for(itr=tol.begin();
|
||||
itr!=tol.end();
|
||||
++itr)
|
||||
TextureObjectListMap::iterator tmitr = _textureObjectListMap.find(contextID);
|
||||
if (tmitr!=_textureObjectListMap.end())
|
||||
{
|
||||
if ((*itr)->_timeStamp==0.0) (*itr)->_timeStamp=currentTime;
|
||||
TextureObjectList& tol = tmitr->second;
|
||||
|
||||
// reset the time of any uninitialized objects.
|
||||
TextureObjectList::iterator itr;
|
||||
for(itr=tol.begin();
|
||||
itr!=tol.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->_timeStamp==0.0) (*itr)->_timeStamp=currentTime;
|
||||
}
|
||||
|
||||
double expiryTime = currentTime-_expiryDelay;
|
||||
|
||||
unsigned int numTexturesDeleted = 0;
|
||||
for(itr=tol.begin();
|
||||
itr!=tol.end() && elapsedTime<availableTime;
|
||||
)
|
||||
{
|
||||
if ((*itr)->_timeStamp<expiryTime)
|
||||
{
|
||||
glDeleteTextures( 1L, &((*itr)->_id));
|
||||
itr = tol.erase(itr);
|
||||
++numTexturesDeleted;
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
elapsedTime = timer.delta_s(start_tick,timer.tick());
|
||||
}
|
||||
|
||||
if (numTexturesDeleted) notify(osg::INFO)<<"Number of Texture's deleted = "<<numTexturesDeleted<<std::endl;
|
||||
}
|
||||
|
||||
_expiryDelay = 10.0;
|
||||
|
||||
double expiryTime = currentTime-_expiryDelay;
|
||||
|
||||
//unsigned int numTexturesDeleted = 0;
|
||||
for(itr=tol.begin();
|
||||
itr!=tol.end();
|
||||
)
|
||||
{
|
||||
if ((*itr)->_timeStamp<expiryTime)
|
||||
{
|
||||
glDeleteTextures( 1L, &((*itr)->_id));
|
||||
itr = tol.erase(itr);
|
||||
//++numTexturesDeleted;
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
//if (numTexturesDeleted) std::cout<<" deleted "<<numTexturesDeleted<<" textures"<<std::endl;
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
static ref_ptr<Texture::TextureObjectManager> s_textureObjectManager;
|
||||
|
||||
@@ -14,14 +14,17 @@
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/VertexProgram>
|
||||
#include <osg/State>
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <list>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
// static cache of deleted vertex programs which can only
|
||||
// by completely deleted once the appropriate OpenGL context
|
||||
// is set.
|
||||
typedef std::vector<GLuint> VertexProgramObjectVector;
|
||||
typedef std::map<unsigned int,VertexProgramObjectVector> DeletedVertexProgramObjectCache;
|
||||
typedef std::list<GLuint> VertexProgramObjectList;
|
||||
typedef std::map<unsigned int,VertexProgramObjectList> DeletedVertexProgramObjectCache;
|
||||
static DeletedVertexProgramObjectCache s_deletedVertexProgramObjectCache;
|
||||
|
||||
void VertexProgram::deleteVertexProgramObject(unsigned int contextID,GLuint handle)
|
||||
@@ -34,30 +37,34 @@ void VertexProgram::deleteVertexProgramObject(unsigned int contextID,GLuint hand
|
||||
}
|
||||
|
||||
|
||||
void VertexProgram::flushDeletedVertexProgramObjects(unsigned int contextID,double currentTime, double& availableTime)
|
||||
void VertexProgram::flushDeletedVertexProgramObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
|
||||
{
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
// if no time available don't try to flush objects.
|
||||
if (availableTime<=0.0) return;
|
||||
|
||||
if (!extensions->isVertexProgramSupported())
|
||||
return;
|
||||
const osg::Timer& timer = *osg::Timer::instance();
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
DeletedVertexProgramObjectCache::iterator citr = s_deletedVertexProgramObjectCache.find(contextID);
|
||||
if (citr!=s_deletedVertexProgramObjectCache.end())
|
||||
{
|
||||
VertexProgramObjectVector vpObjectSet;
|
||||
vpObjectSet.reserve(1000);
|
||||
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
|
||||
// this swap will transfer the content of and empty citr->second
|
||||
// in one quick pointer change.
|
||||
vpObjectSet.swap(citr->second);
|
||||
|
||||
for(VertexProgramObjectVector::iterator titr=vpObjectSet.begin();
|
||||
titr!=vpObjectSet.end();
|
||||
++titr)
|
||||
VertexProgramObjectList& vpol = citr->second;
|
||||
|
||||
for(VertexProgramObjectList::iterator titr=vpol.begin();
|
||||
titr!=vpol.end() && elapsedTime<availableTime;
|
||||
)
|
||||
{
|
||||
extensions->glDeletePrograms( 1L, &(*titr ) );
|
||||
titr = vpol.erase(titr);
|
||||
elapsedTime = timer.delta_s(start_tick,timer.tick());
|
||||
}
|
||||
}
|
||||
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,21 +23,24 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/State>
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <osgGL2/ProgramObject>
|
||||
#include <osgGL2/Extensions>
|
||||
|
||||
#include <list>
|
||||
|
||||
using namespace osgGL2;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// static cache of deleted GL2 objects which may only
|
||||
// by actually deleted in the correct GL context.
|
||||
|
||||
typedef std::vector<GLhandleARB> GL2ObjectVector;
|
||||
typedef std::map<unsigned int, GL2ObjectVector> DeletedGL2ObjectCache;
|
||||
typedef std::list<GLhandleARB> GL2ObjectList;
|
||||
typedef std::map<unsigned int, GL2ObjectList> DeletedGL2ObjectCache;
|
||||
static DeletedGL2ObjectCache s_deletedGL2ObjectCache;
|
||||
|
||||
void osgGL2::DeleteObject(unsigned int contextID, GLhandleARB handle)
|
||||
void ProgramObject::deleteObject(unsigned int contextID, GLhandleARB handle)
|
||||
{
|
||||
if (handle!=0)
|
||||
{
|
||||
@@ -46,28 +49,36 @@ void osgGL2::DeleteObject(unsigned int contextID, GLhandleARB handle)
|
||||
}
|
||||
}
|
||||
|
||||
void osgGL2::FlushDeletedGL2Objects(unsigned int contextID)
|
||||
void ProgramObject::flushDeletedGL2Objects(unsigned int contextID,double /*currentTime*/, double& availableTime)
|
||||
{
|
||||
const Extensions* extensions = Extensions::Get(contextID,true);
|
||||
// if no time available don't try to flush objects.
|
||||
if (availableTime<=0.0) return;
|
||||
|
||||
if (!extensions->isShaderObjectsSupported())
|
||||
return;
|
||||
const osg::Timer& timer = *osg::Timer::instance();
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
DeletedGL2ObjectCache::iterator citr = s_deletedGL2ObjectCache.find(contextID);
|
||||
if( citr != s_deletedGL2ObjectCache.end() )
|
||||
{
|
||||
GL2ObjectVector vpObjectSet;
|
||||
const Extensions* extensions = Extensions::Get(contextID,true);
|
||||
|
||||
// this swap will transfer the content of and empty citr->second
|
||||
// in one quick pointer change.
|
||||
vpObjectSet.swap(citr->second);
|
||||
for( GL2ObjectVector::iterator titr=vpObjectSet.begin();
|
||||
titr!=vpObjectSet.end();
|
||||
++titr )
|
||||
if (!extensions->isShaderObjectsSupported())
|
||||
return;
|
||||
|
||||
GL2ObjectList& vpObjectList = citr->second;
|
||||
|
||||
for(GL2ObjectList::iterator titr=vpObjectList.begin();
|
||||
titr!=vpObjectList.end() && elapsedTime<availableTime;
|
||||
)
|
||||
{
|
||||
extensions->glDeleteObject( *titr );
|
||||
titr = vpObjectList.erase( titr );
|
||||
elapsedTime = timer.delta_s(start_tick,timer.tick());
|
||||
}
|
||||
}
|
||||
|
||||
availableTime -= elapsedTime;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -94,7 +105,7 @@ ProgramObject::~ProgramObject()
|
||||
|
||||
PerContextProgObj* pcpo = _pcpoList[cxt].get();
|
||||
|
||||
DeleteObject( cxt, pcpo->getHandle() );
|
||||
deleteObject( cxt, pcpo->getHandle() );
|
||||
// TODO add shader objects to delete list.
|
||||
_pcpoList[cxt] = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user