Added new Viewer threading model options

This commit is contained in:
Robert Osfield 2007-02-06 14:38:08 +00:00
parent eeaad74021
commit 3de205ec45
4 changed files with 118 additions and 42 deletions

View File

@ -49,16 +49,24 @@ public:
switch(viewer->getThreadingModel()) switch(viewer->getThreadingModel())
{ {
case(osgViewer::Viewer::SingleThreaded): case(osgViewer::Viewer::SingleThreaded):
viewer->setThreadingModel(osgViewer::Viewer::ThreadPerContext); viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerContext' selected."<<std::endl; osg::notify(osg::NOTICE)<<"Threading model 'CullDrawThreadPerContext' selected."<<std::endl;
break; break;
case(osgViewer::Viewer::ThreadPerContext): case(osgViewer::Viewer::CullDrawThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::ThreadPerCamera); viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerCamera' selected."<<std::endl; osg::notify(osg::NOTICE)<<"Threading model 'DrawThreadPerContext' selected."<<std::endl;
break; break;
case(osgViewer::Viewer::ThreadPerCamera): case(osgViewer::Viewer::DrawThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'CullThreadPerCameraDrawThreadPerContext' selected."<<std::endl;
break;
case(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded); viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
osg::notify(osg::NOTICE)<<"Threading model 'SingleTheaded' selected."<<std::endl; osg::notify(osg::NOTICE)<<"Threading model 'SingleThreaded' selected."<<std::endl;
break;
case(osgViewer::Viewer::AutomaticSelection):
viewer->setThreadingModel(viewer->suggestBestThreadingModel());
osg::notify(osg::NOTICE)<<"Threading model 'AutomaticSelection' selected."<<std::endl;
break; break;
} }
return true; return true;

View File

@ -27,16 +27,24 @@ public:
switch(viewer->getThreadingModel()) switch(viewer->getThreadingModel())
{ {
case(osgViewer::Viewer::SingleThreaded): case(osgViewer::Viewer::SingleThreaded):
viewer->setThreadingModel(osgViewer::Viewer::ThreadPerContext); viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerContext' selected."<<std::endl; osg::notify(osg::NOTICE)<<"Threading model 'CullDrawThreadPerContext' selected."<<std::endl;
break; break;
case(osgViewer::Viewer::ThreadPerContext): case(osgViewer::Viewer::CullDrawThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::ThreadPerCamera); viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerCamera' selected."<<std::endl; osg::notify(osg::NOTICE)<<"Threading model 'DrawThreadPerContext' selected."<<std::endl;
break; break;
case(osgViewer::Viewer::ThreadPerCamera): case(osgViewer::Viewer::DrawThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
osg::notify(osg::NOTICE)<<"Threading model 'CullThreadPerCameraDrawThreadPerContext' selected."<<std::endl;
break;
case(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext):
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded); viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
osg::notify(osg::NOTICE)<<"Threading model 'SingleTheaded' selected."<<std::endl; osg::notify(osg::NOTICE)<<"Threading model 'SingleThreaded' selected."<<std::endl;
break;
case(osgViewer::Viewer::AutomaticSelection):
viewer->setThreadingModel(viewer->suggestBestThreadingModel());
osg::notify(osg::NOTICE)<<"Threading model 'AutomaticSelection' selected."<<std::endl;
break; break;
} }
return true; return true;
@ -241,8 +249,9 @@ int main( int argc, char **argv )
osgViewer::Viewer viewer; osgViewer::Viewer viewer;
while (arguments.read("-s")) { viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); } while (arguments.read("-s")) { viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); }
while (arguments.read("-g")) { viewer.setThreadingModel(osgViewer::Viewer::ThreadPerContext); } while (arguments.read("-g")) { viewer.setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext); }
while (arguments.read("-c")) { viewer.setThreadingModel(osgViewer::Viewer::ThreadPerCamera); } while (arguments.read("-d")) { viewer.setThreadingModel(osgViewer::Viewer::DrawThreadPerContext); }
while (arguments.read("-c")) { viewer.setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext); }
bool limitNumberOfFrames = false; bool limitNumberOfFrames = false;
unsigned int maxFrames = 10; unsigned int maxFrames = 10;

