Added preliminary support for thread safety in various delete GLobjects code
This commit is contained in:
@@ -647,6 +647,9 @@ class SG_EXPORT Texture : public osg::StateAttribute
|
||||
|
||||
TextureObjectListMap _textureObjectListMap;
|
||||
|
||||
// mutex to keep access serialized.
|
||||
OpenThreads::Mutex _mutex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user