From bad2a4cc7c4d17afbbc6d4adabb9292e7abf72ec Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 6 Feb 2007 11:03:13 +0000 Subject: [PATCH] Further work on support for ThreadPerCamera, and improved the efficiency of SingleThraeded --- include/osgViewer/Viewer | 28 ++++ src/osgViewer/Viewer.cpp | 350 +++++++++++++++++++++++++++------------ 2 files changed, 275 insertions(+), 103 deletions(-) diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index cbd4ce914..179b3928c 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -133,6 +133,12 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View typedef std::vector Cameras; void getCameras(Cameras& cameras, bool onlyActive=true); + typedef std::vector Threads; + void getAllThreads(Threads& threads, bool onlyActive=true); + + typedef std::vector OperationsThreads; + void getOperationsThreads(OperationsThreads& threads, bool onlyActive=true); + /** Set the graphics operation to call on realization of the viewers graphics windows.*/ void setRealizeOperation(osg::Operation* op) { _realizeOperation = op; } @@ -145,6 +151,8 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** Start any threads required by the viewer, as per viewers ThreadingModel.*/ void startThreading(); + + /** Set up the Operations to render the various viewer cameras on the viewers graphics windows.*/ void setUpRenderingSupport(); @@ -152,6 +160,24 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View void checkWindowStatus(); + inline void makeCurrent(osg::GraphicsContext* gc) + { + if (_currentContext==gc) return; + + releaseContext(); + + if (gc && gc->makeCurrent()) _currentContext = gc; + } + + inline void releaseContext() + { + if (_currentContext.valid()) + { + _currentContext->releaseContext(); + _currentContext = 0; + } + } + bool _firstFrame; bool _done; @@ -183,6 +209,8 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View osg::ref_ptr _eventVisitor; osg::ref_ptr _realizeOperation; + + osg::observer_ptr _currentContext; }; diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index c73df4e48..8f30367ce 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -135,6 +135,8 @@ struct ViewerRenderingOperation : public osg::Operation, public ViewerQuerySuppo _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); } + osg::Camera* getCamera() { return _sceneView->getCamera(); } + virtual void operator () (osg::Object*) { if (!_sceneView) return; @@ -242,6 +244,8 @@ struct ViewerDoubleBufferedRenderingOperation : public osg::Operation, public Vi // osg::notify(osg::NOTICE)<<"constructed"<getCamera(); } + void setGraphicsThreadDoesCull(bool flag) { if (_graphicsThreadDoesCull==flag) return; @@ -490,7 +494,12 @@ struct ViewerDoubleBufferedRenderingOperation : public osg::Operation, public Vi virtual void operator () (osg::Object* object) { osg::GraphicsContext* context = dynamic_cast(object); - if (!context) return; + if (!context) + { + osg::Camera* camera = dynamic_cast(object); + if (camera) cull(); + return; + } //osg::notify(osg::NOTICE)<<"GraphicsCall "< lock( *(gc->getOperationsMutex()) ); osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue(); @@ -744,19 +768,27 @@ void Viewer::stopThreading() } // delete all the graphics threads. - for(Contexts::iterator itr = contexts.begin(); - itr != contexts.end(); - ++itr) + for(gcitr = contexts.begin(); + gcitr != contexts.end(); + ++gcitr) { - (*itr)->setGraphicsThread(0); + (*gcitr)->setGraphicsThread(0); + } + + // delete all the camera threads. + for(citr = cameras.begin(); + citr != cameras.end(); + ++citr) + { + (*citr)->setCameraThread(0); } // reset any double buffer graphics objects - for(citr = contexts.begin(); - citr != contexts.end(); - ++citr) + for(gcitr = contexts.begin(); + gcitr != contexts.end(); + ++gcitr) { - osg::GraphicsContext* gc = (*citr); + osg::GraphicsContext* gc = (*gcitr); OpenThreads::ScopedLock lock( *(gc->getOperationsMutex()) ); osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue(); @@ -779,7 +811,7 @@ void Viewer::stopThreading() _endRenderingDispatchBarrier = 0; _numThreadsOnBarrier = 0; _endDynamicDrawBlock = 0; - osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading :-)"<resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); } - - - Contexts contexts; - getContexts(contexts); - + osg::notify(osg::NOTICE)<<"_numThreadsOnBarrier = "<<_numThreadsOnBarrier<1) + { + _startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); + _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); + } + + + osg::ref_ptr swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION); osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); - citr = contexts.begin(); - unsigned int processNum = 0; - - if (firstContextAsMainThread) - { - ++processNum; - ++citr; - } - - for(; + unsigned int processNum = 1; + for(citr = contexts.begin(); citr != contexts.end(); - ++citr, - ++processNum) + ++citr, ++processNum) { osg::GraphicsContext* gc = (*citr); @@ -973,37 +1002,99 @@ void Viewer::startThreading() // create the a graphics thread for this context gc->createGraphicsThread(); +#if 1 if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); +#else + if (affinity) gc->getGraphicsThread()->setProcessorAffinity(1); +#endif gc->getGraphicsThread()->add(new ViewerCompileOperation(getSceneData())); // add the startRenderingBarrier - if (_startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); + if (_threadingModel==ThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); // add the rendering operation itself. gc->getGraphicsThread()->add(new ViewerRunOperations()); - if (_endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) + if (_threadingModel==ThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); } + if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get()); + // add the swap buffers gc->getGraphicsThread()->add(swapOp.get()); - if (_endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) + if (_threadingModel==ThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); } + + } - if (firstContextAsMainThread) + + if (_threadingModel==ThreadPerCamera && _numThreadsOnBarrier>1) { - if (affinity) OpenThreads::SetProcessorAffinityOfCurrentThread(0); + Cameras::iterator camItr = cameras.begin(); + if (_useMainThreadForRenderingTraversal) ++camItr; + + for(; + camItr != cameras.end(); + ++camItr, ++processNum) + { + osg::Camera* camera = *camItr; + camera->createCameraThread(); + +#if 0 + if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors); +#else + if (affinity) camera->getCameraThread()->setProcessorAffinity(1); +#endif + osg::GraphicsContext* gc = camera->getGraphicsContext(); + + // add the startRenderingBarrier + if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get()); + + OpenThreads::ScopedLock lock( *(gc->getOperationsMutex()) ); + osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue(); + for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin(); + oitr != operations.end(); + ++oitr) + { + ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast(oitr->get()); + if (vdbro && vdbro->getCamera()==camera) + { + camera->getCameraThread()->add(vdbro); + } + } + + if (_endRenderingDispatchBarrier.valid()) + { + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + } + + } + + for(camItr = cameras.begin(); + camItr != cameras.end(); + ++camItr, ++processNum) + { + osg::Camera* camera = *camItr; + if (camera->getCameraThread() && !camera->getCameraThread()->isRunning()) + { + osg::notify(osg::INFO)<<" camera->getCameraThread()-> "<getCameraThread()<getCameraThread()->startThread(); + } + } } + + if (affinity) OpenThreads::SetProcessorAffinityOfCurrentThread(0); for(citr = contexts.begin(); citr != contexts.end(); @@ -1092,17 +1183,72 @@ void Viewer::getCameras(Cameras& cameras, bool onlyActive) { cameras.clear(); - if (onlyActive || _camera->getGraphicsContext()) cameras.push_back(_camera.get()); + if (!onlyActive || _camera->getGraphicsContext()) cameras.push_back(_camera.get()); for(Slaves::iterator itr = _slaves.begin(); itr != _slaves.end(); ++itr) { - if (onlyActive || itr->_camera->getGraphicsContext()) cameras.push_back(itr->_camera.get()); + if (!onlyActive || itr->_camera->getGraphicsContext()) cameras.push_back(itr->_camera.get()); } } +void Viewer::getAllThreads(Threads& threads, bool onlyActive) +{ + OperationsThreads operationsThreads; + getOperationsThreads(operationsThreads); + + for(OperationsThreads::iterator itr = operationsThreads.begin(); + itr != operationsThreads.end(); + ++itr) + { + threads.push_back(*itr); + } + + if (_scene.valid() && + _scene->getDatabasePager() && + (!onlyActive || _scene->getDatabasePager()->isRunning())) + { + threads.push_back(_scene->getDatabasePager()); + } +} + + +void Viewer::getOperationsThreads(OperationsThreads& threads, bool onlyActive) +{ + threads.clear(); + + Contexts contexts; + getContexts(contexts); + for(Contexts::iterator gcitr = contexts.begin(); + gcitr != contexts.end(); + ++gcitr) + { + osg::GraphicsContext* gc = *gcitr; + if (gc->getGraphicsThread() && + (!onlyActive || gc->getGraphicsThread()->isRunning()) ) + { + threads.push_back(gc->getGraphicsThread()); + } + } + + Cameras cameras; + getCameras(cameras); + for(Cameras::iterator citr = cameras.begin(); + citr != cameras.end(); + ++citr) + { + osg::Camera* camera = *citr; + if (camera->getCameraThread() && + (!onlyActive || camera->getCameraThread()->isRunning()) ) + { + threads.push_back(camera->getCameraThread()); + } + } + +} + void Viewer::setUpRenderingSupport() { bool threadsRunningBeforeSetUpRenderingSupport = _threadsRunning; @@ -1740,13 +1886,12 @@ void Viewer::renderingTraversals() ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast(oitr->get()); if (vdbro) { - if (!vdbro->getGraphicsThreadDoesCull()) + if (!vdbro->getGraphicsThreadDoesCull() && !(vdbro->getCamera()->getCameraThread())) { vdbro->cull(); } } } - } for(itr = contexts.begin(); @@ -1756,22 +1901,13 @@ void Viewer::renderingTraversals() if (_done) return; if (!((*itr)->getGraphicsThread())) { - (*itr)->makeCurrent(); + makeCurrent(*itr); (*itr)->runOperations(); - (*itr)->releaseContext(); } } // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<tick(); - _endDynamicDrawBlock->block(); - // osg::notify(osg::NOTICE)<<"Time waiting "<delta_m(startTick, osg::Timer::instance()->tick())<block(); @@ -1783,9 +1919,8 @@ void Viewer::renderingTraversals() if (!((*itr)->getGraphicsThread())) { - (*itr)->makeCurrent(); + makeCurrent(*itr); (*itr)->swapBuffers(); - (*itr)->releaseContext(); } } @@ -1794,6 +1929,15 @@ void Viewer::renderingTraversals() dp->signalEndFrame(); } + // wait till the dynamic draw is complete. + if (_endDynamicDrawBlock.valid()) + { + // osg::Timer_t startTick = osg::Timer::instance()->tick(); + _endDynamicDrawBlock->block(); + // osg::notify(osg::NOTICE)<<"Time waiting "<delta_m(startTick, osg::Timer::instance()->tick())<collectStats("update")) { double endRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());