Added preliminary support for thread safety in various delete GLobjects code

This commit is contained in:
Robert Osfield
2004-07-21 19:16:49 +00:00
parent b0a371ddb0
commit c9f5749c12
7 changed files with 188 additions and 111 deletions

View File

@@ -647,6 +647,9 @@ class SG_EXPORT Texture : public osg::StateAttribute
TextureObjectListMap _textureObjectListMap;
// mutex to keep access serialized.
OpenThreads::Mutex _mutex;
};

View File

@@ -33,13 +33,17 @@ using namespace osg;
// is set. Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
typedef std::list<GLuint> DisplayListList;
typedef std::map<GLuint,DisplayListList> DeletedDisplayListCache;
static OpenThreads::Mutex s_mutex_deletedDisplayListCache;
static DeletedDisplayListCache s_deletedDisplayListCache;
static DeletedDisplayListCache s_deletedVertexBufferObjectCache;
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj)
{
if (globj!=0)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
#endif
// insert the globj into the cache for the appropriate context.
s_deletedDisplayListCache[contextID].push_back(globj);
}
@@ -58,31 +62,45 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentT
unsigned int noDeleted = 0;
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
if (citr!=s_deletedDisplayListCache.end())
{
DisplayListList& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
ditr!=dll.end() && elapsedTime<availableTime;
)
{
glDeleteLists(*ditr,1);
ditr = dll.erase(ditr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
}
}
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
#endif
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
if (citr!=s_deletedDisplayListCache.end())
{
DisplayListList& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
ditr!=dll.end() && elapsedTime<availableTime;
)
{
glDeleteLists(*ditr,1);
ditr = dll.erase(ditr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
}
}
}
if (noDeleted!=0) notify(INFO)<<"Number display lists deleted = "<<noDeleted<<std::endl;
availableTime -= elapsedTime;
}
static OpenThreads::Mutex s_mutex_deletedVertexBufferObjectCache;
static DeletedDisplayListCache s_deletedVertexBufferObjectCache;
void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj)
{
if (globj!=0)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexBufferObjectCache);
#endif
// insert the globj into the cache for the appropriate context.
s_deletedVertexBufferObjectCache[contextID].push_back(globj);
}
@@ -100,28 +118,33 @@ void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*c
double elapsedTime = 0.0;
DeletedDisplayListCache::iterator citr = s_deletedVertexBufferObjectCache.find(contextID);
if (citr!=s_deletedVertexBufferObjectCache.end())
{
const Extensions* extensions = getExtensions(contextID,true);
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexBufferObjectCache);
#endif
unsigned int noDeleted = 0;
DisplayListList& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
ditr!=dll.end() && elapsedTime<availableTime;
)
DeletedDisplayListCache::iterator citr = s_deletedVertexBufferObjectCache.find(contextID);
if (citr!=s_deletedVertexBufferObjectCache.end())
{
extensions->glDeleteBuffers(1,&(*ditr));
ditr = dll.erase(ditr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
}
const Extensions* extensions = getExtensions(contextID,true);
if (noDeleted!=0) notify(osg::INFO)<<"Number VBOs deleted = "<<noDeleted<<std::endl;
}
unsigned int noDeleted = 0;
DisplayListList& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
ditr!=dll.end() && elapsedTime<availableTime;
)
{
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;
}

View File

