diff --git a/include/osgViewer/Renderer b/include/osgViewer/Renderer index 135c2c3bc..d45c7237b 100644 --- a/include/osgViewer/Renderer +++ b/include/osgViewer/Renderer @@ -81,21 +81,40 @@ class OSGVIEWER_EXPORT Renderer : public osg::GraphicsOperation, public OpenGLQu virtual ~Renderer(); + + bool _serializeDraw; + osg::observer_ptr _camera; bool _done; bool _graphicsThreadDoesCull; - unsigned int _currentCull; - unsigned int _currentDraw; - - OpenThreads::Mutex _mutex[2]; - bool _lockHeld[2]; + osg::ref_ptr _sceneView[2]; - int _frameNumber[2]; osg::ref_ptr _flushOperation; + struct TheadSafeQueue + { + OpenThreads::Mutex _mutex; + OpenThreads::Block _block; + typedef std::list SceneViewList; + SceneViewList _queue; + + void release() + { + _block.release(); + } + + osgUtil::SceneView* takeFront(); + + void add(osgUtil::SceneView* sv); + }; + + + TheadSafeQueue _availableQueue; + TheadSafeQueue _drawQueue; + }; } diff --git a/src/osgViewer/Renderer.cpp b/src/osgViewer/Renderer.cpp index cf9438372..46b6823f4 100644 --- a/src/osgViewer/Renderer.cpp +++ b/src/osgViewer/Renderer.cpp @@ -119,11 +119,40 @@ void OpenGLQuerySupport::initialize(osg::State* state) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // -// Renderer +// TheadSafeQueue +osgUtil::SceneView* Renderer::TheadSafeQueue::takeFront() +{ + if (_queue.empty()) _block.block(); + + OpenThreads::ScopedLock lock(_mutex); + if (_queue.empty()) return 0; + + osgUtil::SceneView* front = _queue.front(); + _queue.pop_front(); + + if (_queue.empty()) _block.set(false); + + return front; +} + +void Renderer::TheadSafeQueue::add(osgUtil::SceneView* sv) +{ + OpenThreads::ScopedLock lock(_mutex); + _queue.push_back(sv); + _block.set(true); +} + +static OpenThreads::Mutex s_drawSerializerMutex; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// +// Renderer Renderer::Renderer(osg::Camera* camera): osg::GraphicsOperation("Renderer",true), OpenGLQuerySupport(), + _serializeDraw(true), _camera(camera), _done(false), _graphicsThreadDoesCull(true) @@ -131,9 +160,6 @@ Renderer::Renderer(osg::Camera* camera): DEBUG_MESSAGE<<"Render::Render() "<setCamera(_camera.get(), false); _sceneView[1]->setCamera(_camera.get(), false); - _currentCull = 0; - _currentDraw = 0; - // lock the mutex for the current cull SceneView to // prevent the draw traversal from reading from it before the cull traversal has been completed. - if (!_graphicsThreadDoesCull) - { - _mutex[_currentCull].lock(); - _lockHeld[_currentCull] = true; - } + _availableQueue.add(_sceneView[0].get()); + _availableQueue.add(_sceneView[1].get()); + + DEBUG_MESSAGE<<"_availableQueue.size()="<<_availableQueue._queue.size()<getFrameStamp(); int frameNumber = fs ? fs->getFrameNumber() : 0; - _frameNumber[_currentCull] = frameNumber; - // do cull taversal osg::Timer_t beforeCullTick = osg::Timer::instance()->tick(); @@ -296,20 +289,11 @@ void Renderer::cull() stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick)); stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick)); } + + _drawQueue.add(sceneView); + } - - // relase the mutex associated with this cull traversal, let the draw commence. - _lockHeld[_currentCull] = false; - _mutex[_currentCull].unlock(); - - // swap which SceneView we need to do cull traversal on next. - _currentCull = 1 - _currentCull; - - // aquire the lock for it for the new cull traversal - _mutex[_currentCull].lock(); - _lockHeld[_currentCull] = true; - DEBUG_MESSAGE<<"end cull() "<tick(); + + osgUtil::SceneView* sceneView = _drawQueue.takeFront(); + + + + DEBUG_MESSAGE<<"draw() got SceneView "<getState()->getContextID()); osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0; if (sceneView || _done) { - OpenThreads::ScopedLock lock(_mutex[_currentDraw]); - osgViewer::View* view = dynamic_cast(_camera->getView()); osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0; @@ -347,7 +335,7 @@ void Renderer::draw() osg::Stats* stats = sceneView->getCamera()->getStats(); osg::State* state = sceneView->getState(); - int frameNumber = _frameNumber[_currentDraw]; + int frameNumber = state->getFrameStamp()->getFrameNumber(); if (!_initialized) { @@ -362,8 +350,6 @@ void Renderer::draw() state->getDynamicObjectRenderingCompletedCallback()->completed(state); } - osg::Timer_t beforeDrawTick = osg::Timer::instance()->tick(); - bool aquireGPUStats = stats && _timerQuerySupported && stats->collectStats("gpu"); if (aquireGPUStats) @@ -378,7 +364,21 @@ void Renderer::draw() beginQuery(frameNumber); } - sceneView->draw(); + osg::Timer_t beforeDrawTick; + + if (_serializeDraw) + { + OpenThreads::ScopedLock lock(s_drawSerializerMutex); + beforeDrawTick = osg::Timer::instance()->tick(); + sceneView->draw(); + } + else + { + beforeDrawTick = osg::Timer::instance()->tick(); + sceneView->draw(); + } + + _availableQueue.add(sceneView); double availableTime = 0.004; // 4 ms if (databasePager && databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID())) @@ -401,11 +401,13 @@ void Renderer::draw() checkQuery(stats); } - glFlush(); - - + //glFlush(); + osg::Timer_t afterDrawTick = osg::Timer::instance()->tick(); +// osg::notify(osg::NOTICE)<<"Time wait for draw = "<delta_m(startDrawTick, beforeDrawTick)<setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick)); @@ -414,8 +416,6 @@ void Renderer::draw() } } - _currentDraw = 1-_currentDraw; - DEBUG_MESSAGE<<"end draw() "<getState()->getContextID()); osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0; - OpenThreads::ScopedLock lock(_mutex[_currentDraw]); - if (_done) { osg::notify(osg::INFO)<<"Render::release() causing cull_draw to exit"<draw(); + osg::Timer_t beforeDrawTick; + + if (_serializeDraw) + { + OpenThreads::ScopedLock lock(s_drawSerializerMutex); + + beforeDrawTick = osg::Timer::instance()->tick(); + sceneView->draw(); + } + else + { + beforeDrawTick = osg::Timer::instance()->tick(); + sceneView->draw(); + } double availableTime = 0.004; // 4 ms if (databasePager && databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID())) @@ -519,9 +531,9 @@ void Renderer::cull_draw() stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick)); stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick)); - stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, afterCullTick)); + stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick)); stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick)); - stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(afterCullTick, afterDrawTick)); + stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick)); } DEBUG_MESSAGE<<"end cull_draw() "<