diff --git a/applications/osgviewer/osgviewer.cpp b/applications/osgviewer/osgviewer.cpp index 688d8371c..8983a6fa6 100644 --- a/applications/osgviewer/osgviewer.cpp +++ b/applications/osgviewer/osgviewer.cpp @@ -397,11 +397,7 @@ public: } } -#if 0 bool aquireGPUStats = numCamrasWithTimerQuerySupport==cameras.size(); -#else - bool aquireGPUStats = false; -#endif float leftPos = 10.0f; float startBlocks = aquireGPUStats ? 250.0f : 150.0f; @@ -413,8 +409,6 @@ public: osg::Vec4 colorUpdate( 0.0f,1.0f,0.0f,1.0f); - - // frame rate stats { osg::Geode* geode = new osg::Geode(); @@ -632,33 +626,6 @@ public: drawValue->setDrawCallback(new TextDrawCallback(stats,"Draw traversal time taken",-1, 1000.0)); - if (aquireGPUStats) - { - pos.x() = drawValue->getBound().xMax() + 30.0f; - - osg::ref_ptr gpuLabel = new osgText::Text; - geode->addDrawable( gpuLabel.get() ); - - gpuLabel->setColor(colorGPU); - gpuLabel->setFont(font); - gpuLabel->setCharacterSize(characterSize); - gpuLabel->setPosition(pos); - gpuLabel->setText("GPU: "); - - pos.x() = gpuLabel->getBound().xMax(); - - osg::ref_ptr gpuValue = new osgText::Text; - geode->addDrawable( gpuValue.get() ); - - gpuValue->setColor(colorGPU); - gpuValue->setFont(font); - gpuValue->setCharacterSize(characterSize); - gpuValue->setPosition(pos); - gpuValue->setText("0.0"); - - gpuValue->setDrawCallback(new TextDrawCallback(stats,"GPU draw time taken",-1, 1000.0)); - } - pos.x() = startBlocks; osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorDraw, 10); geometry->setDrawCallback(new BlockDrawCallback(startBlocks, viewerStats, stats, "Draw traversal begin time", "Draw traversal end time", -1, 10, 10000.0)); @@ -667,6 +634,41 @@ public: pos.y() -= characterSize*1.5f; } + if (aquireGPUStats) + { + pos.x() = leftPos; + + osg::ref_ptr gpuLabel = new osgText::Text; + geode->addDrawable( gpuLabel.get() ); + + gpuLabel->setColor(colorGPU); + gpuLabel->setFont(font); + gpuLabel->setCharacterSize(characterSize); + gpuLabel->setPosition(pos); + gpuLabel->setText("GPU: "); + + pos.x() = gpuLabel->getBound().xMax(); + + osg::ref_ptr gpuValue = new osgText::Text; + geode->addDrawable( gpuValue.get() ); + + gpuValue->setColor(colorGPU); + gpuValue->setFont(font); + gpuValue->setCharacterSize(characterSize); + gpuValue->setPosition(pos); + gpuValue->setText("0.0"); + + gpuValue->setDrawCallback(new TextDrawCallback(stats,"GPU draw time taken",-1, 1000.0)); + + pos.x() = startBlocks; + osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorGPU, 10); + geometry->setDrawCallback(new BlockDrawCallback(startBlocks, viewerStats, stats, "GPU draw begin time", "GPU draw end time", -1, 10, 10000.0)); + geode->addDrawable(geometry); + + pos.y() -= characterSize*1.5f; + } + + pos.x() = leftPos; diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index f5971af5b..3f8bfcdaf 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -453,11 +453,81 @@ struct ViewerRenderingOperation : public osg::GraphicsOperation _sceneView(sceneView), _databasePager(databasePager), _startTick(startTick), - _checkForQuery(false) + _initialized(false), + _aquireGPUStats(false), + _extensions(0) { _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); } + typedef std::pair QueryFrameNumberPair; + typedef std::list QueryFrameNumberList; + typedef std::vector QueryList; + + inline void checkQuery(osg::Stats* stats) + { + for(QueryFrameNumberList::iterator itr = _queryFrameNumberList.begin(); + itr != _queryFrameNumberList.end(); + ) + { + GLuint query = itr->first; + GLint available = 0; + _extensions->glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &available); + if (available) + { + GLuint64EXT timeElapsed = 0; + _extensions->glGetQueryObjectui64v(query, GL_QUERY_RESULT, &timeElapsed); + + double timeElapsedSeconds = double(timeElapsed)*1e-9; + double currentTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); + double estimatedEndTime = (_previousQueryTime + currentTime) * 0.5; + double estimatedBeginTime = estimatedEndTime - timeElapsedSeconds; + + stats->setAttribute(itr->second, "GPU draw begin time", estimatedBeginTime); + stats->setAttribute(itr->second, "GPU draw end time", estimatedEndTime); + stats->setAttribute(itr->second, "GPU draw time taken", timeElapsedSeconds); + + + itr = _queryFrameNumberList.erase(itr); + _availableQueryObjects.push_back(query); + } + else + { + ++itr; + } + + } + _previousQueryTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); + } + + inline GLuint createQueryObject() + { + if (_availableQueryObjects.empty()) + { + GLuint query; + _extensions->glGenQueries(1, &query); + return query; + } + else + { + GLuint query = _availableQueryObjects.back(); + _availableQueryObjects.pop_back(); + return query; + } + } + + inline void beginQuery(int frameNumber) + { + GLuint query = createQueryObject(); + _extensions->glBeginQuery(GL_TIME_ELAPSED, query); + _queryFrameNumberList.push_back(QueryFrameNumberPair(query, frameNumber)); + } + + inline void endQuery() + { + _extensions->glEndQuery(GL_TIME_ELAPSED); + } + virtual void operator () (osg::GraphicsContext*) { if (!_sceneView) return; @@ -468,87 +538,54 @@ struct ViewerRenderingOperation : public osg::GraphicsOperation osg::State* state = _sceneView->getState(); const osg::FrameStamp* fs = state->getFrameStamp(); int frameNumber = fs ? fs->getFrameNumber() : 0; - - // osg::notify(osg::NOTICE)<<"Frame number "<tick(); - - _sceneView->cull(); - - osg::Timer_t afterCullTick = osg::Timer::instance()->tick(); - - - const osg::Drawable::Extensions* extensions = stats ? osg::Drawable::getExtensions(state->getContextID(),true) : 0; -#if 0 - bool aquireGPUStats = extensions && extensions->isTimerQuerySupported(); -#else - bool aquireGPUStats = false; -#endif - - if (aquireGPUStats) + if (!_initialized) { - if (_checkForQuery) - { - // Wait for all results to become available - GLint available = 0; - extensions->glGetQueryObjectiv(_query, GL_QUERY_RESULT_AVAILABLE, &available); - - if (!available) - { - osg::notify(osg::INFO)<<"Stats not available - forcing a glFinish"<glGetQueryObjectiv(_query, GL_QUERY_RESULT_AVAILABLE, &available); - } - - if (available) - { - GLuint64EXT timeElapsed = 0; - extensions->glGetQueryObjectui64v(_query, GL_QUERY_RESULT, &timeElapsed); - stats->setAttribute(frameNumber-1, "GPU draw time taken", double(timeElapsed)*1e-9); - } - else - { - osg::notify(osg::INFO)<<"Stats not available - query has been lost."<glGenQueries(1, &_query); - } - } - else - { - // Create a query object. - extensions->glGenQueries(1, &_query); - } - - extensions->glBeginQuery(GL_TIME_ELAPSED, _query); - - _sceneView->draw(); - - double availableTime = 0.004; // 4 ms - if (_databasePager.valid()) - { - _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime); - } - _sceneView->flushDeletedGLObjects(availableTime); - - extensions->glEndQuery(GL_TIME_ELAPSED); - - _checkForQuery = true; + _initialized = true; + _extensions = stats ? osg::Drawable::getExtensions(state->getContextID(),true) : 0; + _aquireGPUStats = _extensions && _extensions->isTimerQuerySupported(); + _previousQueryTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); } - else - { - _sceneView->draw(); + +// _aquireGPUStats = false; - double availableTime = 0.004; // 4 ms - if (_databasePager.valid()) - { - _databasePager->compileGLObjects(*(state), availableTime); - } - _sceneView->flushDeletedGLObjects(availableTime); + + if (_aquireGPUStats) + { + checkQuery(stats); + } + + // do cull taversal + osg::Timer_t beforeCullTick = osg::Timer::instance()->tick(); + _sceneView->cull(); + osg::Timer_t afterCullTick = osg::Timer::instance()->tick(); + + + // do draw traveral + if (_aquireGPUStats) + { + checkQuery(stats); + beginQuery(frameNumber); + } + + _sceneView->draw(); + + double availableTime = 0.004; // 4 ms + if (_databasePager.valid()) + { + _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime); + } + _sceneView->flushDeletedGLObjects(availableTime); + + if (_aquireGPUStats) + { + endQuery(); + checkQuery(stats); } osg::Timer_t afterDrawTick = osg::Timer::instance()->tick(); + if (stats) { stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick)); @@ -566,8 +603,13 @@ struct ViewerRenderingOperation : public osg::GraphicsOperation osg::observer_ptr _databasePager; osg::Timer_t _startTick; - bool _checkForQuery; - GLuint _query; + + bool _initialized; + bool _aquireGPUStats; + const osg::Drawable::Extensions* _extensions; + QueryFrameNumberList _queryFrameNumberList; + QueryList _availableQueryObjects; + double _previousQueryTime; }; void Viewer::setUpRenderingSupport()