Updates for better DatabasePager peformance w.r.t constant frame rates.

This commit is contained in:
Robert Osfield
2004-09-23 12:27:56 +00:00
parent 1a03a08f4a
commit 5b0739bcf0
4 changed files with 366 additions and 222 deletions

View File

@@ -38,17 +38,17 @@ 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.
typedef std::list<GLuint> DisplayListList;
typedef std::map<GLuint,DisplayListList> DeletedDisplayListCache;
typedef std::multimap<unsigned int,GLuint> DisplayListMap;
typedef std::map<unsigned int,DisplayListMap> DeletedDisplayListCache;
static OpenThreads::Mutex s_mutex_deletedDisplayListCache;
static DeletedDisplayListCache s_deletedDisplayListCache;
GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int /*sizeHint*/)
GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int sizeHint)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
DisplayListList& dll = s_deletedDisplayListCache[contextID];
DisplayListMap& dll = s_deletedDisplayListCache[contextID];
if (dll.empty())
{
++s_numberNewDrawablesInLastFrame;
@@ -56,11 +56,24 @@ GLuint Drawable::generateDisplayList(unsigned int contextID, unsigned int /*size
}
else
{
++s_numberDrawablesReusedLastInLastFrame;
// notify(NOTICE)<<"reusing display list "<<std::endl;
GLuint globj = dll.back();
dll.pop_back();
return globj;
DisplayListMap::iterator itr = dll.lower_bound(sizeHint);
if (itr!=dll.end())
{
// osg::notify(osg::NOTICE)<<"Reusing a display list of size = "<<itr->first<<" for requested size = "<<sizeHint<<std::endl;
++s_numberDrawablesReusedLastInLastFrame;
GLuint globj = itr->second;
dll.erase(itr);
return globj;
}
else
{
// osg::notify(osg::NOTICE)<<"Creating a new display list of size = "<<sizeHint<<" although "<<dll.size()<<" are available"<<std::endl;
++s_numberNewDrawablesInLastFrame;
return glGenLists( 1 );
}
}
}
@@ -75,14 +88,14 @@ unsigned int Drawable::getMinimumNumberOfDisplayListsToRetainInCache()
return s_minimumNumberOfDisplayListsToRetainInCache;
}
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int /*sizeHint*/)
void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj, unsigned int sizeHint)
{
if (globj!=0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedDisplayListCache);
// insert the globj into the cache for the appropriate context.
s_deletedDisplayListCache[contextID].push_back(globj);
s_deletedDisplayListCache[contextID].insert(DisplayListMap::value_type(sizeHint,globj));
}
}
@@ -93,13 +106,13 @@ void Drawable::flushAllDeletedDisplayLists(unsigned int contextID)
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
if (citr!=s_deletedDisplayListCache.end())
{
DisplayListList& dll = citr->second;
DisplayListMap& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
for(DisplayListMap::iterator ditr=dll.begin();
ditr!=dll.end();
++ditr)
{
glDeleteLists(*ditr,1);
glDeleteLists(ditr->second,1);
}
dll.clear();
@@ -123,19 +136,60 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID, double& availabl
DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
if (citr!=s_deletedDisplayListCache.end())
{
DisplayListList& dll = citr->second;
DisplayListMap& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
ditr!=dll.end() && elapsedTime<availableTime && dll.size()>s_minimumNumberOfDisplayListsToRetainInCache;
)
bool trimFromFront = true;
if (trimFromFront)
{
glDeleteLists(*ditr,1);
ditr = dll.erase(ditr);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
++Drawable::s_numberDeletedDrawablesInLastFrame;
}
unsigned int prev_size = dll.size();
DisplayListMap::iterator ditr=dll.begin();
unsigned int maxNumToDelete = (dll.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
for(;
ditr!=dll.end() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
++ditr)
{
glDeleteLists(ditr->second,1);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
++Drawable::s_numberDeletedDrawablesInLastFrame;
}
if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr);
if (noDeleted+dll.size() != prev_size)
{
osg::notify(osg::WARN)<<"Error in delete"<<std::endl;
}
}
else
{
unsigned int prev_size = dll.size();
DisplayListMap::reverse_iterator ditr=dll.rbegin();
unsigned int maxNumToDelete = (dll.size() > s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0;
for(;
ditr!=dll.rend() && elapsedTime<availableTime && noDeleted<maxNumToDelete;
++ditr)
{
glDeleteLists(ditr->second,1);
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
++Drawable::s_numberDeletedDrawablesInLastFrame;
}
if (ditr!=dll.rbegin()) dll.erase(ditr.base(),dll.end());
if (noDeleted+dll.size() != prev_size)
{
osg::notify(osg::WARN)<<"Error in delete"<<std::endl;
}
}
}
}
elapsedTime = timer.delta_s(start_tick,timer.tick());
@@ -156,7 +210,7 @@ void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj)
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedVertexBufferObjectCache);
// insert the globj into the cache for the appropriate context.
s_deletedVertexBufferObjectCache[contextID].push_back(globj);
s_deletedVertexBufferObjectCache[contextID].insert(DisplayListMap::value_type(0,globj));
}
}
@@ -182,17 +236,18 @@ void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*c
unsigned int noDeleted = 0;
DisplayListList& dll = citr->second;
DisplayListMap& dll = citr->second;
for(DisplayListList::iterator ditr=dll.begin();
DisplayListMap::iterator ditr=dll.begin();
for(;
ditr!=dll.end() && elapsedTime<availableTime;
)
++ditr)
{
extensions->glDeleteBuffers(1,&(*ditr));
ditr = dll.erase(ditr);
extensions->glDeleteBuffers(1,&(ditr->second));
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
}
if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr);
if (noDeleted!=0) notify(osg::INFO)<<"Number VBOs deleted = "<<noDeleted<<std::endl;
}

