root/OpenSceneGraph/trunk/src/osgViewer/ViewerBase.cpp @ 9868

Revision 9868, 27.2 kB (checked in by robert, 5 years ago)

Preliminary work on general purpose incremental compile support in osgViewer.

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <stdlib.h>
15#include <string.h>
16
17#include <osgViewer/ViewerBase>
18#include <osgViewer/View>
19#include <osgViewer/Renderer>
20
21#include <osg/io_utils>
22
23#include <osg/TextureCubeMap>
24#include <osg/TextureRectangle>
25#include <osg/TexMat>
26#include <osg/DeleteHandler>
27
28#include <osgUtil/Optimizer>
29#include <osgUtil/IntersectionVisitor>
30#include <osgUtil/Statistics>
31
32static osg::ApplicationUsageProxy ViewerBase_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_CONFIG_FILE <filename>","Specify a viewer configuration file to load by default.");
33static osg::ApplicationUsageProxy ViewerBase_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREADING <value>","Set the threading model using by Viewer, <value> can be SingleThreaded, CullDrawThreadPerContext, DrawThreadPerContext or CullThreadPerCameraDrawThreadPerContext.");
34static osg::ApplicationUsageProxy ViewerBase_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN <value>","Set the default screen that windows should open up on.");
35static osg::ApplicationUsageProxy ViewerBase_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x y width height","Set the default window dimensions that windows should open up on.");
36
37
38using namespace osgViewer;
39
40ViewerBase::ViewerBase():
41    osg::Object(true)
42{
43    _firstFrame = true;
44    _done = false;
45    _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape;
46    _quitEventSetsDone = true;
47    _releaseContextAtEndOfFrameHint = true;
48    _threadingModel = AutomaticSelection;
49    _threadsRunning = false;
50    _endBarrierPosition = AfterSwapBuffers;
51}
52
53ViewerBase::ViewerBase(const ViewerBase& base):
54    osg::Object(true)
55{
56    _firstFrame = true;
57    _done = false;
58    _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape;
59    _quitEventSetsDone = true;
60    _releaseContextAtEndOfFrameHint = true;
61    _threadingModel = AutomaticSelection;
62    _threadsRunning = false;
63    _endBarrierPosition = AfterSwapBuffers;
64}
65
66void ViewerBase::setThreadingModel(ThreadingModel threadingModel)
67{
68    if (_threadingModel == threadingModel) return;
69   
70    if (_threadsRunning) stopThreading();
71   
72    _threadingModel = threadingModel;
73
74    if (isRealized() && _threadingModel!=SingleThreaded) startThreading();
75}
76
77ViewerBase::ThreadingModel ViewerBase::suggestBestThreadingModel()
78{
79    const char* str = getenv("OSG_THREADING");
80    if (str)
81    {
82        if (strcmp(str,"SingleThreaded")==0) return SingleThreaded;
83        else if (strcmp(str,"CullDrawThreadPerContext")==0) return CullDrawThreadPerContext;
84        else if (strcmp(str,"DrawThreadPerContext")==0) return DrawThreadPerContext;
85        else if (strcmp(str,"CullThreadPerCameraDrawThreadPerContext")==0) return CullThreadPerCameraDrawThreadPerContext;
86    }
87
88    Contexts contexts;
89    getContexts(contexts);
90   
91    if (contexts.empty()) return SingleThreaded;
92
93#if 0
94    // temporary hack to disable multi-threading under Windows till we find good solutions for
95    // crashes that users are seeing.
96    return SingleThreaded;
97#endif
98
99    Cameras cameras;
100    getCameras(cameras);
101
102    if (cameras.empty()) return SingleThreaded;
103
104
105    int numProcessors = OpenThreads::GetNumberOfProcessors();
106
107    if (contexts.size()==1)
108    {
109        if (numProcessors==1) return SingleThreaded;
110        else return DrawThreadPerContext;
111    }
112   
113#if 1
114    if (numProcessors >= static_cast<int>(cameras.size()+contexts.size()))
115    {
116        return CullThreadPerCameraDrawThreadPerContext;
117    }
118#endif
119
120    return DrawThreadPerContext;
121}
122
123void ViewerBase::setUpThreading()
124{
125    Contexts contexts;
126    getContexts(contexts);
127
128    if (_threadingModel==SingleThreaded)
129    {
130        if (_threadsRunning) stopThreading();
131        else
132        {
133            // we'll set processor affinity here to help single threaded apps
134            // with multiple processor cores, and using the database pager.
135            int numProcessors = OpenThreads::GetNumberOfProcessors();
136            bool affinity = numProcessors>1;   
137            if (affinity)
138            {
139                OpenThreads::SetProcessorAffinityOfCurrentThread(0);
140
141                Scenes scenes;
142                getScenes(scenes);
143               
144                for(Scenes::iterator itr = scenes.begin();
145                    itr != scenes.end();
146                    ++itr)
147                {
148                    Scene* scene = *itr;
149                    osgDB::DatabasePager* dp = scene->getDatabasePager();
150                    if (dp)
151                    {
152                        for(unsigned int i=0; i<dp->getNumDatabaseThreads(); ++i)
153                        {
154                            osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i);
155                            dt->setProcessorAffinity(1);
156                        }
157                    }
158                }
159           
160            }
161        }
162    }
163    else
164    {
165        if (!_threadsRunning) startThreading();
166    }
167   
168}
169
170void ViewerBase::setEndBarrierPosition(BarrierPosition bp)
171{
172    if (_endBarrierPosition == bp) return;
173   
174    if (_threadsRunning) stopThreading();
175   
176    _endBarrierPosition = bp;
177
178    if (_threadingModel!=SingleThreaded) startThreading();
179}
180
181
182void ViewerBase::stopThreading()
183{
184    if (!_threadsRunning) return;
185
186    osg::notify(osg::INFO)<<"ViewerBase::stopThreading() - stopping threading"<<std::endl;
187
188    Contexts contexts;
189    getContexts(contexts);
190
191    Cameras cameras;
192    getCameras(cameras);
193
194    Contexts::iterator gcitr;
195    Cameras::iterator citr;
196
197    for(Cameras::iterator camItr = cameras.begin();
198        camItr != cameras.end();
199        ++camItr)
200    {
201        osg::Camera* camera = *camItr;
202        Renderer* renderer = dynamic_cast<Renderer*>(camera->getRenderer());
203        if (renderer) renderer->release();
204    }
205
206    // delete all the graphics threads.   
207    for(gcitr = contexts.begin();
208        gcitr != contexts.end();
209        ++gcitr)
210    {
211        (*gcitr)->setGraphicsThread(0);
212    }
213
214    // delete all the camera threads.   
215    for(citr = cameras.begin();
216        citr != cameras.end();
217        ++citr)
218    {
219        (*citr)->setCameraThread(0);
220    }
221
222    for(Cameras::iterator camItr = cameras.begin();
223        camItr != cameras.end();
224        ++camItr)
225    {
226        osg::Camera* camera = *camItr;
227        Renderer* renderer = dynamic_cast<Renderer*>(camera->getRenderer());
228        if (renderer)
229        {
230            renderer->setGraphicsThreadDoesCull( true );
231            renderer->setDone(false);
232        }
233    }
234
235
236    _threadsRunning = false;
237    _startRenderingBarrier = 0;
238    _endRenderingDispatchBarrier = 0;
239    _endDynamicDrawBlock = 0;
240
241    osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading."<<std::endl;
242}
243
244void ViewerBase::startThreading()
245{
246    if (_threadsRunning) return;
247   
248    osg::notify(osg::INFO)<<"Viewer::startThreading() - starting threading"<<std::endl;
249   
250    // release any context held by the main thread.
251    releaseContext();
252
253    _threadingModel = _threadingModel==AutomaticSelection ? suggestBestThreadingModel() : _threadingModel;
254
255    Contexts contexts;
256    getContexts(contexts);
257   
258    osg::notify(osg::INFO)<<"Viewer::startThreading() - contexts.size()="<<contexts.size()<<std::endl;
259
260    Cameras cameras;
261    getCameras(cameras);
262   
263    unsigned int numThreadsOnStartBarrier = 0;
264    unsigned int numThreadsOnEndBarrier = 0;
265    switch(_threadingModel)
266    {
267        case(SingleThreaded):
268            numThreadsOnStartBarrier = 1;
269            numThreadsOnEndBarrier = 1;
270            return;
271        case(CullDrawThreadPerContext):
272            numThreadsOnStartBarrier = contexts.size()+1;
273            numThreadsOnEndBarrier = contexts.size()+1;
274            break;
275        case(DrawThreadPerContext):
276            numThreadsOnStartBarrier = 1;
277            numThreadsOnEndBarrier = 1;
278            break;
279        case(CullThreadPerCameraDrawThreadPerContext):
280            numThreadsOnStartBarrier = cameras.size()+1;
281            numThreadsOnEndBarrier = 1;
282            break;
283        default:
284            osg::notify(osg::NOTICE)<<"Error: Threading model not selected"<<std::endl;
285            return;
286    }
287
288    // using multi-threading so make sure that new objects are allocated with thread safe ref/unref
289    osg::Referenced::setThreadSafeReferenceCounting(true);
290
291    Scenes scenes;
292    getScenes(scenes);
293    for(Scenes::iterator scitr = scenes.begin();
294        scitr != scenes.end();
295        ++scitr)
296    {
297        if ((*scitr)->getSceneData())
298        {
299            osg::notify(osg::INFO)<<"Making scene thread safe"<<std::endl;
300
301            // make sure that existing scene graph objects are allocated with thread safe ref/unref
302            (*scitr)->getSceneData()->setThreadSafeRefUnref(true);
303
304            // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
305            (*scitr)->getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
306        }
307    }
308       
309    int numProcessors = OpenThreads::GetNumberOfProcessors();
310    bool affinity = numProcessors>1;   
311   
312    Contexts::iterator citr;
313
314    unsigned int numViewerDoubleBufferedRenderingOperation = 0;
315
316    bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext || _threadingModel==SingleThreaded;
317
318    for(Cameras::iterator camItr = cameras.begin();
319        camItr != cameras.end();
320        ++camItr)
321    {
322        osg::Camera* camera = *camItr;
323        Renderer* renderer = dynamic_cast<Renderer*>(camera->getRenderer());
324        if (renderer)
325        {
326            renderer->setGraphicsThreadDoesCull(graphicsThreadsDoesCull);
327            renderer->setDone(false);
328            ++numViewerDoubleBufferedRenderingOperation;
329        }
330    }
331
332    if (_threadingModel==CullDrawThreadPerContext)
333    {
334        _startRenderingBarrier = 0;
335        _endRenderingDispatchBarrier = 0;
336        _endDynamicDrawBlock = 0;
337    }
338    else if (_threadingModel==DrawThreadPerContext ||
339             _threadingModel==CullThreadPerCameraDrawThreadPerContext)
340    {
341        _startRenderingBarrier = 0;
342        _endRenderingDispatchBarrier = 0;
343        _endDynamicDrawBlock = new osg::EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation);
344       
345#ifndef OSGUTIL_RENDERBACKEND_USE_REF_PTR
346        if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2));
347        else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2);
348#endif
349    }
350   
351    if (numThreadsOnStartBarrier>1)
352    {
353        _startRenderingBarrier = new osg::BarrierOperation(numThreadsOnStartBarrier, osg::BarrierOperation::NO_OPERATION);
354    }
355
356    if (numThreadsOnEndBarrier>1)
357    {
358        _endRenderingDispatchBarrier = new osg::BarrierOperation(numThreadsOnEndBarrier, osg::BarrierOperation::NO_OPERATION);
359    }
360
361
362    osg::ref_ptr<osg::BarrierOperation> swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION);
363
364    osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
365
366    typedef std::map<OpenThreads::Thread*, int> ThreadAffinityMap;
367    ThreadAffinityMap threadAffinityMap;
368
369    unsigned int processNum = 1;
370    for(citr = contexts.begin();
371        citr != contexts.end();
372        ++citr, ++processNum)
373    {
374        osg::GraphicsContext* gc = (*citr);
375       
376        if (!gc->isRealized())
377        {
378            osg::notify(osg::INFO)<<"ViewerBase::startThreading() : Realizing window "<<gc<<std::endl;
379            gc->realize();
380        }
381       
382        gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get());
383
384        // create the a graphics thread for this context
385        gc->createGraphicsThread();
386
387        if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
388        threadAffinityMap[gc->getGraphicsThread()] = processNum % numProcessors;
389
390        // add the startRenderingBarrier
391        if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get());
392
393        // add the rendering operation itself.
394        gc->getGraphicsThread()->add(new osg::RunOperations());
395
396        if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid())
397        {
398            // add the endRenderingDispatchBarrier
399            gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
400        }
401
402        if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get());
403
404        // add the swap buffers
405        gc->getGraphicsThread()->add(swapOp.get());
406
407        if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid())
408        {
409            // add the endRenderingDispatchBarrier
410            gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
411        }
412
413    }
414
415    if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && numThreadsOnStartBarrier>1)
416    {
417        Cameras::iterator camItr;
418
419        for(camItr = cameras.begin();
420            camItr != cameras.end();
421            ++camItr, ++processNum)
422        {
423            osg::Camera* camera = *camItr;
424            camera->createCameraThread();
425
426            if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors);
427            threadAffinityMap[camera->getCameraThread()] = processNum % numProcessors;
428
429            osg::GraphicsContext* gc = camera->getGraphicsContext();
430
431            // add the startRenderingBarrier
432            if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get());
433
434            Renderer* renderer = dynamic_cast<Renderer*>(camera->getRenderer());
435            renderer->setGraphicsThreadDoesCull(false);
436            camera->getCameraThread()->add(renderer);
437           
438            if (_endRenderingDispatchBarrier.valid())
439            {
440                // add the endRenderingDispatchBarrier
441                gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
442            }
443
444        }
445
446        for(camItr = cameras.begin();
447            camItr != cameras.end();
448            ++camItr)
449        {
450            osg::Camera* camera = *camItr;
451            if (camera->getCameraThread() && !camera->getCameraThread()->isRunning())
452            {
453                osg::notify(osg::INFO)<<"  camera->getCameraThread()-> "<<camera->getCameraThread()<<std::endl;
454                camera->getCameraThread()->startThread();
455            }
456        }
457    }
458
459#if 0   
460    if (affinity)
461    {
462        OpenThreads::SetProcessorAffinityOfCurrentThread(0);
463        if (_scene.valid() && _scene->getDatabasePager())
464        {
465#if 0       
466            _scene->getDatabasePager()->setProcessorAffinity(1);
467#else
468            _scene->getDatabasePager()->setProcessorAffinity(0);
469#endif
470        }
471    }
472#endif
473
474#if 0
475    if (affinity)
476    {
477        for(ThreadAffinityMap::iterator titr = threadAffinityMap.begin();
478            titr != threadAffinityMap.end();
479            ++titr)
480        {
481            titr->first->setProcessorAffinity(titr->second);
482        }
483    }
484#endif
485
486
487    for(citr = contexts.begin();
488        citr != contexts.end();
489        ++citr)
490    {
491        osg::GraphicsContext* gc = (*citr);
492        if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning())
493        {
494            osg::notify(osg::INFO)<<"  gc->getGraphicsThread()->startThread() "<<gc->getGraphicsThread()<<std::endl;
495            gc->getGraphicsThread()->startThread();
496            // OpenThreads::Thread::YieldCurrentThread();
497        }
498    }
499
500    _threadsRunning = true;
501
502    osg::notify(osg::INFO)<<"Set up threading"<<std::endl;
503}
504
505void ViewerBase::getWindows(Windows& windows, bool onlyValid)
506{
507    windows.clear();
508
509    Contexts contexts;
510    getContexts(contexts, onlyValid);
511   
512    for(Contexts::iterator itr = contexts.begin();
513        itr != contexts.end();
514        ++itr)
515    {
516        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*itr);
517        if (gw) windows.push_back(gw);
518    }
519}
520
521void ViewerBase::checkWindowStatus()
522{
523    Contexts contexts;
524    getContexts(contexts);
525   
526    // osg::notify(osg::NOTICE)<<"Viewer::checkWindowStatus() - "<<contexts.size()<<std::endl;
527   
528    if (contexts.size()==0)
529    {
530        _done = true;
531        if (areThreadsRunning()) stopThreading();
532    }
533}
534
535void ViewerBase::addUpdateOperation(osg::Operation* operation)
536{
537    if (!operation) return;
538
539    if (!_updateOperations) _updateOperations = new osg::OperationQueue;
540   
541    _updateOperations->add(operation);
542}
543
544void ViewerBase::removeUpdateOperation(osg::Operation* operation)
545{
546    if (!operation) return;
547
548    if (_updateOperations.valid())
549    {
550        _updateOperations->remove(operation);
551    }
552}
553
554void ViewerBase::setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico)
555{
556    if (_incrementalCompileOperation == ico) return;
557   
558    Contexts contexts;
559    getContexts(contexts, false);
560   
561    if (_incrementalCompileOperation.valid()) _incrementalCompileOperation->removeContexts(contexts);
562
563    // assign new operation       
564    _incrementalCompileOperation = ico;
565
566    if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
567}
568
569int ViewerBase::run()
570{
571    if (!isRealized())
572    {
573        realize();
574    }
575
576#if 0
577    while (!done())
578    {
579        frame();
580    }
581#else
582
583    const char* str = getenv("OSG_RUN_FRAME_COUNT");
584    if (str)
585    {
586        int runTillFrameNumber = atoi(str);
587        while (!done() && getViewerFrameStamp()->getFrameNumber()<runTillFrameNumber)
588        {
589            frame();
590        }
591    }
592    else
593    {
594        while (!done())
595        {
596            frame();
597        }
598    }
599#endif   
600    return 0;
601}
602
603void ViewerBase::frame(double simulationTime)
604{
605    if (_done) return;
606
607    // osg::notify(osg::NOTICE)<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl;
608
609    if (_firstFrame)
610    {
611        viewerInit();
612       
613        if (!isRealized())
614        {
615            realize();
616        }
617       
618        _firstFrame = false;
619    }
620    advance(simulationTime);
621   
622    eventTraversal();
623    updateTraversal();
624    renderingTraversals();
625}
626
627
628void ViewerBase::renderingTraversals()
629{
630    bool _outputMasterCameraLocation = false;
631    if (_outputMasterCameraLocation)
632    {
633        Views views;
634        getViews(views);
635
636        for(Views::iterator itr = views.begin();
637            itr != views.end();
638            ++itr)
639        {
640            osgViewer::View* view = *itr;
641            if (view)
642            {
643                const osg::Matrixd& m = view->getCamera()->getInverseViewMatrix();
644                osg::notify(osg::NOTICE)<<"View "<<view<<", Master Camera position("<<m.getTrans()<<"), rotation("<<m.getRotate()<<")"<<std::endl;
645            }
646        }
647    }
648       
649    // check to see if windows are still valid
650    checkWindowStatus();
651
652    if (_done) return;
653
654    double beginRenderingTraversals = elapsedTime();
655
656    osg::FrameStamp* frameStamp = getViewerFrameStamp();
657
658    if (getViewerStats() && getViewerStats()->collectStats("scene"))
659    {
660        int frameNumber = frameStamp ? frameStamp->getFrameNumber() : 0;
661   
662        Views views;
663        getViews(views);
664        for(Views::iterator vitr = views.begin();
665            vitr != views.end();
666            ++vitr)
667        {
668            View* view = *vitr;
669            osg::Stats* stats = view->getStats();           
670            osg::Node* sceneRoot = view->getSceneData();
671            if (sceneRoot && stats)
672            {
673                osgUtil::StatsVisitor statsVisitor;
674                sceneRoot->accept(statsVisitor);
675                statsVisitor.totalUpStats();
676               
677                unsigned int unique_primitives = 0;
678                osgUtil::Statistics::PrimitiveCountMap::iterator pcmitr;
679                for(pcmitr = statsVisitor._uniqueStats.GetPrimitivesBegin();
680                    pcmitr != statsVisitor._uniqueStats.GetPrimitivesEnd();
681                    ++pcmitr)
682                {
683                    unique_primitives += pcmitr->second;
684                }
685
686                stats->setAttribute(frameNumber, "Number of unique StateSet", static_cast<double>(statsVisitor._statesetSet.size()));
687                stats->setAttribute(frameNumber, "Number of unique Group", static_cast<double>(statsVisitor._groupSet.size()));
688                stats->setAttribute(frameNumber, "Number of unique Transform", static_cast<double>(statsVisitor._transformSet.size()));
689                stats->setAttribute(frameNumber, "Number of unique LOD", static_cast<double>(statsVisitor._lodSet.size()));
690                stats->setAttribute(frameNumber, "Number of unique Switch", static_cast<double>(statsVisitor._switchSet.size()));
691                stats->setAttribute(frameNumber, "Number of unique Geode", static_cast<double>(statsVisitor._geodeSet.size()));
692                stats->setAttribute(frameNumber, "Number of unique Drawable", static_cast<double>(statsVisitor._drawableSet.size()));
693                stats->setAttribute(frameNumber, "Number of unique Geometry", static_cast<double>(statsVisitor._geometrySet.size()));
694                stats->setAttribute(frameNumber, "Number of unique Vertices", static_cast<double>(statsVisitor._uniqueStats._vertexCount));
695                stats->setAttribute(frameNumber, "Number of unique Primitives", static_cast<double>(unique_primitives));
696
697                unsigned int instanced_primitives = 0;
698                for(pcmitr = statsVisitor._instancedStats.GetPrimitivesBegin();
699                    pcmitr != statsVisitor._instancedStats.GetPrimitivesEnd();
700                    ++pcmitr)
701                {
702                    instanced_primitives += pcmitr->second;
703                }
704
705                stats->setAttribute(frameNumber, "Number of instanced Stateset", static_cast<double>(statsVisitor._numInstancedStateSet));
706                stats->setAttribute(frameNumber, "Number of instanced Group", static_cast<double>(statsVisitor._numInstancedGroup));
707                stats->setAttribute(frameNumber, "Number of instanced Transform", static_cast<double>(statsVisitor._numInstancedTransform));
708                stats->setAttribute(frameNumber, "Number of instanced LOD", static_cast<double>(statsVisitor._numInstancedLOD));
709                stats->setAttribute(frameNumber, "Number of instanced Switch", static_cast<double>(statsVisitor._numInstancedSwitch));
710                stats->setAttribute(frameNumber, "Number of instanced Geode", static_cast<double>(statsVisitor._numInstancedGeode));
711                stats->setAttribute(frameNumber, "Number of instanced Drawable", static_cast<double>(statsVisitor._numInstancedDrawable));
712                stats->setAttribute(frameNumber, "Number of instanced Geometry", static_cast<double>(statsVisitor._numInstancedGeometry));
713                stats->setAttribute(frameNumber, "Number of instanced Vertices", static_cast<double>(statsVisitor._instancedStats._vertexCount));
714                stats->setAttribute(frameNumber, "Number of instanced Primitives", static_cast<double>(instanced_primitives));
715           }
716        }
717    }
718
719    Scenes scenes;
720    getScenes(scenes);
721   
722    for(Scenes::iterator sitr = scenes.begin();
723        sitr != scenes.end();
724        ++sitr)
725    {
726        Scene* scene = *sitr;
727        osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0;
728        if (dp)
729        {
730            dp->signalBeginFrame(frameStamp);
731        }
732       
733        if (scene->getSceneData())
734        {
735            // fire off a build of the bounding volumes while we
736            // are still running single threaded.
737            scene->getSceneData()->getBound();
738        }
739    }
740
741    // osg::notify(osg::NOTICE)<<std::endl<<"Start frame"<<std::endl;
742   
743
744    Contexts contexts;
745    getContexts(contexts);
746
747    Cameras cameras;
748    getCameras(cameras);
749   
750    Contexts::iterator itr;
751   
752    bool doneMakeCurrentInThisThread = false;
753
754    if (_endDynamicDrawBlock.valid())
755    {
756        _endDynamicDrawBlock->reset();
757    }
758   
759    // dispatch the rendering threads
760    if (_startRenderingBarrier.valid()) _startRenderingBarrier->block();
761
762    // reset any double buffer graphics objects
763    for(Cameras::iterator camItr = cameras.begin();
764        camItr != cameras.end();
765        ++camItr)
766    {
767        osg::Camera* camera = *camItr;
768        Renderer* renderer = dynamic_cast<Renderer*>(camera->getRenderer());
769        if (renderer)
770        {
771            if (!renderer->getGraphicsThreadDoesCull() && !(camera->getCameraThread()))
772            {
773                renderer->cull();
774            }
775        }
776    }
777
778    for(itr = contexts.begin();
779        itr != contexts.end();
780        ++itr)
781    {
782        if (_done) return;
783        if (!((*itr)->getGraphicsThread()) && (*itr)->valid())
784        {
785            doneMakeCurrentInThisThread = true;
786            makeCurrent(*itr);
787            (*itr)->runOperations();
788        }
789    }
790
791    // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block "<<_endRenderingDispatchBarrier.get()<<std::endl;
792
793    // wait till the rendering dispatch is done.
794    if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block();
795
796    for(itr = contexts.begin();
797        itr != contexts.end();
798        ++itr)
799    {
800        if (_done) return;
801
802        if (!((*itr)->getGraphicsThread()) && (*itr)->valid())
803        {
804            doneMakeCurrentInThisThread = true;
805            makeCurrent(*itr);
806            (*itr)->swapBuffers();
807        }
808    }
809
810    for(Scenes::iterator sitr = scenes.begin();
811        sitr != scenes.end();
812        ++sitr)
813    {
814        Scene* scene = *sitr;
815        osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0;
816        if (dp)
817        {
818            dp->signalEndFrame();
819        }
820    }
821
822    // wait till the dynamic draw is complete.
823    if (_endDynamicDrawBlock.valid())
824    {
825        // osg::Timer_t startTick = osg::Timer::instance()->tick();
826        _endDynamicDrawBlock->block();
827        // osg::notify(osg::NOTICE)<<"Time waiting "<<osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick())<<std::endl;;
828    }
829   
830    if (_releaseContextAtEndOfFrameHint && doneMakeCurrentInThisThread)
831    {
832        //osg::notify(osg::NOTICE)<<"Doing release context"<<std::endl;
833        releaseContext();
834    }
835
836    if (getViewerStats() && getViewerStats()->collectStats("update"))
837    {
838        double endRenderingTraversals = elapsedTime();
839
840        // update current frames stats
841        getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals);
842        getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals);
843        getViewerStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals);
844    }
845}
Note: See TracBrowser for help on using the browser.