diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index b759eee2f..924faab09 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -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 DisplayListList; -typedef std::map DeletedDisplayListCache; +typedef std::multimap DisplayListMap; +typedef std::map 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 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 "< 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() && elapsedTimes_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() && elapsedTimesecond,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"< s_minimumNumberOfDisplayListsToRetainInCache) ? dll.size()-s_minimumNumberOfDisplayListsToRetainInCache : 0; + for(; + ditr!=dll.rend() && elapsedTimesecond,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"< 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() && elapsedTimeglDeleteBuffers(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 = "<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 ) diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 79d376e15..4f2a2a149 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -226,14 +226,72 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou } } +static double s_start_frame = 0; +static double s_before_compile = 0; +static double s_after_compile = 0; +static osg::Timer_t startTick = 0; + void DatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp) { + if (framestamp) { //osg::notify(osg::INFO) << "signalBeginFrame "<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber(); + + } //else osg::notify(osg::INFO) << "signalBeginFrame >>>>>>>>>>>>>>>>"<tick(); + + double timeStamp = osg::Timer::instance()->delta_s(startTick,osg::Timer::instance()->tick()); + + double drawTime = s_before_compile-s_start_frame; + double compileTime = s_after_compile-s_before_compile; + double timeDelta = timeStamp-s_start_frame; + + unsigned int numFrames = (timeDelta*60.0074); +/* + 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_numberDrawablesReusedLastInLastFrame > 0) str += " RD "; + if (osg::Drawable::s_numberNewDrawablesInLastFrame > 0) str += " ND "; + if (osg::Drawable::s_numberDeletedDrawablesInLastFrame > 0) str += " DD "; + + if (str.empty()) str += " ?? "; + + osg::notify(osg::NOTICE)<<" ************* frame="<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_numberDrawablesReusedLastInLastFrame > 0) str += " RD "; - 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 "<delta_m(before,osg::Timer::instance()->tick())<<" ms objects"<targetNumOfInActivePagedLODs) targetNumOfRemovedChildPagedLODs = _inactivePagedLODList.size()-targetNumOfInActivePagedLODs; @@ -793,169 +816,187 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) { // osg::notify(osg::NOTICE)<<"DatabasePager::compileGLObjects "<<_frameNumber< databaseRequest; - - // get the first compileable entry. + s_before_compile = osg::Timer::instance()->delta_s(startTick,osg::Timer::instance()->tick()); + + + double drawTime = s_before_compile-s_start_frame; + if (drawTime<0.01) { - OpenThreads::ScopedLock lock(_dataToCompileListMutex); - if (!_dataToCompileList.empty()) + + const osg::Timer& timer = *osg::Timer::instance(); + osg::Timer_t start_tick = timer.tick(); + double elapsedTime = 0.0; + double estimatedTextureDuration = 0.0; + double estimatedDrawableDuration = 0.0; + + osg::ref_ptr databaseRequest; + + // get the first compileable entry. { - std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor()); - - DatabaseRequestList::iterator litr; - int i=0; - for(litr = _dataToCompileList.begin(); - (litr != _dataToCompileList.end()) && (_frameNumber == (*litr)->_frameNumberLastRequest); - ++litr,i++) - { - //osg::notify(osg::NOTICE)<<"Compile "<<_frameNumber-(*litr)->_frameNumberLastRequest< 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<_dataToCompileMap; - DataToCompile& dtc = dcm[state.getContextID()]; - if (!dtc.first.empty() && (elapsedTime+estimatedTextureDuration)compileGLObjects(state); - - GLint p; - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_RESIDENT, &p); - - elapsedTime = timer.delta_s(start_tick,timer.tick()); - - - // 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)compileGLObjects(state); - elapsedTime = timer.delta_s(start_tick,timer.tick()); - - // 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); - } - - //osg::notify(osg::INFO)<<"Checking if compiled"<second.first.empty())) allCompiled=false; - if (!(itr->second.second.empty())) allCompiled=false; - } - - - if (allCompiled) - { - osg::notify(osg::INFO)<<"All compiled"< lock(_dataToCompileListMutex); - - { - OpenThreads::ScopedLock lock(_dataToMergeListMutex); - _dataToMergeList.push_back(databaseRequest); - } - - if (!_dataToCompileList.empty()) _dataToCompileList.erase(_dataToCompileList.begin()); - if (!_dataToCompileList.empty()) { std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor()); + + DatabaseRequestList::iterator litr; + int i=0; + for(litr = _dataToCompileList.begin(); + (litr != _dataToCompileList.end()) && (_frameNumber == (*litr)->_frameNumberLastRequest); + ++litr,i++) + { + //osg::notify(osg::NOTICE)<<"Compile "<<_frameNumber-(*litr)->_frameNumberLastRequest< 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<_dataToCompileMap; + DataToCompile& dtc = dcm[state.getContextID()]; + if (!dtc.first.empty() && (elapsedTime+estimatedTextureDuration)compileGLObjects(state); + + GLint p; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_RESIDENT, &p); + + elapsedTime = timer.delta_s(start_tick,timer.tick()); + + + // 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)compileGLObjects(state); + elapsedTime = timer.delta_s(start_tick,timer.tick()); + + // estimate the duration of the compile based on current compile duration. + estimatedDrawableDuration = (elapsedTime-startCompileTime); + + // osg::notify(osg::NOTICE)<<" Compiling drawable "<second.first.empty())) allCompiled=false; + if (!(itr->second.second.empty())) allCompiled=false; + } + + + if (allCompiled) + { + osg::notify(osg::INFO)<<"All compiled"< lock(_dataToCompileListMutex); + + { + OpenThreads::ScopedLock lock(_dataToMergeListMutex); + _dataToMergeList.push_back(databaseRequest); + } + + if (!_dataToCompileList.empty()) _dataToCompileList.erase(_dataToCompileList.begin()); + + if (!_dataToCompileList.empty()) + { + std::sort(_dataToCompileList.begin(),_dataToCompileList.end(),SortFileRequestFunctor()); + databaseRequest = _dataToCompileList.front(); + } + else databaseRequest = 0; + + } + else + { + //osg::notify(osg::INFO)<<"Not all compiled"<