diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 071a2540d..86516f03a 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -87,31 +87,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** Get whether new database request calls are accepted or ignored.*/ bool getAcceptNewDatabaseRequests() const { return _acceptNewRequests; } - /** Set the use of the frame block which, if enabled, blocks the DatabasePager - * from executing which the current frame is being drawn. - * When a single processor machine is being used it can be useful to block on - * frame to help prevent the database paging thread from slowing the cull and draw - * traversals which in turn can cause frame drops.*/ - void setUseFrameBlock(bool useFrameBlock) { _useFrameBlock = useFrameBlock; } - - /** Get the whether UseFrameBlock is on or off.*/ - bool getUseFrameBlock() const { return _useFrameBlock; } - - osg::RefBlock* getFrameBlock() { return _frameBlock.get(); } - - /** Set the priority of the database pager thread during the frame (i.e. while cull and draw are running.)*/ - void setThreadPriorityDuringFrame(ThreadPriority duringFrame) { _threadPriorityDuringFrame = duringFrame; } - - /** Get the priority of the database pager thread during the frame*/ - ThreadPriority getThreadPriorityDuringFrame() const { return _threadPriorityDuringFrame; } - - /** Set the priority of the database pager thread when the frame is not being exectuted (i.e. before or after cull and draw have run.)*/ - void setThreadPriorityOutwithFrame(ThreadPriority outwithFrame) { _threadPriorityOutwithFrame = outwithFrame; } - - /** Get the priority of the database pager thread when the frame is not being exectuted.*/ - ThreadPriority getThreadPriorityOutwithFrame() const { return _threadPriorityOutwithFrame; } - - /** Get the number of frames that are currently active.*/ int getNumFramesActive() const { return _numFramesActive; } @@ -259,6 +234,20 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** Report how many items are in the _dataToCompileList queue */ unsigned int getDataToCompileListSize() const { return _dataToCompileList.size(); } + + + + /** Get the minimum time between the first request for a tile to be loaded and the time of its merge into the main scene graph.*/ + double getMinimumTimeToMergeTile() const { return _minimumTimeToMergeTile; } + + /** Get the maximum time between the first request for a tile to be loaded and the time of its merge into the main scene graph.*/ + double getMaximumTimeToMergeTile() const { return _maximumTimeToMergeTile; } + + /** Get the average time between the first request for a tile to be loaded and the time of its merge into the main scene graph.*/ + double getAverageTimeToMergeTiles() const { return _totalTimeToMergeTiles/static_cast(_numTilesMerges); } + + /** Reset the Stats variables.*/ + void resetStats(); typedef std::list< osg::ref_ptr > PagedLODList; @@ -322,13 +311,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl (!_fileRequestList.empty() || !_childrenToDeleteList.empty()) && !_databasePagerThreadPaused); } - inline void updateFrameBlock(int delta) - { - OpenThreads::ScopedLock lock(_numFramesActiveMutex); - _numFramesActive += delta; - _frameBlock->set(_numFramesActive==0); - } - /** Iterate through the active PagedLOD nodes children removing * children which havn't been visited since specified expiryTime. @@ -343,15 +325,10 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl bool _acceptNewRequests; bool _databasePagerThreadPaused; - bool _useFrameBlock; int _numFramesActive; mutable OpenThreads::Mutex _numFramesActiveMutex; - osg::ref_ptr _frameBlock; int _frameNumber; - ThreadPriority _threadPriorityDuringFrame; - ThreadPriority _threadPriorityOutwithFrame; - DatabaseRequestList _fileRequestList; mutable OpenThreads::Mutex _fileRequestListMutex; @@ -386,6 +363,12 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl double _minimumTimeAvailableForGLCompileAndDeletePerFrame; unsigned int _maximumNumOfObjectsToCompilePerFrame; + double _minimumTimeToMergeTile; + double _maximumTimeToMergeTile; + double _totalTimeToMergeTiles; + unsigned int _numTilesMerges; + + struct CompileOperation : public osg::GraphicsOperation { CompileOperation(DatabasePager* databasePager); diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 7ea949c05..44776af83 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -34,14 +34,11 @@ DatabasePager::DatabasePager() _acceptNewRequests = true; _databasePagerThreadPaused = false; - _useFrameBlock = false; _numFramesActive = 0; _frameNumber = 0; - _frameBlock = new osg::RefBlock; _databasePagerThreadBlock = new osg::RefBlock; - - _threadPriorityDuringFrame = THREAD_PRIORITY_MIN; - _threadPriorityOutwithFrame = THREAD_PRIORITY_MIN; + + setSchedulePriority(THREAD_PRIORITY_MIN); #if __APPLE__ // OSX really doesn't like compiling display lists, and performs poorly when they are used, @@ -108,6 +105,10 @@ DatabasePager::DatabasePager() _maximumNumOfObjectsToCompilePerFrame = atoi(ptr); } + + // initialize the stats variables + resetStats(); + // make sure a SharedStateManager exists. //osgDB::Registry::instance()->getOrCreateSharedStateManager(); @@ -125,15 +126,10 @@ DatabasePager::DatabasePager(const DatabasePager& rhs) _acceptNewRequests = true; _databasePagerThreadPaused = false; - _useFrameBlock = rhs._useFrameBlock; _numFramesActive = 0; _frameNumber = 0; - _frameBlock = new osg::RefBlock; _databasePagerThreadBlock = new osg::RefBlock; - _threadPriorityDuringFrame = rhs._threadPriorityDuringFrame; - _threadPriorityOutwithFrame = rhs._threadPriorityOutwithFrame; - _drawablePolicy = rhs._drawablePolicy; _changeAutoUnRef = rhs._changeAutoUnRef; @@ -149,6 +145,9 @@ DatabasePager::DatabasePager(const DatabasePager& rhs) _targetFrameRate = rhs._targetFrameRate; _minimumTimeAvailableForGLCompileAndDeletePerFrame = rhs._minimumTimeAvailableForGLCompileAndDeletePerFrame; _maximumNumOfObjectsToCompilePerFrame = rhs._maximumNumOfObjectsToCompilePerFrame; + + // initialize the stats variables + resetStats(); } @@ -184,7 +183,6 @@ int DatabasePager::cancel() //join(); // release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation. - _frameBlock->release(); _databasePagerThreadBlock->release(); // then wait for the the thread to stop running. @@ -232,6 +230,15 @@ void DatabasePager::clear() // _activeGraphicsContexts } +void DatabasePager::resetStats() +{ + // initialize the stats variables + _minimumTimeToMergeTile = DBL_MAX; + _maximumTimeToMergeTile = -DBL_MAX; + _totalTimeToMergeTiles = 0.0; + _numTilesMerges = 0; +} + void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* group, float priority, const osg::FrameStamp* framestamp) { @@ -340,7 +347,6 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou _startThreadCalled = true; _done = false; osg::notify(osg::DEBUG_INFO)<<"DatabasePager::startThread()"<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber(); } //else osg::notify(osg::INFO) << "signalBeginFrame >>>>>>>>>>>>>>>>"<0 && _threadPriorityDuringFrame!=getSchedulePriority()) - setSchedulePriority(_threadPriorityDuringFrame); } void DatabasePager::signalEndFrame() { //osg::notify(osg::INFO) << "signalEndFrame <<<<<<<<<<<<<<<<<<<< "<block(); - if (_useFrameBlock) - { - _frameBlock->block(); - } - // // delete any children if required. // @@ -749,8 +739,18 @@ void DatabasePager::addLoadedDataToSceneGraph(double timeStamp) plod->setTimeStamp(plod->getNumChildren(),timeStamp); } group->addChild(databaseRequest->_loadedModel.get()); - osg::notify(osg::INFO)<<"merged subgraph"<_fileName<<" after "<_numOfRequests<<" requests."<_fileName<<" after "<_numOfRequests<<" requests and time="<<(timeStamp-databaseRequest->_timestampFirstRequest)*1000.0<_timestampFirstRequest; + + if (timeToMerge<_minimumTimeToMergeTile) _minimumTimeToMergeTile = timeToMerge; + if (timeToMerge>_maximumTimeToMergeTile) _maximumTimeToMergeTile = timeToMerge; + + _totalTimeToMergeTiles += timeToMerge; + ++_numTilesMerges; + + // osg::notify(osg::NOTICE)<<"curr = "<delta_m(before,osg::Timer::instance()->tick())<<" ms objects"<getDatabasePager() && viewer->getDatabasePager()->isRunning()) + { + viewer->getDatabasePager()->resetStats(); + } + viewer->getStats()->collectStats("event",true); viewer->getStats()->collectStats("update",true); @@ -410,6 +415,69 @@ struct FrameMarkerDrawCallback : public virtual osg::Drawable::DrawCallback int _numFrames; }; +struct PagerCallback : public virtual osg::NodeCallback +{ + + PagerCallback(osgDB::DatabasePager* dp, osgText::Text* minValue, osgText::Text* maxValue, osgText::Text* averageValue, double multiplier): + _dp(dp), + _minValue(minValue), + _maxValue(maxValue), + _averageValue(averageValue), + _multiplier(multiplier) + { + } + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + if (_dp.valid()) + { + double value = _dp->getAverageTimeToMergeTiles(); + if (value>= 0.0 && value <= 1000) + { + sprintf(_tmpText,"%4.0f",value * _multiplier); + _averageValue->setText(_tmpText); + } + else + { + _averageValue->setText(""); + } + + value = _dp->getMinimumTimeToMergeTile(); + if (value>= 0.0 && value <= 1000) + { + sprintf(_tmpText,"%4.0f",value * _multiplier); + _minValue->setText(_tmpText); + } + else + { + _minValue->setText(""); + } + + value = _dp->getMaximumTimeToMergeTile(); + if (value>= 0.0 && value <= 1000) + { + sprintf(_tmpText,"%4.0f",value * _multiplier); + _maxValue->setText(_tmpText); + } + else + { + _maxValue->setText(""); + } + } + + traverse(node,nv); + } + + osg::observer_ptr _dp; + + osg::ref_ptr _minValue; + osg::ref_ptr _maxValue; + osg::ref_ptr _averageValue; + double _multiplier; + char _tmpText[128]; + osg::Timer_t _tickLastUpdated; +}; + osg::Geometry* StatsHandler::createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks) { @@ -523,6 +591,8 @@ void StatsHandler::setUpScene(osgViewer::Viewer* viewer) osg::Vec4 colorUpdate( 0.0f,1.0f,0.0f,1.0f); osg::Vec4 colorUpdateAlpha( 0.0f,1.0f,0.0f,0.5f); + osg::Vec4 colorDP( 1.0f,1.0f,0.5f,1.0f); + // frame rate stats { @@ -683,6 +753,87 @@ void StatsHandler::setUpScene(osgViewer::Viewer* viewer) geode->addDrawable(frameMarkers); } + + osgDB::DatabasePager* dp = viewer->getDatabasePager(); + if (dp && dp->isRunning()) + { + pos.y() -= characterSize*1.5f; + + pos.x() = leftPos; + + osg::ref_ptr averageLabel = new osgText::Text; + geode->addDrawable( averageLabel.get() ); + + averageLabel->setColor(colorDP); + averageLabel->setFont(font); + averageLabel->setCharacterSize(characterSize); + averageLabel->setPosition(pos); + averageLabel->setText("DatabasePager time to merge new tiles - average: "); + + pos.x() = averageLabel->getBound().xMax(); + + osg::ref_ptr averageValue = new osgText::Text; + geode->addDrawable( averageValue.get() ); + + averageValue->setColor(colorDP); + averageValue->setFont(font); + averageValue->setCharacterSize(characterSize); + averageValue->setPosition(pos); + averageValue->setText("1000"); + + pos.x() = averageValue->getBound().xMax() + 2.0f*characterSize; + + + osg::ref_ptr minLabel = new osgText::Text; + geode->addDrawable( minLabel.get() ); + + minLabel->setColor(colorDP); + minLabel->setFont(font); + minLabel->setCharacterSize(characterSize); + minLabel->setPosition(pos); + minLabel->setText("min: "); + + pos.x() = minLabel->getBound().xMax(); + + osg::ref_ptr minValue = new osgText::Text; + geode->addDrawable( minValue.get() ); + + minValue->setColor(colorDP); + minValue->setFont(font); + minValue->setCharacterSize(characterSize); + minValue->setPosition(pos); + minValue->setText("1000"); + + pos.x() = minValue->getBound().xMax() + 2.0f*characterSize; + + + osg::ref_ptr maxLabel = new osgText::Text; + geode->addDrawable( maxLabel.get() ); + + maxLabel->setColor(colorDP); + maxLabel->setFont(font); + maxLabel->setCharacterSize(characterSize); + maxLabel->setPosition(pos); + maxLabel->setText("max: "); + + pos.x() = maxLabel->getBound().xMax(); + + osg::ref_ptr maxValue = new osgText::Text; + geode->addDrawable( maxValue.get() ); + + maxValue->setColor(colorDP); + maxValue->setFont(font); + maxValue->setCharacterSize(characterSize); + maxValue->setPosition(pos); + maxValue->setText("1000"); + + pos.x() = maxLabel->getBound().xMax(); + + geode->setCullCallback(new PagerCallback(dp, minValue.get(), maxValue.get(), averageValue.get(), 1000.0)); + } + + pos.x() = leftPos; + } #if 0 // scene stats diff --git a/src/osgWrappers/osgDB/DatabasePager.cpp b/src/osgWrappers/osgDB/DatabasePager.cpp index a41a439ca..44e6ed0c5 100644 --- a/src/osgWrappers/osgDB/DatabasePager.cpp +++ b/src/osgWrappers/osgDB/DatabasePager.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -114,41 +113,6 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) __bool__getAcceptNewDatabaseRequests, "Get whether new database request calls are accepted or ignored. ", ""); - I_Method1(void, setUseFrameBlock, IN, bool, useFrameBlock, - Properties::NON_VIRTUAL, - __void__setUseFrameBlock__bool, - "Set the use of the frame block which, if enabled, blocks the DatabasePager from executing which the current frame is being drawn. ", - "When a single processor machine is being used it can be useful to block on frame to help prevent the database paging thread from slowing the cull and draw traversals which in turn can cause frame drops. "); - I_Method0(bool, getUseFrameBlock, - Properties::NON_VIRTUAL, - __bool__getUseFrameBlock, - "Get the whether UseFrameBlock is on or off. ", - ""); - I_Method0(osg::RefBlock *, getFrameBlock, - Properties::NON_VIRTUAL, - __osg_RefBlock_P1__getFrameBlock, - "", - ""); - I_Method1(void, setThreadPriorityDuringFrame, IN, osgDB::DatabasePager::ThreadPriority, duringFrame, - Properties::NON_VIRTUAL, - __void__setThreadPriorityDuringFrame__ThreadPriority, - "Set the priority of the database pager thread during the frame (i.e. ", - "while cull and draw are running.) "); - I_Method0(osgDB::DatabasePager::ThreadPriority, getThreadPriorityDuringFrame, - Properties::NON_VIRTUAL, - __ThreadPriority__getThreadPriorityDuringFrame, - "Get the priority of the database pager thread during the frame. ", - ""); - I_Method1(void, setThreadPriorityOutwithFrame, IN, osgDB::DatabasePager::ThreadPriority, outwithFrame, - Properties::NON_VIRTUAL, - __void__setThreadPriorityOutwithFrame__ThreadPriority, - "Set the priority of the database pager thread when the frame is not being exectuted (i.e. ", - "before or after cull and draw have run.) "); - I_Method0(osgDB::DatabasePager::ThreadPriority, getThreadPriorityOutwithFrame, - Properties::NON_VIRTUAL, - __ThreadPriority__getThreadPriorityOutwithFrame, - "Get the priority of the database pager thread when the frame is not being exectuted. ", - ""); I_Method0(int, getNumFramesActive, Properties::NON_VIRTUAL, __int__getNumFramesActive, @@ -309,6 +273,26 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) __unsigned_int__getDataToCompileListSize, "Report how many items are in the _dataToCompileList queue. ", ""); + I_Method0(double, getMinimumTimeToMergeTile, + Properties::NON_VIRTUAL, + __double__getMinimumTimeToMergeTile, + "Get the minimum time between the first request for a tile to be loaded and the time of its merge into the main scene graph. ", + ""); + I_Method0(double, getMaximumTimeToMergeTile, + Properties::NON_VIRTUAL, + __double__getMaximumTimeToMergeTile, + "Get the maximum time between the first request for a tile to be loaded and the time of its merge into the main scene graph. ", + ""); + I_Method0(double, getAverageTimeToMergeTiles, + Properties::NON_VIRTUAL, + __double__getAverageTimeToMergeTiles, + "Get the average time between the first request for a tile to be loaded and the time of its merge into the main scene graph. ", + ""); + I_Method0(void, resetStats, + Properties::NON_VIRTUAL, + __void__resetStats, + "Reset the Stats variables. ", + ""); I_StaticMethod0(osg::ref_ptr< osgDB::DatabasePager > &, prototype, __osg_ref_ptrT1_DatabasePager__R1__prototype_S, "get the prototype singleton used by DatabasePager::create(). ", @@ -323,12 +307,6 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) __void__updateDatabasePagerThreadBlock, "", ""); - I_ProtectedMethod1(void, updateFrameBlock, IN, int, delta, - Properties::NON_VIRTUAL, - Properties::NON_CONST, - __void__updateFrameBlock__int, - "", - ""); I_ProtectedMethod1(void, removeExpiredSubgraphs, IN, double, currentFrameTime, Properties::VIRTUAL, Properties::NON_CONST, @@ -344,6 +322,9 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) I_SimpleProperty(bool, AcceptNewDatabaseRequests, __bool__getAcceptNewDatabaseRequests, __void__setAcceptNewDatabaseRequests__bool); + I_SimpleProperty(double, AverageTimeToMergeTiles, + __double__getAverageTimeToMergeTiles, + 0); I_IndexedProperty(bool, CompileGLObjectsForContextID, __bool__getCompileGLObjectsForContextID__unsigned_int, __void__setCompileGLObjectsForContextID__unsigned_int__bool, @@ -369,27 +350,21 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) I_SimpleProperty(unsigned int, FileRequestListSize, __unsigned_int__getFileRequestListSize, 0); - I_SimpleProperty(osg::RefBlock *, FrameBlock, - __osg_RefBlock_P1__getFrameBlock, - 0); I_SimpleProperty(unsigned int, MaximumNumOfObjectsToCompilePerFrame, __unsigned_int__getMaximumNumOfObjectsToCompilePerFrame, __void__setMaximumNumOfObjectsToCompilePerFrame__unsigned_int); + I_SimpleProperty(double, MaximumTimeToMergeTile, + __double__getMaximumTimeToMergeTile, + 0); I_SimpleProperty(double, MinimumTimeAvailableForGLCompileAndDeletePerFrame, __double__getMinimumTimeAvailableForGLCompileAndDeletePerFrame, __void__setMinimumTimeAvailableForGLCompileAndDeletePerFrame__double); + I_SimpleProperty(double, MinimumTimeToMergeTile, + __double__getMinimumTimeToMergeTile, + 0); I_SimpleProperty(double, TargetFrameRate, __double__getTargetFrameRate, __void__setTargetFrameRate__double); - I_SimpleProperty(osgDB::DatabasePager::ThreadPriority, ThreadPriorityDuringFrame, - __ThreadPriority__getThreadPriorityDuringFrame, - __void__setThreadPriorityDuringFrame__ThreadPriority); - I_SimpleProperty(osgDB::DatabasePager::ThreadPriority, ThreadPriorityOutwithFrame, - __ThreadPriority__getThreadPriorityOutwithFrame, - __void__setThreadPriorityOutwithFrame__ThreadPriority); - I_SimpleProperty(bool, UseFrameBlock, - __bool__getUseFrameBlock, - __void__setUseFrameBlock__bool); END_REFLECTOR BEGIN_OBJECT_REFLECTOR(osg::observer_ptr< osg::GraphicsContext >)