Changeset 6097

Show
Ignore:
Timestamp:
02/06/07 12:03:13
Author:
robert
Message:

Further work on support for ThreadPerCamera?, and improved the efficiency of SingleThraeded?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • OpenSceneGraph/trunk/include/osgViewer/Viewer

    r6088 r6097  
    134134        void getCameras(Cameras& cameras, bool onlyActive=true); 
    135135 
     136        typedef std::vector<OpenThreads::Thread*> Threads; 
     137        void getAllThreads(Threads& threads, bool onlyActive=true); 
     138 
     139        typedef std::vector<osg::OperationsThread*> OperationsThreads; 
     140        void getOperationsThreads(OperationsThreads& threads, bool onlyActive=true); 
     141 
    136142        /** Set the graphics operation to call on realization of the viewers graphics windows.*/ 
    137143        void setRealizeOperation(osg::Operation* op) { _realizeOperation = op; } 
     
    145151        /** Start any threads required by the viewer, as per viewers ThreadingModel.*/ 
    146152        void startThreading();         
     153 
     154 
    147155 
    148156        /** Set up the Operations to render the various viewer cameras on the viewers graphics windows.*/ 
     
    153161        void checkWindowStatus(); 
    154162         
     163        inline void makeCurrent(osg::GraphicsContext* gc) 
     164        { 
     165            if (_currentContext==gc) return; 
     166             
     167            releaseContext(); 
     168             
     169            if (gc && gc->makeCurrent()) _currentContext = gc; 
     170        } 
     171         
     172        inline void releaseContext() 
     173        { 
     174            if (_currentContext.valid()) 
     175            { 
     176                _currentContext->releaseContext(); 
     177                _currentContext = 0; 
     178            } 
     179        } 
     180         
    155181        bool _firstFrame; 
    156182         
     
    184210         
    185211        osg::ref_ptr<osg::Operation>        _realizeOperation; 
     212         
     213        osg::observer_ptr<osg::GraphicsContext> _currentContext; 
    186214}; 
    187215 
  • OpenSceneGraph/trunk/src/osgViewer/Viewer.cpp

    r6095 r6097  
    136136    } 
    137137     
     138    osg::Camera* getCamera() { return _sceneView->getCamera(); } 
     139 
    138140    virtual void operator () (osg::Object*) 
    139141    { 
     
    243245    } 
    244246     
     247    osg::Camera* getCamera() { return _sceneView[0]->getCamera(); } 
     248 
    245249    void setGraphicsThreadDoesCull(bool flag) 
    246250    { 
     
    491495    { 
    492496        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object); 
    493         if (!context) return; 
     497        if (!context) 
     498        { 
     499            osg::Camera* camera = dynamic_cast<osg::Camera*>(object); 
     500            if (camera) cull(); 
     501            return; 
     502        } 
    494503 
    495504        //osg::notify(osg::NOTICE)<<"GraphicsCall "<<std::endl; 
     
    533542    _keyEventSetsDone(osgGA::GUIEventAdapter::KEY_Escape), 
    534543    _quitEventSetsDone(true), 
    535 //    _threadingModel(SingleThreaded), 
    536     _threadingModel(ThreadPerContext), 
     544    _threadingModel(SingleThreaded), 
     545//    _threadingModel(ThreadPerContext), 
    537546//    _threadingModel(ThreadPerCamera), 
    538547    _threadsRunning(false), 
    539     _useMainThreadForRenderingTraversal(false), 
     548    _useMainThreadForRenderingTraversal(true), 
    540549    _endBarrierPosition(AfterSwapBuffers), 
    541550    _numThreadsOnBarrier(0) 
     
    558567    //osg::notify(osg::NOTICE)<<"Viewer::~Viewer()"<<std::endl; 
    559568 
     569 
     570    Threads threads; 
     571    getAllThreads(threads); 
     572 
     573    osg::notify(osg::NOTICE)<<"start destrcutor getThreads = "<<threads.size()<<std::endl; 
     574 
     575 
    560576    stopThreading(); 
    561577     
     
    584600    //osg::notify(osg::NOTICE)<<"finish Viewer::~Viewer()"<<std::endl; 
    585601     
     602    getAllThreads(threads); 
     603 
     604    osg::notify(osg::NOTICE)<<"end destrcutor getThreads = "<<threads.size()<<std::endl; 
     605 
    586606} 
    587607 
     
    715735    if (!_threadsRunning) return; 
    716736 
    717     osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopping threading"<<std::endl; 
     737    osg::notify(osg::NOTICE)<<"Viewer::stopThreading() - stopping threading"<<std::endl; 
    718738 
    719739    Contexts contexts; 
    720740    getContexts(contexts); 
    721741 
    722     Contexts::iterator citr; 
     742    Cameras cameras; 
     743    getCameras(cameras); 
     744 
     745    Contexts::iterator gcitr; 
     746    Cameras::iterator citr; 
    723747 
    724748    // reset any double buffer graphics objects 
    725     for(citr = contexts.begin(); 
    726         citr != contexts.end(); 
    727         ++citr) 
    728     { 
    729         osg::GraphicsContext* gc = (*citr); 
     749    for(gcitr = contexts.begin(); 
     750        gcitr != contexts.end(); 
     751        ++gcitr) 
     752    { 
     753        osg::GraphicsContext* gc = (*gcitr); 
    730754         
    731755        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) ); 
     
    745769 
    746770    // delete all the graphics threads.     
    747     for(Contexts::iterator itr = contexts.begin(); 
    748         itr != contexts.end(); 
    749         ++itr) 
    750     { 
    751         (*itr)->setGraphicsThread(0); 
     771    for(gcitr = contexts.begin(); 
     772        gcitr != contexts.end(); 
     773        ++gcitr) 
     774    { 
     775        (*gcitr)->setGraphicsThread(0); 
     776    } 
     777 
     778    // delete all the camera threads.     
     779    for(citr = cameras.begin(); 
     780        citr != cameras.end(); 
     781        ++citr) 
     782    { 
     783        (*citr)->setCameraThread(0); 
    752784    } 
    753785 
    754786    // reset any double buffer graphics objects 
    755     for(citr = contexts.begin(); 
    756         citr != contexts.end(); 
    757         ++citr) 
    758     { 
    759         osg::GraphicsContext* gc = (*citr); 
     787    for(gcitr = contexts.begin(); 
     788        gcitr != contexts.end(); 
     789        ++gcitr) 
     790    { 
     791        osg::GraphicsContext* gc = (*gcitr); 
    760792         
    761793        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) ); 
     
    780812    _numThreadsOnBarrier = 0; 
    781813    _endDynamicDrawBlock = 0; 
    782     osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading :-)"<<std::endl; 
     814    osg::notify(osg::NOTICE)<<"Viewer::stopThreading() - stopped threading :-)"<<std::endl; 
    783815} 
    784816 
     
    834866unsigned int Viewer::computeNumberOfThreadsIncludingMainRequired() 
    835867{ 
     868    unsigned int numThreadsOnBarrier = 1; 
     869    switch(_threadingModel) 
     870    { 
     871        case(SingleThreaded):  
     872            numThreadsOnBarrier = 1; 
     873            break; 
     874        case(ThreadPerContext):  
     875        { 
     876            Contexts contexts; 
     877            getContexts(contexts); 
     878            numThreadsOnBarrier = contexts.size()+1; 
     879            break; 
     880        }    
     881        case(ThreadPerCamera):  
     882        { 
     883            Cameras cameras; 
     884            getCameras(cameras); 
     885            numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1; 
     886            break; 
     887        } 
     888    } 
     889    return numThreadsOnBarrier; 
     890} 
     891 
     892void Viewer::startThreading() 
     893{ 
     894    if (_threadsRunning) return; 
     895     
     896    osg::notify(osg::INFO)<<"Viewer::startThreading() - starting threading"<<std::endl; 
     897     
     898    // release any context held by the main thread. 
     899    releaseContext(); 
     900 
    836901    Contexts contexts; 
    837902    getContexts(contexts); 
    838903 
    839     if (contexts.empty()) return 0; 
    840  
    841     if (_threadingModel==SingleThreaded) 
    842     { 
    843         return 1; 
    844     } 
    845  
    846     return _useMainThreadForRenderingTraversal ? contexts.size() : contexts.size()+1; 
    847 
    848  
    849 void Viewer::startThreading() 
    850 
    851     if (_threadsRunning) return; 
    852  
    853     osg::notify(osg::INFO)<<"Starting threading"<<std::endl; 
    854  
    855     unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired(); 
    856  
    857     // return if we don't need multiple threads. 
    858     // if (numThreadsIncludingMainThread <= 1) return; 
    859      
    860     // return if threading is already up and running 
    861 #if 0 
    862     if (numThreadsIncludingMainThread == _numThreadsOnBarrier) 
    863     { 
    864         osg::notify(osg::NOTICE)<<"Thread already started?"<<std::endl; 
    865         return; 
    866     } 
    867      
    868     if (_numThreadsOnBarrier!=0)  
    869     { 
    870         // we already have threads running but not the right number, so stop them and then create new threads. 
    871         stopThreading(); 
    872     } 
    873 #endif 
    874  
    875     osg::notify(osg::INFO)<<"Viewer::startThreading() - starting threading"<<std::endl; 
     904    Cameras cameras; 
     905    getCameras(cameras); 
     906     
     907    _numThreadsOnBarrier = 0; 
     908    switch(_threadingModel) 
     909    { 
     910        case(SingleThreaded):  
     911            _numThreadsOnBarrier = 1; 
     912            return; 
     913        case(ThreadPerContext):  
     914            _numThreadsOnBarrier = contexts.size()+1; 
     915            break; 
     916        case(ThreadPerCamera):  
     917            _numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1; 
     918            break; 
     919    } 
    876920 
    877921    // using multi-threading so make sure that new objects are allocated with thread safe ref/unref 
     
    888932        getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); 
    889933    } 
    890  
    891  
    892     Contexts contexts; 
    893     getContexts(contexts); 
    894  
    895      
     934     
     935    osg::notify(osg::NOTICE)<<"_numThreadsOnBarrier = "<<_numThreadsOnBarrier<<std::endl; 
     936 
    896937 
    897938    int numProcessors = OpenThreads::GetNumberOfProcessors(); 
    898     bool affinity = true; 
    899      
    900     bool firstContextAsMainThread = numThreadsIncludingMainThread==contexts.size(); 
    901  
    902     // osg::notify(osg::NOTICE)<<"numThreadsIncludingMainThread=="<<numThreadsIncludingMainThread<<std::endl; 
    903  
    904     _numThreadsOnBarrier = numThreadsIncludingMainThread; 
    905      
    906  
     939    bool affinity = false;//true; 
     940     
    907941    Contexts::iterator citr; 
    908942 
     
    935969    if (_threadingModel==ThreadPerContext) 
    936970    { 
    937         _startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); 
    938  
    939     #if 1 
    940         _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); 
    941     #else     
    942         _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::GL_FINISH); 
    943     #endif 
     971        _startRenderingBarrier = 0; 
     972        _endRenderingDispatchBarrier = 0; 
    944973        _endDynamicDrawBlock = 0; 
    945974    } 
     
    950979        _endDynamicDrawBlock = new EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation); 
    951980    } 
     981     
     982    if (_numThreadsOnBarrier>1) 
     983    { 
     984        _startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); 
     985        _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); 
     986    } 
     987 
     988 
     989    osg::ref_ptr<osg::BarrierOperation> swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION); 
    952990 
    953991    osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation(); 
    954992 
    955     citr = contexts.begin();  
    956     unsigned int processNum = 0; 
    957  
    958     if (firstContextAsMainThread) 
    959     { 
    960         ++processNum; 
    961         ++citr; 
    962     } 
    963  
    964     for(; 
     993    unsigned int processNum = 1; 
     994    for(citr = contexts.begin(); 
    965995        citr != contexts.end(); 
    966         ++citr, 
    967         ++processNum) 
     996        ++citr, ++processNum) 
    968997    { 
    969998        osg::GraphicsContext* gc = (*citr); 
     
    9741003        gc->createGraphicsThread(); 
    9751004 
     1005#if 1 
    9761006        if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); 
     1007#else 
     1008        if (affinity) gc->getGraphicsThread()->setProcessorAffinity(1); 
     1009#endif 
    9771010 
    9781011        gc->getGraphicsThread()->add(new ViewerCompileOperation(getSceneData())); 
    9791012 
    9801013        // add the startRenderingBarrier 
    981         if (_startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); 
     1014        if (_threadingModel==ThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); 
    9821015 
    9831016        // add the rendering operation itself. 
    9841017        gc->getGraphicsThread()->add(new ViewerRunOperations()); 
    9851018 
    986         if (_endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) 
     1019        if (_threadingModel==ThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) 
    9871020        { 
    9881021            // add the endRenderingDispatchBarrier 
     
    9901023        } 
    9911024 
     1025        if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get()); 
     1026 
    9921027        // add the swap buffers 
    9931028        gc->getGraphicsThread()->add(swapOp.get()); 
    9941029 
    995         if (_endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) 
     1030        if (_threadingModel==ThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) 
    9961031        { 
    9971032            // add the endRenderingDispatchBarrier 
     
    9991034        } 
    10001035 
    1001     } 
    1002  
    1003     if (firstContextAsMainThread) 
    1004     { 
    1005         if (affinity) OpenThreads::SetProcessorAffinityOfCurrentThread(0); 
    1006     } 
     1036 
     1037 
     1038    } 
     1039 
     1040     
     1041    if (_threadingModel==ThreadPerCamera && _numThreadsOnBarrier>1) 
     1042    { 
     1043        Cameras::iterator camItr = cameras.begin(); 
     1044        if (_useMainThreadForRenderingTraversal) ++camItr; 
     1045 
     1046        for(; 
     1047            camItr != cameras.end(); 
     1048            ++camItr, ++processNum) 
     1049        { 
     1050            osg::Camera* camera = *camItr; 
     1051            camera->createCameraThread(); 
     1052 
     1053#if 0 
     1054            if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors); 
     1055#else 
     1056            if (affinity) camera->getCameraThread()->setProcessorAffinity(1); 
     1057#endif             
     1058            osg::GraphicsContext* gc = camera->getGraphicsContext(); 
     1059 
     1060            // add the startRenderingBarrier 
     1061            if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get()); 
     1062 
     1063            OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) ); 
     1064            osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue(); 
     1065            for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin(); 
     1066                oitr != operations.end(); 
     1067                ++oitr) 
     1068            { 
     1069                ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get()); 
     1070                if (vdbro && vdbro->getCamera()==camera) 
     1071                { 
     1072                    camera->getCameraThread()->add(vdbro); 
     1073                } 
     1074            } 
     1075             
     1076            if (_endRenderingDispatchBarrier.valid()) 
     1077            { 
     1078                // add the endRenderingDispatchBarrier 
     1079                gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); 
     1080            } 
     1081 
     1082        } 
     1083 
     1084        for(camItr = cameras.begin(); 
     1085            camItr != cameras.end(); 
     1086            ++camItr, ++processNum) 
     1087        { 
     1088            osg::Camera* camera = *camItr; 
     1089            if (camera->getCameraThread() && !camera->getCameraThread()->isRunning()) 
     1090            { 
     1091                osg::notify(osg::INFO)<<"  camera->getCameraThread()-> "<<camera->getCameraThread()<<std::endl; 
     1092                camera->getCameraThread()->startThread(); 
     1093            } 
     1094        } 
     1095    } 
     1096     
     1097    if (affinity) OpenThreads::SetProcessorAffinityOfCurrentThread(0); 
    10071098 
    10081099    for(citr = contexts.begin(); 
     
    10931184    cameras.clear(); 
    10941185     
    1095     if (onlyActive || _camera->getGraphicsContext()) cameras.push_back(_camera.get()); 
     1186    if (!onlyActive || _camera->getGraphicsContext()) cameras.push_back(_camera.get()); 
    10961187 
    10971188    for(Slaves::iterator itr = _slaves.begin(); 
     
    10991190        ++itr) 
    11001191    { 
    1101         if (onlyActive || itr->_camera->getGraphicsContext()) cameras.push_back(itr->_camera.get()); 
    1102     } 
    1103          
     1192        if (!onlyActive || itr->_camera->getGraphicsContext()) cameras.push_back(itr->_camera.get()); 
     1193    } 
     1194         
     1195
     1196 
     1197void Viewer::getAllThreads(Threads& threads, bool onlyActive) 
     1198
     1199    OperationsThreads operationsThreads; 
     1200    getOperationsThreads(operationsThreads); 
     1201     
     1202    for(OperationsThreads::iterator itr = operationsThreads.begin(); 
     1203        itr != operationsThreads.end(); 
     1204        ++itr) 
     1205    { 
     1206        threads.push_back(*itr); 
     1207    } 
     1208     
     1209    if (_scene.valid() &&  
     1210        _scene->getDatabasePager() && 
     1211       (!onlyActive || _scene->getDatabasePager()->isRunning()))  
     1212    { 
     1213        threads.push_back(_scene->getDatabasePager()); 
     1214    } 
     1215
     1216 
     1217 
     1218void Viewer::getOperationsThreads(OperationsThreads& threads, bool onlyActive) 
     1219
     1220    threads.clear(); 
     1221     
     1222    Contexts contexts; 
     1223    getContexts(contexts); 
     1224    for(Contexts::iterator gcitr = contexts.begin(); 
     1225        gcitr != contexts.end(); 
     1226        ++gcitr) 
     1227    { 
     1228        osg::GraphicsContext* gc = *gcitr; 
     1229        if (gc->getGraphicsThread() &&  
     1230            (!onlyActive || gc->getGraphicsThread()->isRunning()) ) 
     1231        { 
     1232            threads.push_back(gc->getGraphicsThread()); 
     1233        } 
     1234    } 
     1235     
     1236    Cameras cameras; 
     1237    getCameras(cameras); 
     1238    for(Cameras::iterator citr = cameras.begin(); 
     1239        citr != cameras.end(); 
     1240        ++citr) 
     1241    { 
     1242        osg::Camera* camera = *citr; 
     1243        if (camera->getCameraThread() &&  
     1244            (!onlyActive || camera->getCameraThread()->isRunning()) ) 
     1245        { 
     1246            threads.push_back(camera->getCameraThread()); 
     1247        } 
     1248    } 
     1249     
    11041250} 
    11051251 
     
    17411887            if (vdbro) 
    17421888            { 
    1743                 if (!vdbro->getGraphicsThreadDoesCull()
     1889                if (!vdbro->getGraphicsThreadDoesCull() && !(vdbro->getCamera()->getCameraThread())
    17441890                { 
    17451891                    vdbro->cull(); 
     
    17471893            } 
    17481894        } 
    1749  
    17501895    } 
    17511896 
     
    17571902        if (!((*itr)->getGraphicsThread())) 
    17581903        {  
    1759             (*itr)->makeCurrent(); 
     1904            makeCurrent(*itr); 
    17601905            (*itr)->runOperations(); 
    1761             (*itr)->releaseContext(); 
    17621906        } 
    17631907    } 
    17641908 
    17651909    // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl; 
     1910 
     1911    // wait till the rendering dispatch is done. 
     1912    if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block(); 
     1913 
     1914    for(itr = contexts.begin(); 
     1915        itr != contexts.end(); 
     1916        ++itr) 
     1917    { 
     1918        if (_done) return; 
     1919 
     1920        if (!((*itr)->getGraphicsThread())) 
     1921        {  
     1922            makeCurrent(*itr); 
     1923            (*itr)->swapBuffers(); 
     1924        } 
     1925    } 
     1926 
     1927    if (dp) 
     1928    { 
     1929        dp->signalEndFrame(); 
     1930    } 
    17661931 
    17671932    // wait till the dynamic draw is complete. 
     
    17731938    } 
    17741939 
    1775     // wait till the rendering dispatch is done. 
    1776     if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block(); 
    1777  
    1778     for(itr = contexts.begin(); 
    1779         itr != contexts.end(); 
    1780         ++itr) 
    1781     { 
    1782         if (_done) return; 
    1783  
    1784         if (!((*itr)->getGraphicsThread())) 
    1785         {  
    1786             (*itr)->makeCurrent(); 
    1787             (*itr)->swapBuffers(); 
    1788             (*itr)->releaseContext(); 
    1789         } 
    1790     } 
    1791  
    1792     if (dp) 
    1793     { 
    1794         dp->signalEndFrame(); 
    1795     } 
    17961940 
    17971941    if (getStats() && getStats()->collectStats("update"))