View File

@@ -417,6 +417,9 @@ Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
Geometry::~Geometry()
{
// do dirty here to keep the getGLObjectSizeHint() estimate on the ball
dirtyDisplayList();
// no need to delete, all automatically handled by ref_ptr :-)
}
@@ -745,8 +748,49 @@ bool Geometry::computeFastPathsUsed()
unsigned int Geometry::getGLObjectSizeHint() const
{
unsigned int totalSize = 0;
if (_vertexData.array.valid()) totalSize += _vertexData.array->getTotalDataSize();
if (_normalData.array.valid()) totalSize += _normalData.array->getTotalDataSize();
if (_colorData.array.valid()) totalSize += _colorData.array->getTotalDataSize();
if (_secondaryColorData.array.valid()) totalSize += _secondaryColorData.array->getTotalDataSize();
if (_fogCoordData.array.valid()) totalSize += _fogCoordData.array->getTotalDataSize();
unsigned int unit;
for(unit=0;unit<_texCoordList.size();++unit)
{
const Array* array = _texCoordList[unit].array.get();
if (array) totalSize += array->getTotalDataSize();
}
bool handleVertexAttributes = true;
if (handleVertexAttributes)
{
unsigned int index;
for( index = 0; index < _vertexAttribList.size(); ++index )
{
const Array* array = _vertexAttribList[index].array.get();
if (array) totalSize += array->getTotalDataSize();
}
}
for(PrimitiveSetList::const_iterator itr=_primitives.begin();
itr!=_primitives.end();
++itr)
{
totalSize += 4*(*itr)->getNumIndices();
}
// do a very simply mapping of display list size proportional to vertex datasize.
return _vertexData.array.valid() ? _vertexData.array->getNumElements() : 0;
return totalSize;
}
void Geometry::drawImplementation(State& state) const
@@ -885,7 +929,7 @@ void Geometry::drawImplementation(State& state) const
unsigned int index;
for( index = 0; index < _vertexAttribList.size(); ++index )
{
_texCoordList[unit].offset = totalSize;
_vertexAttribList[unit].offset = totalSize;
const Array* array = _vertexAttribList[index].array.get();
const AttributeBinding ab = _vertexAttribList[index].binding;
if( ab == BIND_PER_VERTEX && array )