diff --git a/include/osg/BufferObject b/include/osg/BufferObject index 3ec365544fb..d0488d51464 100644 --- a/include/osg/BufferObject +++ b/include/osg/BufferObject @@ -272,6 +272,7 @@ class OSG_EXPORT GLBufferObject : public GraphicsObject }; typedef std::list< ref_ptr > GLBufferObjectList; +typedef std::vector> GLBufferObjectVector; class OSG_EXPORT GLBufferObjectSet : public Referenced { @@ -322,7 +323,8 @@ class OSG_EXPORT GLBufferObjectSet : public Referenced BufferObjectProfile _profile; unsigned int _numOfGLBufferObjects; GLBufferObjectList _orphanedGLBufferObjects; - GLBufferObjectList _pendingOrphanedGLBufferObjects; + OpenThreads::Atomic _pendingOrphanedGLBufferObjectsSize; + GLBufferObjectVector _pendingOrphanedGLBufferObjects; GLBufferObject* _head; GLBufferObject* _tail; @@ -368,6 +370,8 @@ class OSG_EXPORT GLBufferObjectManager : public GraphicsObjectManager void reportStats(std::ostream& out); void recomputeStats(std::ostream& out) const; + void reportStats(unsigned frameNumber, Stats& stats) const override; + unsigned int& getFrameNumber() { return _frameNumber; } unsigned int& getNumberFrames() { return _numFrames; } diff --git a/include/osg/ContextData b/include/osg/ContextData index fec208a7d1f..4bf22d81e6d 100644 --- a/include/osg/ContextData +++ b/include/osg/ContextData @@ -14,10 +14,15 @@ #ifndef OSG_CONTEXTDATA #define OSG_CONTEXTDATA 1 +#include #include namespace osg { +class ContextData; + +typedef std::map > ContextDataMap; + class OSG_EXPORT ContextData : public GraphicsObjectManager { public: @@ -73,6 +78,8 @@ class OSG_EXPORT ContextData : public GraphicsObjectManager virtual void reportStats(std::ostream& out); virtual void recomputeStats(std::ostream& out) const; + void reportStats(unsigned frameNumber, Stats& stats) const override; + /** Flush all deleted OpenGL objects within the specified availableTime. * Note, must be called from a thread which has current the graphics context associated with contextID. */ virtual void flushDeletedGLObjects(double currentTime, double& availableTime); @@ -130,6 +137,8 @@ class OSG_EXPORT ContextData : public GraphicsObjectManager /** Unregister a GraphicsContext.*/ static void unregisterGraphicsContext(GraphicsContext* gc); + static ContextDataMap getContextDataMap(); + protected: virtual ~ContextData(); diff --git a/include/osg/GLObjects b/include/osg/GLObjects index 84b5ec30853..f8ca8d15710 100644 --- a/include/osg/GLObjects +++ b/include/osg/GLObjects @@ -23,6 +23,7 @@ namespace osg { // forward declare class FrameStamp; +class Stats; /** Flush all deleted OpenGL objects within the specified availableTime. * Note, must be called from a thread which has current the graphics context associated with contextID. */ @@ -67,6 +68,8 @@ class OSG_EXPORT GraphicsObjectManager : public osg::Referenced virtual void reportStats(std::ostream& /*out*/) {} virtual void recomputeStats(std::ostream& /*out*/) const {} + virtual void reportStats(unsigned frameNumber, Stats& stats) const {} + /** Flush all deleted OpenGL objects within the specified availableTime. * Note, must be called from a thread which has current the graphics context associated with contextID. */ @@ -117,11 +120,13 @@ public: /** implementation of the actual deletion of an GL object - subclasses from GLObjectManager must implement the appropriate GL calls.*/ virtual void deleteGLObject(GLuint globj) = 0; + void reportStats(unsigned frameNumber, Stats& stats) const override; + protected: virtual ~GLObjectManager(); typedef std::list GLObjectHandleList; - OpenThreads::Mutex _mutex; + mutable OpenThreads::Mutex _mutex; GLObjectHandleList _deleteGLObjectHandles; }; diff --git a/include/osg/Texture b/include/osg/Texture index f6614633acd..166584ee860 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -1166,6 +1166,7 @@ public: unsigned int getNumPendingOrphans() const { return static_cast(_pendingOrphanedTextureObjects.size()); } protected: + typedef std::vector> TextureObjectVector; virtual ~TextureObjectSet(); @@ -1176,7 +1177,8 @@ protected: Texture::TextureProfile _profile; unsigned int _numOfTextureObjects; Texture::TextureObjectList _orphanedTextureObjects; - Texture::TextureObjectList _pendingOrphanedTextureObjects; + OpenThreads::Atomic _pendingOrphanedTextureObjectsSize; + TextureObjectVector _pendingOrphanedTextureObjects; Texture::TextureObject* _head; Texture::TextureObject* _tail; @@ -1232,6 +1234,8 @@ public: void recomputeStats(std::ostream& out) const; bool checkConsistency() const; + void reportStats(unsigned frameNumber, Stats& stats) const override; + unsigned int& getFrameNumber() { return _frameNumber; } unsigned int& getNumberFrames() { return _numFrames; } diff --git a/src/osg/BufferObject.cpp b/src/osg/BufferObject.cpp index b94d9805934..d731959fa13 100644 --- a/src/osg/BufferObject.cpp +++ b/src/osg/BufferObject.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,19 @@ using namespace osg; +namespace +{ + +template +Iterator eraseIfEmpty(Iterator it, Map& map) +{ + if (it->second->getNumOfGLBufferObjects() == 0) + return map.erase(it); + return ++it; +} + +} + ////////////////////////////////////////////////////////////////////////////////////////////////////// // // GLBufferObject::BufferEntry @@ -351,7 +365,7 @@ void GLBufferObjectSet::handlePendingOrphandedGLBufferObjects() unsigned int numOrphaned = _pendingOrphanedGLBufferObjects.size(); - for(GLBufferObjectList::iterator itr = _pendingOrphanedGLBufferObjects.begin(); + for(GLBufferObjectVector::iterator itr = _pendingOrphanedGLBufferObjects.begin(); itr != _pendingOrphanedGLBufferObjects.end(); ++itr) { @@ -368,6 +382,7 @@ void GLBufferObjectSet::handlePendingOrphandedGLBufferObjects() _parent->getNumberActiveGLBufferObjects() -= numOrphaned; _pendingOrphanedGLBufferObjects.clear(); + _pendingOrphanedGLBufferObjectsSize.exchange(0); CHECK_CONSISTENCY } @@ -376,13 +391,11 @@ void GLBufferObjectSet::deleteAllGLBufferObjects() { // OSG_NOTICE<<"GLBufferObjectSet::deleteAllGLBufferObjects()"< lock(_mutex); - if (!_pendingOrphanedGLBufferObjects.empty()) - { - // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"< lock(_mutex); - if (!_pendingOrphanedGLBufferObjects.empty()) - { - // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"< lock(_mutex); - if (!_pendingOrphanedGLBufferObjects.empty()) - { - // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"< lock(_mutex); - if (!_pendingOrphanedGLBufferObjects.empty()) - { - // OSG_NOTICE<<"GLBufferObjectSet::flushDeletedGLBufferObjects(..) handling orphans"<getCurrGLBufferObjectPoolSize()<=_parent->getMaxGLBufferObjectPoolSize()) @@ -574,11 +581,8 @@ bool GLBufferObjectSet::makeSpace(unsigned int& size) { { OpenThreads::ScopedLock lock(_mutex); - if (!_pendingOrphanedGLBufferObjects.empty()) - { - // OSG_NOTICE<<"GLBufferSet::::makeSpace(..) handling orphans"<deleteAllGLBufferObjects(); + itr = eraseIfEmpty(itr, _glBufferObjectSetMap); } } @@ -951,6 +956,7 @@ void GLBufferObjectManager::discardAllGLObjects() { (*itr).second->discardAllGLBufferObjects(); } + _glBufferObjectSetMap.clear(); } void GLBufferObjectManager::flushAllDeletedGLObjects() @@ -958,20 +964,20 @@ void GLBufferObjectManager::flushAllDeletedGLObjects() ElapsedTime elapsedTime(&(getDeleteTime())); for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin(); - itr != _glBufferObjectSetMap.end(); - ++itr) + itr != _glBufferObjectSetMap.end();) { (*itr).second->flushAllDeletedGLBufferObjects(); + itr = eraseIfEmpty(itr, _glBufferObjectSetMap); } } void GLBufferObjectManager::discardAllDeletedGLObjects() { for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin(); - itr != _glBufferObjectSetMap.end(); - ++itr) + itr != _glBufferObjectSetMap.end();) { (*itr).second->discardAllDeletedGLBufferObjects(); + itr = eraseIfEmpty(itr, _glBufferObjectSetMap); } } @@ -980,10 +986,10 @@ void GLBufferObjectManager::flushDeletedGLObjects(double currentTime, double& av ElapsedTime elapsedTime(&(getDeleteTime())); for(GLBufferObjectSetMap::iterator itr = _glBufferObjectSetMap.begin(); - (itr != _glBufferObjectSetMap.end()) && (availableTime > 0.0); - ++itr) + (itr != _glBufferObjectSetMap.end()) && (availableTime > 0.0);) { (*itr).second->flushDeletedGLBufferObjects(currentTime, availableTime); + itr = eraseIfEmpty(itr, _glBufferObjectSetMap); } } @@ -1051,6 +1057,11 @@ void GLBufferObjectManager::recomputeStats(std::ostream& out) const out<<" getMaxGLBufferObjectPoolSize()="<(_glBufferObjectSetMap.size())); +} + ////////////////////////////////////////////////////////////////////////////////////////////////////// // // BufferObject diff --git a/src/osg/ContextData.cpp b/src/osg/ContextData.cpp index bdbc4aaf6f8..34843b9bc7c 100644 --- a/src/osg/ContextData.cpp +++ b/src/osg/ContextData.cpp @@ -19,7 +19,7 @@ using namespace osg; -typedef std::map > ContextIDMap; +typedef ContextDataMap ContextIDMap; static ContextIDMap s_contextIDMap; static OpenThreads::ReentrantMutex s_contextIDMapMutex; static ContextData::GraphicsContexts s_registeredContexts; @@ -79,6 +79,12 @@ void ContextData::recomputeStats(std::ostream& out) const } } +void ContextData::reportStats(unsigned frameNumber, Stats& stats) const +{ + for (ManagerMap::const_iterator it = _managerMap.begin(); it != _managerMap.end(); ++it) + if (osg::GraphicsObjectManager* const v = dynamic_cast(it->second.get())) + v->reportStats(frameNumber, stats); +} void ContextData::flushDeletedGLObjects(double currentTime, double& availableTime) { @@ -334,3 +340,9 @@ GraphicsContext* ContextData::getCompileContext(unsigned int contextID) if (itr != s_contextIDMap.end()) return itr->second->getCompileContext(); else return 0; } + +ContextDataMap ContextData::getContextDataMap() +{ + OpenThreads::ScopedLock lock(s_contextIDMapMutex); + return s_contextIDMap; +} diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 348deaf0e7b..7c87af859c8 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -188,6 +188,16 @@ class DisplayListManager : public GraphicsObjectManager #endif } + void reportStats(unsigned frameNumber, Stats& stats) const override + { + const std::size_t size = [&](){ + const OpenThreads::ScopedLock lock(_mutex_deletedDisplayListCache); + return _displayListMap.size(); + }(); + + stats.setAttribute(frameNumber, "DisplayListManager" + std::to_string(_contextID), static_cast(size)); + } + protected: int _numberDrawablesReusedLastInLastFrame; @@ -195,7 +205,7 @@ class DisplayListManager : public GraphicsObjectManager int _numberDeletedDrawablesInLastFrame; typedef std::multimap DisplayListMap; - OpenThreads::Mutex _mutex_deletedDisplayListCache; + mutable OpenThreads::Mutex _mutex_deletedDisplayListCache; DisplayListMap _displayListMap; }; diff --git a/src/osg/GLObjects.cpp b/src/osg/GLObjects.cpp index 0e2ca14013a..a85876ac86e 100644 --- a/src/osg/GLObjects.cpp +++ b/src/osg/GLObjects.cpp @@ -146,3 +146,13 @@ GLuint GLObjectManager::createGLObject() OSG_INFO<<"void "<<_name<<"::createGLObject() : Not Implemented"< lock(_mutex); + return _deleteGLObjectHandles.size(); + }(); + + stats.setAttribute(frameNumber, _name + std::to_string(_contextID), static_cast(size)); +} diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index 189d941ef81..20cfe56693f 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -60,6 +60,17 @@ #define CHECK_CONSISTENCY #endif +namespace { + template + Iterator eraseIfEmpty(Iterator it, Map& map) + { + if (it->second->getNumOfTextureObjects() == 0) + return map.erase(it); + return ++it; + } +} + + namespace osg { ApplicationUsageProxy Texture_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_TEXTURE_SIZE","Set the maximum size of textures."); @@ -519,7 +530,7 @@ void TextureObjectSet::handlePendingOrphandedTextureObjects() unsigned int numOrphaned = _pendingOrphanedTextureObjects.size(); - for(Texture::TextureObjectList::iterator itr = _pendingOrphanedTextureObjects.begin(); + for(TextureObjectVector::iterator itr = _pendingOrphanedTextureObjects.begin(); itr != _pendingOrphanedTextureObjects.end(); ++itr) { @@ -536,6 +547,7 @@ void TextureObjectSet::handlePendingOrphandedTextureObjects() _parent->getNumberActiveTextureObjects() -= numOrphaned; _pendingOrphanedTextureObjects.clear(); + _pendingOrphanedTextureObjectsSize.exchange(0); CHECK_CONSISTENCY } @@ -545,13 +557,11 @@ void TextureObjectSet::deleteAllTextureObjects() { // OSG_NOTICE<<"TextureObjectSet::deleteAllTextureObjects()"< lock(_mutex); - if (!_pendingOrphanedTextureObjects.empty()) - { - // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"< lock(_mutex); - if (!_pendingOrphanedTextureObjects.empty()) - { - // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"< lock(_mutex); - if (!_pendingOrphanedTextureObjects.empty()) - { - // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"< lock(_mutex); - if (!_pendingOrphanedTextureObjects.empty()) - { - // OSG_NOTICE<<"TextureObjectSet::flushDeletedTextureObjects(..) handling orphans"<getCurrTexturePoolSize()<=_parent->getMaxTexturePoolSize()) @@ -757,13 +762,11 @@ void TextureObjectSet::flushDeletedTextureObjects(double /*currentTime*/, double bool TextureObjectSet::makeSpace(unsigned int& size) { + if (_pendingOrphanedTextureObjectsSize != 0) { OpenThreads::ScopedLock lock(_mutex); - if (!_pendingOrphanedTextureObjects.empty()) - { - // OSG_NOTICE<<"TextureObjectSet::TextureObjectSet::makeSpace(..) handling orphans"<(_textureSetMap.size())); +} + osg::ref_ptr Texture::generateTextureObject(const Texture* texture, unsigned int contextID, GLenum target) { return osg::get(contextID)->generateTextureObject(texture, target); diff --git a/src/osg/VertexArrayState.cpp b/src/osg/VertexArrayState.cpp index 16298b720a9..e8f67c3a6b7 100644 --- a/src/osg/VertexArrayState.cpp +++ b/src/osg/VertexArrayState.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace osg; @@ -102,10 +103,20 @@ class VertexArrayStateManager : public GraphicsObjectManager _vertexArrayStateList.push_back(vas); } + void reportStats(unsigned frameNumber, Stats& stats) const override + { + const std::size_t size = [&](){ + const OpenThreads::ScopedLock lock(_mutex_vertexArrayStateList); + return _vertexArrayStateList.size(); + }(); + + stats.setAttribute(frameNumber, "VertexArrayStateManager" + std::to_string(_contextID), static_cast(size)); + } + protected: typedef std::list< osg::ref_ptr > VertexArrayStateList; - OpenThreads::Mutex _mutex_vertexArrayStateList; + mutable OpenThreads::Mutex _mutex_vertexArrayStateList; VertexArrayStateList _vertexArrayStateList; };