View File

@ -53,8 +53,10 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View
enum ThreadingModel enum ThreadingModel
{ {
SingleThreaded, SingleThreaded,
ThreadPerContext, CullDrawThreadPerContext,
ThreadPerCamera DrawThreadPerContext,
CullThreadPerCameraDrawThreadPerContext,
AutomaticSelection
}; };
/** Set the threading model the rendering traversals will use.*/ /** Set the threading model the rendering traversals will use.*/
@ -69,6 +71,8 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View
/** Get whether the main thread, calling frame(), should be used for the rendering traversals.*/ /** Get whether the main thread, calling frame(), should be used for the rendering traversals.*/
bool getUseMainThreadForRenderingTraversals() const { return _useMainThreadForRenderingTraversal; } bool getUseMainThreadForRenderingTraversals() const { return _useMainThreadForRenderingTraversal; }
/** Let the viewer suggest the best threading model for the viewers camera/window setup and the hardware available.*/
ThreadingModel suggestBestThreadingModel();
enum BarrierPosition enum BarrierPosition
{ {
@ -178,6 +182,7 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View
} }
} }
bool _firstFrame; bool _firstFrame;
bool _done; bool _done;

View File

@ -541,9 +541,10 @@ Viewer::Viewer():
_done(false), _done(false),
_keyEventSetsDone(osgGA::GUIEventAdapter::KEY_Escape), _keyEventSetsDone(osgGA::GUIEventAdapter::KEY_Escape),
_quitEventSetsDone(true), _quitEventSetsDone(true),
_threadingModel(SingleThreaded), // _threadingModel(SingleThreaded),
// _threadingModel(ThreadPerContext), // _threadingModel(CullDrawThreadPerContext),
// _threadingModel(ThreadPerCamera), // _threadingModel(CullThreadPerCameraDrawThreadPerContext),
_threadingModel(AutomaticSelection),
_threadsRunning(false), _threadsRunning(false),
_useMainThreadForRenderingTraversal(true), _useMainThreadForRenderingTraversal(true),
_endBarrierPosition(AfterSwapBuffers), _endBarrierPosition(AfterSwapBuffers),
@ -570,7 +571,7 @@ Viewer::~Viewer()
Threads threads; Threads threads;
getAllThreads(threads); getAllThreads(threads);
osg::notify(osg::NOTICE)<<"start destrcutor getThreads = "<<threads.size()<<std::endl; osg::notify(osg::INFO)<<"Viewer::~Viewer():: start destructor getThreads = "<<threads.size()<<std::endl;
stopThreading(); stopThreading();
@ -601,7 +602,7 @@ Viewer::~Viewer()
getAllThreads(threads); getAllThreads(threads);
osg::notify(osg::NOTICE)<<"end destrcutor getThreads = "<<threads.size()<<std::endl; osg::notify(osg::INFO)<<"Viewer::~Viewer() end destrcutor getThreads = "<<threads.size()<<std::endl;
} }
@ -734,7 +735,7 @@ void Viewer::stopThreading()
{ {
if (!_threadsRunning) return; if (!_threadsRunning) return;
osg::notify(osg::NOTICE)<<"Viewer::stopThreading() - stopping threading"<<std::endl; osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopping threading"<<std::endl;
Contexts contexts; Contexts contexts;
getContexts(contexts); getContexts(contexts);
@ -811,7 +812,7 @@ void Viewer::stopThreading()
_endRenderingDispatchBarrier = 0; _endRenderingDispatchBarrier = 0;
_numThreadsOnBarrier = 0; _numThreadsOnBarrier = 0;
_endDynamicDrawBlock = 0; _endDynamicDrawBlock = 0;
osg::notify(osg::NOTICE)<<"Viewer::stopThreading() - stopped threading :-)"<<std::endl; osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading."<<std::endl;
} }
// Compile operation, that compile OpenGL objects. // Compile operation, that compile OpenGL objects.
@ -863,28 +864,70 @@ struct ViewerRunOperations : public osg::Operation
} }
}; };
Viewer::ThreadingModel Viewer::suggestBestThreadingModel()
{
Contexts contexts;
getContexts(contexts);
if (contexts.empty()) return SingleThreaded;
Cameras cameras;
getCameras(cameras);
if (cameras.empty()) return SingleThreaded;
int numProcessors = OpenThreads::GetNumberOfProcessors();
if (contexts.size()==1)
{
if (numProcessors==1) return SingleThreaded;
else return DrawThreadPerContext;
}
if (numProcessors >= static_cast<int>(cameras.size()+contexts.size()))
{
return CullThreadPerCameraDrawThreadPerContext;
}
#if 1
return DrawThreadPerContext;
#else
return CullDrawThreadPerContext;
#endif
}
unsigned int Viewer::computeNumberOfThreadsIncludingMainRequired() unsigned int Viewer::computeNumberOfThreadsIncludingMainRequired()
{ {
unsigned int numThreadsOnBarrier = 1; unsigned int numThreadsOnBarrier = 1;
switch(_threadingModel)
ThreadingModel threadingModel = _threadingModel==AutomaticSelection ? suggestBestThreadingModel() : _threadingModel;
switch(threadingModel)
{ {
case(SingleThreaded): case(SingleThreaded):
numThreadsOnBarrier = 1; numThreadsOnBarrier = 1;
break; break;
case(ThreadPerContext): case(CullDrawThreadPerContext):
{ {
Contexts contexts; Contexts contexts;
getContexts(contexts); getContexts(contexts);
numThreadsOnBarrier = contexts.size()+1; numThreadsOnBarrier = contexts.size()+1;
break; break;
} }
case(ThreadPerCamera): case(DrawThreadPerContext):
numThreadsOnBarrier = 1;
break;
case(CullThreadPerCameraDrawThreadPerContext):
{ {
Cameras cameras; Cameras cameras;
getCameras(cameras); getCameras(cameras);
numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1; numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1;
break; break;
} }
default:
osg::notify(osg::NOTICE)<<"Error: Threading model not selected"<<std::endl;
} }
return numThreadsOnBarrier; return numThreadsOnBarrier;
} }
@ -898,6 +941,8 @@ void Viewer::startThreading()
// release any context held by the main thread. // release any context held by the main thread.
releaseContext(); releaseContext();
_threadingModel = _threadingModel==AutomaticSelection ? suggestBestThreadingModel() : _threadingModel;
Contexts contexts; Contexts contexts;
getContexts(contexts); getContexts(contexts);
@ -910,12 +955,18 @@ void Viewer::startThreading()
case(SingleThreaded): case(SingleThreaded):
_numThreadsOnBarrier = 1; _numThreadsOnBarrier = 1;
return; return;
case(ThreadPerContext): case(CullDrawThreadPerContext):
_numThreadsOnBarrier = contexts.size()+1; _numThreadsOnBarrier = contexts.size()+1;
break; break;
case(ThreadPerCamera): case(DrawThreadPerContext):
_numThreadsOnBarrier = 1;
break;
case(CullThreadPerCameraDrawThreadPerContext):
_numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1; _numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1;
break; break;
default:
osg::notify(osg::NOTICE)<<"Error: Threading model not selected"<<std::endl;
return;
} }
// using multi-threading so make sure that new objects are allocated with thread safe ref/unref // using multi-threading so make sure that new objects are allocated with thread safe ref/unref
@ -932,7 +983,7 @@ void Viewer::startThreading()
getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
} }
osg::notify(osg::NOTICE)<<"_numThreadsOnBarrier = "<<_numThreadsOnBarrier<<std::endl; osg::notify(osg::INFO)<<"_numThreadsOnBarrier = "<<_numThreadsOnBarrier<<std::endl;
int numProcessors = OpenThreads::GetNumberOfProcessors(); int numProcessors = OpenThreads::GetNumberOfProcessors();
@ -942,6 +993,8 @@ void Viewer::startThreading()
unsigned int numViewerDoubleBufferedRenderingOperation = 0; unsigned int numViewerDoubleBufferedRenderingOperation = 0;
bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext;
// reset any double buffer graphics objects // reset any double buffer graphics objects
for(citr = contexts.begin(); for(citr = contexts.begin();
citr != contexts.end(); citr != contexts.end();
@ -958,7 +1011,7 @@ void Viewer::startThreading()
ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get()); ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
if (vdbro) if (vdbro)
{ {
vdbro->setGraphicsThreadDoesCull( _threadingModel != ThreadPerCamera ); vdbro->setGraphicsThreadDoesCull( graphicsThreadsDoesCull );
vdbro->_done = false; vdbro->_done = false;
++numViewerDoubleBufferedRenderingOperation; ++numViewerDoubleBufferedRenderingOperation;
} }
@ -966,13 +1019,14 @@ void Viewer::startThreading()
} }
if (_threadingModel==ThreadPerContext) if (_threadingModel==CullDrawThreadPerContext)
{ {
_startRenderingBarrier = 0; _startRenderingBarrier = 0;
_endRenderingDispatchBarrier = 0; _endRenderingDispatchBarrier = 0;
_endDynamicDrawBlock = 0; _endDynamicDrawBlock = 0;
} }
else if (_threadingModel==ThreadPerCamera) else if (_threadingModel==DrawThreadPerContext ||
_threadingModel==CullThreadPerCameraDrawThreadPerContext)
{ {
_startRenderingBarrier = 0; _startRenderingBarrier = 0;
_endRenderingDispatchBarrier = 0; _endRenderingDispatchBarrier = 0;
@ -1011,12 +1065,12 @@ void Viewer::startThreading()
gc->getGraphicsThread()->add(new ViewerCompileOperation(getSceneData())); gc->getGraphicsThread()->add(new ViewerCompileOperation(getSceneData()));
// add the startRenderingBarrier // add the startRenderingBarrier
if (_threadingModel==ThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get());
// add the rendering operation itself. // add the rendering operation itself.
gc->getGraphicsThread()->add(new ViewerRunOperations()); gc->getGraphicsThread()->add(new ViewerRunOperations());
if (_threadingModel==ThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid())
{ {
// add the endRenderingDispatchBarrier // add the endRenderingDispatchBarrier
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
@ -1027,7 +1081,7 @@ void Viewer::startThreading()
// add the swap buffers // add the swap buffers
gc->getGraphicsThread()->add(swapOp.get()); gc->getGraphicsThread()->add(swapOp.get());
if (_threadingModel==ThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid())
{ {
// add the endRenderingDispatchBarrier // add the endRenderingDispatchBarrier
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
@ -1038,7 +1092,7 @@ void Viewer::startThreading()
} }
if (_threadingModel==ThreadPerCamera && _numThreadsOnBarrier>1) if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && _numThreadsOnBarrier>1)
{ {
Cameras::iterator camItr = cameras.begin(); Cameras::iterator camItr = cameras.begin();
if (_useMainThreadForRenderingTraversal) ++camItr; if (_useMainThreadForRenderingTraversal) ++camItr;
@ -1050,7 +1104,7 @@ void Viewer::startThreading()
osg::Camera* camera = *camItr; osg::Camera* camera = *camItr;
camera->createCameraThread(); camera->createCameraThread();
#if 0 #if 1
if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors); if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors);
#else #else
if (affinity) camera->getCameraThread()->setProcessorAffinity(1); if (affinity) camera->getCameraThread()->setProcessorAffinity(1);
@ -1263,13 +1317,13 @@ void Viewer::setUpRenderingSupport()
osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance(); osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance();
osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0; osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0;
bool graphicsThreadDoesCull = _threadingModel!=ThreadPerCamera; bool graphicsThreadDoesCull = _threadingModel!=CullThreadPerCameraDrawThreadPerContext;
unsigned int numViewerDoubleBufferedRenderingOperation = 0; unsigned int numViewerDoubleBufferedRenderingOperation = 0;
Cameras localCameras; Cameras localCameras;
getCameras(localCameras); getCameras(localCameras);
if (true)//(_threadingModel==ThreadPerCamera) if (true)//(_threadingModel==CullThreadPerCameraDrawThreadPerContext)
{ {
for(Contexts::iterator gcitr = contexts.begin(); for(Contexts::iterator gcitr = contexts.begin();
gcitr != contexts.end(); gcitr != contexts.end();