@@ -25,12 +25,18 @@ using namespace osg;
// is set.
typedef std::list<GLuint> FragmentProgramObjectList;
typedef std::map<unsigned int,FragmentProgramObjectList> DeletedFragmentProgramObjectCache;
static OpenThreads::Mutex s_mutex_deletedFragmentProgramObjectCache;
static DeletedFragmentProgramObjectCache s_deletedFragmentProgramObjectCache;
void FragmentProgram::deleteFragmentProgramObject(unsigned int contextID,GLuint handle)
{
if (handle!=0)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
#endif
// insert the handle into the cache for the appropriate context.
s_deletedFragmentProgramObjectCache[contextID].push_back(handle);
}
@@ -46,24 +52,29 @@ void FragmentProgram::flushDeletedFragmentProgramObjects(unsigned int contextID,
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
DeletedFragmentProgramObjectCache::iterator citr = s_deletedFragmentProgramObjectCache.find(contextID);
if (citr!=s_deletedFragmentProgramObjectCache.end())
{
const Extensions* extensions = getExtensions(contextID,true);
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
#endif
FragmentProgramObjectList& vpol = citr->second;
for(FragmentProgramObjectList::iterator titr=vpol.begin();
titr!=vpol.end() && elapsedTime<availableTime;
)
DeletedFragmentProgramObjectCache::iterator citr = s_deletedFragmentProgramObjectCache.find(contextID);
if (citr!=s_deletedFragmentProgramObjectCache.end())
{
extensions->glDeletePrograms( 1L, &(*titr ) );
titr = vpol.erase(titr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
const Extensions* extensions = getExtensions(contextID,true);
FragmentProgramObjectList& vpol = citr->second;
for(FragmentProgramObjectList::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;
}

View File

@@ -70,6 +70,10 @@ Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsign
GLsizei depth,
GLint border)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
#endif
TextureObjectList& tol = _textureObjectListMap[contextID];
for(TextureObjectList::iterator itr = tol.begin();
itr != tol.end();
@@ -94,6 +98,10 @@ Texture::TextureObject* Texture::TextureObjectManager::reuseTextureObject(unsign
void Texture::TextureObjectManager::addTextureObjects(Texture::TextureObjectListMap& toblm)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
#endif
for(TextureObjectListMap::iterator itr = toblm.begin();
itr != toblm.end();
++itr)
@@ -105,6 +113,8 @@ void Texture::TextureObjectManager::addTextureObjects(Texture::TextureObjectList
void Texture::TextureObjectManager::addTextureObjectsFrom(Texture& texture)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
texture.takeTextureObjects(_textureObjectListMap);
}
@@ -113,47 +123,54 @@ void Texture::TextureObjectManager::flushTextureObjects(unsigned int contextID,d
// 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;
TextureObjectListMap::iterator tmitr = _textureObjectListMap.find(contextID);
if (tmitr!=_textureObjectListMap.end())
{
TextureObjectList& tol = tmitr->second;
// reset the time of any uninitialized objects.
TextureObjectList::iterator itr;
for(itr=tol.begin();
itr!=tol.end();
++itr)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
#endif
TextureObjectListMap::iterator tmitr = _textureObjectListMap.find(contextID);
if (tmitr!=_textureObjectListMap.end())
{
if ((*itr)->_timeStamp==0.0) (*itr)->_timeStamp=currentTime;
}
TextureObjectList& tol = tmitr->second;
double expiryTime = currentTime-_expiryDelay;
unsigned int numTexturesDeleted = 0;
for(itr=tol.begin();
itr!=tol.end() && elapsedTime<availableTime;
)
{
if ((*itr)->_timeStamp<expiryTime)
// reset the time of any uninitialized objects.
TextureObjectList::iterator itr;
for(itr=tol.begin();
itr!=tol.end();
++itr)
{
glDeleteTextures( 1L, &((*itr)->_id));
itr = tol.erase(itr);
++numTexturesDeleted;
if ((*itr)->_timeStamp==0.0) (*itr)->_timeStamp=currentTime;
}
else
{
++itr;
}
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
if (numTexturesDeleted) notify(osg::INFO)<<"Number of Texture's deleted = "<<numTexturesDeleted<<std::endl;
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;
}
}
availableTime -= elapsedTime;
}

View File

@@ -25,12 +25,18 @@ using namespace osg;
// is set.
typedef std::list<GLuint> VertexProgramObjectList;
typedef std::map<unsigned int,VertexProgramObjectList> DeletedVertexProgramObjectCache;
static OpenThreads::Mutex s_mutex_deletedVertexProgramObjectCache;
static DeletedVertexProgramObjectCache s_deletedVertexProgramObjectCache;
void VertexProgram::deleteVertexProgramObject(unsigned int contextID,GLuint handle)
{
if (handle!=0)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexProgramObjectCache);
#endif
// insert the handle into the cache for the appropriate context.
s_deletedVertexProgramObjectCache[contextID].push_back(handle);
}
@@ -46,24 +52,30 @@ void VertexProgram::flushDeletedVertexProgramObjects(unsigned int contextID,doub
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
DeletedVertexProgramObjectCache::iterator citr = s_deletedVertexProgramObjectCache.find(contextID);
if (citr!=s_deletedVertexProgramObjectCache.end())
{
const Extensions* extensions = getExtensions(contextID,true);
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexProgramObjectCache);
#endif
VertexProgramObjectList& vpol = citr->second;
for(VertexProgramObjectList::iterator titr=vpol.begin();
titr!=vpol.end() && elapsedTime<availableTime;
)
DeletedVertexProgramObjectCache::iterator citr = s_deletedVertexProgramObjectCache.find(contextID);
if (citr!=s_deletedVertexProgramObjectCache.end())
{
extensions->glDeletePrograms( 1L, &(*titr ) );
titr = vpol.erase(titr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
const Extensions* extensions = getExtensions(contextID,true);
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;
}

View File

@@ -28,8 +28,8 @@ DatabasePager::DatabasePager()
_threadPriorityDuringFrame = PRIORITY_MIN;
_threadPriorityOutwithFrame = PRIORITY_MIN;
_changeAutoUnRef = false;
_valueAutoUnRef = false;
_changeAutoUnRef = true;
_valueAutoUnRef = true;
_changeAnisotropy = false;
_valueAnisotropy = 1.0f;

View File

@@ -75,12 +75,17 @@ private:
typedef std::list<GLhandleARB> GL2ObjectList;
typedef std::map<unsigned int, GL2ObjectList> DeletedGL2ObjectCache;
static OpenThreads::Mutex s_mutex_deletedGL2ObjectCache;
static DeletedGL2ObjectCache s_deletedGL2ObjectCache;
void ProgramObject::deleteObject(unsigned int contextID, GLhandleARB handle)
{
if (handle!=0)
{
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGL2ObjectCache);
#endif
// add handle to the cache for the appropriate context.
s_deletedGL2ObjectCache[contextID].push_back(handle);
}
@@ -95,30 +100,36 @@ void ProgramObject::flushDeletedGL2Objects(unsigned int contextID,double /*curre
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
DeletedGL2ObjectCache::iterator citr = s_deletedGL2ObjectCache.find(contextID);
if( citr != s_deletedGL2ObjectCache.end() )
{
const Extensions* extensions = Extensions::Get(contextID,true);
#ifdef THREAD_SAFE_DELETE_LISTS
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedGL2ObjectCache);
#endif
if (!extensions->isGlslSupported())
{
// can we really get here?
osg::notify(osg::WARN) << "flushDeletedGL2Objects not supported by OpenGL driver" << std::endl;
return;
}
GL2ObjectList& vpObjectList = citr->second;
for(GL2ObjectList::iterator titr=vpObjectList.begin();
titr!=vpObjectList.end() && elapsedTime<availableTime;
)
DeletedGL2ObjectCache::iterator citr = s_deletedGL2ObjectCache.find(contextID);
if( citr != s_deletedGL2ObjectCache.end() )
{
extensions->glDeleteObject( *titr );
titr = vpObjectList.erase( titr );
elapsedTime = timer.delta_s(start_tick,timer.tick());
const Extensions* extensions = Extensions::Get(contextID,true);
if (!extensions->isGlslSupported())
{
// can we really get here?
osg::notify(osg::WARN) << "flushDeletedGL2Objects not supported by OpenGL driver" << std::endl;
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;
}