root/OpenSceneGraph/trunk/src/osgViewer/Renderer.cpp @ 13041

Revision 13041, 32.0 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
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 <stdio.h>
15
16#include <osg/GLExtensions>
17
18#include <osgUtil/Optimizer>
19#include <osgUtil/GLObjectsVisitor>
20#include <osgUtil/Statistics>
21
22#include <osgViewer/Renderer>
23#include <osgViewer/View>
24
25#include <osgDB/DatabasePager>
26#include <osgDB/ImagePager>
27
28#include <osg/io_utils>
29
30#include <sstream>
31
32using namespace osgViewer;
33
34//#define DEBUG_MESSAGE OSG_NOTICE
35#define DEBUG_MESSAGE OSG_DEBUG
36
37
38OpenGLQuerySupport::OpenGLQuerySupport():
39    _extensions(0)
40{
41}
42
43class OSGVIEWER_EXPORT EXTQuerySupport : public OpenGLQuerySupport
44{
45 public:
46    EXTQuerySupport();
47    void checkQuery(osg::Stats* stats, osg::State* state, osg::Timer_t startTick);
48    virtual void beginQuery(unsigned int frameNumber, osg::State* state);
49    virtual void endQuery(osg::State* state);
50    virtual void initialize(osg::State* state, osg::Timer_t startTick);
51 protected:
52    GLuint createQueryObject();
53    typedef std::pair<GLuint, unsigned int> QueryFrameNumberPair;
54    typedef std::list<QueryFrameNumberPair> QueryFrameNumberList;
55    typedef std::vector<GLuint> QueryList;
56
57    QueryFrameNumberList                        _queryFrameNumberList;
58    QueryList                                   _availableQueryObjects;
59    double                                      _previousQueryTime;
60};
61
62
63EXTQuerySupport::EXTQuerySupport():
64    _previousQueryTime(0.0)
65{
66}
67
68void EXTQuerySupport::checkQuery(osg::Stats* stats, osg::State* state,
69                                 osg::Timer_t startTick)
70{
71    for(QueryFrameNumberList::iterator itr = _queryFrameNumberList.begin();
72        itr != _queryFrameNumberList.end();
73        )
74    {
75        GLuint query = itr->first;
76        GLint available = 0;
77        _extensions->glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &available);
78        if (available)
79        {
80            GLuint64EXT timeElapsed = 0;
81            _extensions->glGetQueryObjectui64v(query, GL_QUERY_RESULT, &timeElapsed);
82
83            double timeElapsedSeconds = double(timeElapsed)*1e-9;
84            double currentTime = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
85            double estimatedEndTime = (_previousQueryTime + currentTime) * 0.5;
86            double estimatedBeginTime = estimatedEndTime - timeElapsedSeconds;
87
88            stats->setAttribute(itr->second, "GPU draw begin time", estimatedBeginTime);
89            stats->setAttribute(itr->second, "GPU draw end time", estimatedEndTime);
90            stats->setAttribute(itr->second, "GPU draw time taken", timeElapsedSeconds);
91
92
93            itr = _queryFrameNumberList.erase(itr);
94            _availableQueryObjects.push_back(query);
95        }
96        else
97        {
98            ++itr;
99        }
100
101    }
102    _previousQueryTime = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
103}
104
105GLuint EXTQuerySupport::createQueryObject()
106{
107    if (_availableQueryObjects.empty())
108    {
109        GLuint query;
110        _extensions->glGenQueries(1, &query);
111        return query;
112    }
113    else
114    {
115        GLuint query = _availableQueryObjects.back();
116        _availableQueryObjects.pop_back();
117        return query;
118    }
119}
120
121void EXTQuerySupport::beginQuery(unsigned int frameNumber, osg::State* state)
122{
123    GLuint query = createQueryObject();
124    _extensions->glBeginQuery(GL_TIME_ELAPSED, query);
125    _queryFrameNumberList.push_back(QueryFrameNumberPair(query, frameNumber));
126}
127
128void EXTQuerySupport::endQuery(osg::State* state)
129{
130    _extensions->glEndQuery(GL_TIME_ELAPSED);
131}
132
133void OpenGLQuerySupport::initialize(osg::State* state, osg::Timer_t startTick)
134{
135    _extensions = osg::Drawable::getExtensions(state->getContextID(),true);
136}
137
138void EXTQuerySupport::initialize(osg::State* state, osg::Timer_t startTick)
139{
140    OpenGLQuerySupport::initialize(state, startTick);
141    _previousQueryTime = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
142
143}
144
145class ARBQuerySupport : public OpenGLQuerySupport
146{
147public:
148    virtual void checkQuery(osg::Stats* stats, osg::State* state,
149                            osg::Timer_t startTick);
150
151    virtual void beginQuery(unsigned int frameNumber, osg::State* state);
152    virtual void endQuery(osg::State* state);
153    virtual void initialize(osg::State* state, osg::Timer_t startTick);
154protected:
155    typedef std::pair<GLuint, GLuint> QueryPair;
156    struct ActiveQuery {
157        ActiveQuery() : queries(0, 0), frameNumber(0) {}
158        ActiveQuery(GLuint start_, GLuint end_, int frameNumber_)
159            : queries(start_, end_), frameNumber(frameNumber_)
160        {
161        }
162        ActiveQuery(const QueryPair& queries_, unsigned int frameNumber_)
163            : queries(queries_), frameNumber(frameNumber_)
164        {
165        }
166        QueryPair queries;
167        unsigned int frameNumber;
168    };
169    typedef std::list<ActiveQuery> QueryFrameList;
170    typedef std::vector<QueryPair> QueryList;
171    QueryFrameList _queryFrameList;
172    QueryList _availableQueryObjects;
173};
174
175void ARBQuerySupport::initialize(osg::State* state, osg::Timer_t startTick)
176{
177    OpenGLQuerySupport::initialize(state, startTick);
178}
179
180void ARBQuerySupport::beginQuery(unsigned int frameNumber, osg::State* state)
181{
182    QueryPair query;
183    if (_availableQueryObjects.empty())
184    {
185        _extensions->glGenQueries(1, &query.first);
186        _extensions->glGenQueries(1, &query.second);
187    }
188    else
189    {
190        query = _availableQueryObjects.back();
191        _availableQueryObjects.pop_back();
192    }
193    _extensions->glQueryCounter(query.first, GL_TIMESTAMP);
194    _queryFrameList.push_back(ActiveQuery(query, frameNumber));
195}
196
197void ARBQuerySupport::endQuery(osg::State* state)
198{
199    _extensions->glQueryCounter(_queryFrameList.back().queries.second,
200                                GL_TIMESTAMP);
201}
202
203void ARBQuerySupport::checkQuery(osg::Stats* stats, osg::State* state,
204                                 osg::Timer_t startTick)
205{
206    for(QueryFrameList::iterator itr = _queryFrameList.begin();
207        itr != _queryFrameList.end();
208        )
209    {
210        GLint available = 0;
211        // If the end query is available, the begin query must be too.
212        _extensions->glGetQueryObjectiv(itr->queries.second,
213                                        GL_QUERY_RESULT_AVAILABLE, &available);
214        if (available)
215        {
216            QueryPair queries = itr->queries;
217            GLuint64EXT beginTimestamp = 0;
218            GLuint64EXT endTimestamp = 0;
219            _extensions->glGetQueryObjectui64v(queries.first, GL_QUERY_RESULT,
220                                               &beginTimestamp);
221            _extensions->glGetQueryObjectui64v(queries.second, GL_QUERY_RESULT,
222                                               &endTimestamp);
223            GLuint64EXT gpuTimestamp = state->getGpuTimestamp();
224            // Have any of the timestamps wrapped around?
225            int tbits = state->getTimestampBits();
226            if (tbits < 64)
227            {
228                // If the high bits on any of the timestamp bits are
229                // different then the counters may have wrapped.
230                const int hiShift = (tbits - 1);
231                const GLuint64EXT hiMask = 1 << hiShift;
232                const GLuint64EXT sum = (beginTimestamp >> hiShift)
233                    + (endTimestamp >> hiShift) + (gpuTimestamp >> hiShift);
234                if (sum == 1 || sum == 2) {
235                    const GLuint64EXT wrapAdd = 1 << tbits;
236                    // Counter wrapped between begin and end?
237                    if (beginTimestamp > endTimestamp)
238                    {
239                        endTimestamp += wrapAdd;
240                    }
241                    else if (gpuTimestamp < beginTimestamp
242                             && beginTimestamp - gpuTimestamp > (hiMask >> 1))
243                    {
244                        gpuTimestamp += wrapAdd;
245                    }
246                    else if (endTimestamp < gpuTimestamp
247                             && gpuTimestamp - endTimestamp > (hiMask >> 1))
248                    {
249                        beginTimestamp += wrapAdd;
250                        endTimestamp += wrapAdd;
251                    }
252                }
253            }
254            GLuint64EXT timeElapsed = endTimestamp - beginTimestamp;
255            double timeElapsedSeconds = double(timeElapsed)*1e-9;
256            double gpuTick = state->getGpuTime();
257                     double beginTime = 0.0;
258            double endTime = 0.0;
259            if (beginTimestamp > gpuTimestamp)
260                beginTime = gpuTick
261                    + double(beginTimestamp - gpuTimestamp) * 1e-9;
262            else
263                beginTime = gpuTick
264                    - double(gpuTimestamp - beginTimestamp) * 1e-9;
265            if (endTimestamp > gpuTimestamp)
266                endTime = gpuTick
267                    + double(endTimestamp - gpuTimestamp) * 1e-9;
268            else
269                endTime = gpuTick
270                    - double(gpuTimestamp - endTimestamp) * 1e-9;
271            stats->setAttribute(itr->frameNumber, "GPU draw begin time",
272                                beginTime);
273            stats->setAttribute(itr->frameNumber, "GPU draw end time", endTime);
274            stats->setAttribute(itr->frameNumber, "GPU draw time taken",
275                                timeElapsedSeconds);
276            itr = _queryFrameList.erase(itr);
277            _availableQueryObjects.push_back(queries);
278        }
279        else
280        {
281            ++itr;
282        }
283    }
284}
285
286///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
287//
288//
289//  ThreadSafeQueue
290
291Renderer::ThreadSafeQueue::ThreadSafeQueue()
292    : _isReleased(false)
293{
294}
295
296Renderer::ThreadSafeQueue::~ThreadSafeQueue()
297{
298}
299
300void Renderer::ThreadSafeQueue::release()
301{
302    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
303    _isReleased = true;
304    _cond.broadcast();
305}
306
307osgUtil::SceneView* Renderer::ThreadSafeQueue::takeFront()
308{
309    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
310    // Loop in case there are spurious wakeups from the condition wait.
311    while (true)
312    {
313        // If the queue has been released but nothing is enqueued,
314        // just return. This prevents a deadlock when threading is
315        // restarted.
316        if (_isReleased)
317        {
318            if (!_queue.empty())
319            {
320                osgUtil::SceneView* front = _queue.front();
321                _queue.pop_front();
322                if (_queue.empty())
323                    _isReleased = false;
324                return front;
325            }
326            return 0;
327        }
328        _cond.wait(&_mutex);
329    }
330    return 0;                   // Can't happen
331}
332
333void Renderer::ThreadSafeQueue::add(osgUtil::SceneView* sv)
334{
335    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
336    _queue.push_back(sv);
337    _isReleased = true;
338    _cond.broadcast();
339}
340
341static OpenThreads::Mutex s_drawSerializerMutex;
342
343///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
344//
345//
346//  Renderer
347Renderer::Renderer(osg::Camera* camera):
348    osg::GraphicsOperation("Renderer",true),
349    _camera(camera),
350    _done(false),
351    _graphicsThreadDoesCull(true),
352    _compileOnNextDraw(true),
353    _initialized(false),
354    _startTick(0)
355{
356
357    DEBUG_MESSAGE<<"Render::Render() "<<this<<std::endl;
358
359    _sceneView[0] = new osgUtil::SceneView;
360    _sceneView[1] = new osgUtil::SceneView;
361
362    osg::Camera* masterCamera = _camera->getView() ? _camera->getView()->getCamera() : camera;
363
364    osg::StateSet* global_stateset = 0;
365    osg::StateSet* secondary_stateset = 0;
366    if (_camera != masterCamera)
367    {
368        global_stateset = masterCamera->getOrCreateStateSet();
369        secondary_stateset = _camera->getStateSet();
370    }
371    else
372    {
373        global_stateset = _camera->getOrCreateStateSet();
374    }
375
376    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
377    osgViewer::ViewerBase* viewer = view ? view->getViewerBase() : 0;
378    osgUtil::IncrementalCompileOperation* ico = viewer ? viewer->getIncrementalCompileOperation() : 0;
379    bool automaticFlush = (ico==NULL);
380
381    osg::DisplaySettings* ds = _camera->getDisplaySettings() ?  _camera->getDisplaySettings() :
382                               ((view && view->getDisplaySettings()) ?  view->getDisplaySettings() :  osg::DisplaySettings::instance().get());
383
384    unsigned int sceneViewOptions = osgUtil::SceneView::HEADLIGHT;
385    if (view)
386    {
387        switch(view->getLightingMode())
388        {
389            case(osg::View::NO_LIGHT): sceneViewOptions = 0; break;
390            case(osg::View::SKY_LIGHT): sceneViewOptions = osgUtil::SceneView::SKY_LIGHT; break;
391            case(osg::View::HEADLIGHT): sceneViewOptions = osgUtil::SceneView::HEADLIGHT; break;
392        }
393    }
394
395    _sceneView[0]->setAutomaticFlush(automaticFlush);
396    _sceneView[0]->setGlobalStateSet(global_stateset);
397    _sceneView[0]->setSecondaryStateSet(secondary_stateset);
398
399    _sceneView[1]->setAutomaticFlush(automaticFlush);
400    _sceneView[1]->setGlobalStateSet(global_stateset);
401    _sceneView[1]->setSecondaryStateSet(secondary_stateset);
402
403    _sceneView[0]->setDefaults(sceneViewOptions);
404    _sceneView[1]->setDefaults(sceneViewOptions);
405
406    _sceneView[0]->setDisplaySettings(ds);
407    _sceneView[1]->setDisplaySettings(ds);
408
409    _sceneView[0]->setCamera(_camera.get(), false);
410    _sceneView[1]->setCamera(_camera.get(), false);
411
412    {
413        // assign CullVisitor::Identifier so that the double buffering of SceneView doesn't interfer
414        // with code that requires a consistent knowledge and which effective cull traversal to taking place
415        osg::ref_ptr<osgUtil::CullVisitor::Identifier> leftEyeIdentifier = _sceneView[0]->getCullVisitor()->getIdentifier();
416        osg::ref_ptr<osgUtil::CullVisitor::Identifier> rightEyeIdentifier = new osgUtil::CullVisitor::Identifier();
417
418        _sceneView[0]->setCullVisitorLeft(_sceneView[0]->getCullVisitor()->clone());
419        _sceneView[0]->getCullVisitorLeft()->setIdentifier(leftEyeIdentifier.get());
420        _sceneView[0]->setCullVisitorRight(_sceneView[0]->getCullVisitor()->clone());
421        _sceneView[0]->getCullVisitorRight()->setIdentifier(rightEyeIdentifier.get());
422
423        _sceneView[1]->getCullVisitor()->setIdentifier(leftEyeIdentifier.get());
424        _sceneView[1]->setCullVisitorLeft(_sceneView[1]->getCullVisitor()->clone());
425        _sceneView[1]->getCullVisitorLeft()->setIdentifier(leftEyeIdentifier.get());
426        _sceneView[1]->setCullVisitorRight(_sceneView[1]->getCullVisitor()->clone());
427        _sceneView[1]->getCullVisitorRight()->setIdentifier(rightEyeIdentifier.get());
428    }
429
430    // lock the mutex for the current cull SceneView to
431    // prevent the draw traversal from reading from it before the cull traversal has been completed.
432    _availableQueue.add(_sceneView[0].get());
433    _availableQueue.add(_sceneView[1].get());
434
435    DEBUG_MESSAGE<<"_availableQueue.size()="<<_availableQueue._queue.size()<<std::endl;
436}
437
438Renderer::~Renderer()
439{
440    DEBUG_MESSAGE<<"Render::~Render() "<<this<<std::endl;
441}
442
443void Renderer::initialize(osg::State* state)
444{
445    if (!_initialized)
446    {
447        _initialized = true;
448        osg::Drawable::Extensions* ext = osg::Drawable::getExtensions(state->getContextID(), true);
449        if (ext->isARBTimerQuerySupported() && state->getTimestampBits() > 0)
450            _querySupport = new ARBQuerySupport();
451        else if (ext->isTimerQuerySupported())
452            _querySupport = new EXTQuerySupport();
453        if (_querySupport.valid())
454            _querySupport->initialize(state, _startTick);
455    }
456}
457
458void Renderer::setGraphicsThreadDoesCull(bool flag)
459{
460    if (_graphicsThreadDoesCull==flag) return;
461
462    _graphicsThreadDoesCull = flag;
463}
464
465void Renderer::updateSceneView(osgUtil::SceneView* sceneView)
466{
467    osg::Camera* masterCamera = _camera->getView() ? _camera->getView()->getCamera() : _camera.get();
468
469    osg::StateSet* global_stateset = 0;
470    osg::StateSet* secondary_stateset = 0;
471    if (_camera != masterCamera)
472    {
473        global_stateset = masterCamera->getOrCreateStateSet();
474        secondary_stateset = _camera->getStateSet();
475    }
476    else
477    {
478        global_stateset = _camera->getOrCreateStateSet();
479    }
480
481    if (sceneView->getGlobalStateSet()!=global_stateset)
482    {
483        sceneView->setGlobalStateSet(global_stateset);
484    }
485
486    if (sceneView->getSecondaryStateSet()!=secondary_stateset)
487    {
488        sceneView->setSecondaryStateSet(secondary_stateset);
489    }
490
491    osg::GraphicsContext* context = _camera->getGraphicsContext();
492    osg::State* state = context ? context->getState() : 0;
493    if (sceneView->getState()!=state)
494    {
495        sceneView->setState(state);
496    }
497
498    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
499    osgViewer::ViewerBase* viewer = view ? view->getViewerBase() : 0;
500    osgUtil::IncrementalCompileOperation* ico = viewer ? viewer->getIncrementalCompileOperation() : 0;
501    bool automaticFlush = (ico==NULL);
502
503    sceneView->setAutomaticFlush(automaticFlush);
504
505    osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
506    sceneView->getCullVisitor()->setDatabaseRequestHandler(databasePager);
507
508    osgDB::ImagePager* imagePager = view ? view->getImagePager() : 0;
509    sceneView->getCullVisitor()->setImageRequestHandler(imagePager);
510
511    sceneView->setFrameStamp(view ? view->getFrameStamp() : state->getFrameStamp());
512
513    osg::DisplaySettings* ds = _camera->getDisplaySettings() ?  _camera->getDisplaySettings() :
514                               ((view &&view->getDisplaySettings()) ?  view->getDisplaySettings() :  osg::DisplaySettings::instance().get());
515
516    sceneView->setDisplaySettings(ds);
517
518    if (view)
519    {
520        _startTick = view->getStartTick();
521        if (state) state->setStartTick(_startTick);
522    }
523}
524
525void Renderer::compile()
526{
527    DEBUG_MESSAGE<<"Renderer::compile()"<<std::endl;
528
529
530    _compileOnNextDraw = false;
531
532    osgUtil::SceneView* sceneView = _sceneView[0].get();
533    if (!sceneView || _done) return;
534
535    sceneView->getState()->checkGLErrors("Before Renderer::compile");
536
537    if (sceneView->getSceneData())
538    {
539        osgUtil::GLObjectsVisitor glov;
540        glov.setState(sceneView->getState());
541        sceneView->getSceneData()->accept(glov);
542    }
543
544    sceneView->getState()->checkGLErrors("After Renderer::compile");
545}
546
547static void collectSceneViewStats(unsigned int frameNumber, osgUtil::SceneView* sceneView, osg::Stats* stats)
548{
549    osgUtil::Statistics sceneStats;
550    sceneView->getStats(sceneStats);
551
552    stats->setAttribute(frameNumber, "Visible vertex count", static_cast<double>(sceneStats._vertexCount));
553    stats->setAttribute(frameNumber, "Visible number of drawables", static_cast<double>(sceneStats.numDrawables));
554    stats->setAttribute(frameNumber, "Visible number of fast drawables", static_cast<double>(sceneStats.numFastDrawables));
555    stats->setAttribute(frameNumber, "Visible number of lights", static_cast<double>(sceneStats.nlights));
556    stats->setAttribute(frameNumber, "Visible number of render bins", static_cast<double>(sceneStats.nbins));
557    stats->setAttribute(frameNumber, "Visible depth", static_cast<double>(sceneStats.depth));
558    stats->setAttribute(frameNumber, "Number of StateGraphs", static_cast<double>(sceneStats.numStateGraphs));
559    stats->setAttribute(frameNumber, "Visible number of impostors", static_cast<double>(sceneStats.nimpostor));
560    stats->setAttribute(frameNumber, "Number of ordered leaves", static_cast<double>(sceneStats.numOrderedLeaves));
561
562    unsigned int totalNumPrimitiveSets = 0;
563    const osgUtil::Statistics::PrimitiveValueMap& pvm = sceneStats.getPrimitiveValueMap();
564    for(osgUtil::Statistics::PrimitiveValueMap::const_iterator pvm_itr = pvm.begin();
565        pvm_itr != pvm.end();
566        ++pvm_itr)
567    {
568        totalNumPrimitiveSets += pvm_itr->second.first;
569    }
570    stats->setAttribute(frameNumber, "Visible number of PrimitiveSets", static_cast<double>(totalNumPrimitiveSets));
571
572    osgUtil::Statistics::PrimitiveCountMap& pcm = sceneStats.getPrimitiveCountMap();
573    stats->setAttribute(frameNumber, "Visible number of GL_POINTS", static_cast<double>(pcm[GL_POINTS]));
574    stats->setAttribute(frameNumber, "Visible number of GL_LINES", static_cast<double>(pcm[GL_LINES]));
575    stats->setAttribute(frameNumber, "Visible number of GL_LINE_STRIP", static_cast<double>(pcm[GL_LINE_STRIP]));
576    stats->setAttribute(frameNumber, "Visible number of GL_LINE_LOOP", static_cast<double>(pcm[GL_LINE_LOOP]));
577    stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLES", static_cast<double>(pcm[GL_TRIANGLES]));
578    stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLE_STRIP", static_cast<double>(pcm[GL_TRIANGLE_STRIP]));
579    stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLE_FAN", static_cast<double>(pcm[GL_TRIANGLE_FAN]));
580    stats->setAttribute(frameNumber, "Visible number of GL_QUADS", static_cast<double>(pcm[GL_QUADS]));
581    stats->setAttribute(frameNumber, "Visible number of GL_QUAD_STRIP", static_cast<double>(pcm[GL_QUAD_STRIP]));
582    stats->setAttribute(frameNumber, "Visible number of GL_POLYGON", static_cast<double>(pcm[GL_POLYGON]));
583}
584
585void Renderer::cull()
586{
587    DEBUG_MESSAGE<<"cull()"<<std::endl;
588
589    if (_done || _graphicsThreadDoesCull) return;
590
591    // note we assume lock has already been acquired.
592    osgUtil::SceneView* sceneView = _availableQueue.takeFront();
593
594    DEBUG_MESSAGE<<"cull() got SceneView "<<sceneView<<std::endl;
595
596    if (sceneView)
597    {
598        updateSceneView(sceneView);
599
600        // OSG_NOTICE<<"Culling buffer "<<_currentCull<<std::endl;
601
602        // pass on the fusion distance settings from the View to the SceneView
603        osgViewer::View* view = dynamic_cast<osgViewer::View*>(sceneView->getCamera()->getView());
604        if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
605
606        osg::Stats* stats = sceneView->getCamera()->getStats();
607        osg::State* state = sceneView->getState();
608        const osg::FrameStamp* fs = state->getFrameStamp();
609        unsigned int frameNumber = fs ? fs->getFrameNumber() : 0;
610
611        // do cull traversal
612        osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
613
614        sceneView->inheritCullSettings(*(sceneView->getCamera()));
615        sceneView->cull();
616
617        osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
618
619#if 0
620        if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
621        {
622            // OSG_NOTICE<<"Completed in cull"<<std::endl;
623            state->getDynamicObjectRenderingCompletedCallback()->completed(state);
624        }
625#endif
626        if (stats && stats->collectStats("rendering"))
627        {
628            DEBUG_MESSAGE<<"Collecting rendering stats"<<std::endl;
629
630            stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
631            stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
632            stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
633        }
634
635        if (stats && stats->collectStats("scene"))
636        {
637            collectSceneViewStats(frameNumber, sceneView, stats);
638        }
639
640        _drawQueue.add(sceneView);
641
642    }
643
644    DEBUG_MESSAGE<<"end cull() "<<this<<std::endl;
645}
646
647void Renderer::draw()
648{
649    DEBUG_MESSAGE<<"draw() "<<this<<std::endl;
650
651    // osg::Timer_t startDrawTick = osg::Timer::instance()->tick();
652
653    osgUtil::SceneView* sceneView = _drawQueue.takeFront();
654
655    DEBUG_MESSAGE<<"draw() got SceneView "<<sceneView<<std::endl;
656
657    if (sceneView && !_done)
658    {
659        // since we are running the draw thread in parallel with the main thread it's possible to unreference Camera's
660        // that are still being used by this rendering thread, so to prevent this we'll take references to all these
661        // Camera's and the clear these references once we've completed the whole draw dispatch.
662        sceneView->collateReferencesToDependentCameras();
663
664        if (_compileOnNextDraw)
665        {
666            compile();
667        }
668
669        // OSG_NOTICE<<"Drawing buffer "<<_currentDraw<<std::endl;
670
671        if (_done)
672        {
673            OSG_INFO<<"Renderer::release() causing draw to exit"<<std::endl;
674            return;
675        }
676
677        if (_graphicsThreadDoesCull)
678        {
679            OSG_INFO<<"Renderer::draw() completing early due to change in _graphicsThreadDoesCull flag."<<std::endl;
680            return;
681        }
682
683        // OSG_NOTICE<<"RenderingOperation"<<std::endl;
684
685        osg::Stats* stats = sceneView->getCamera()->getStats();
686        osg::State* state = sceneView->getState();
687        unsigned int frameNumber = state->getFrameStamp()->getFrameNumber();
688
689        if (!_initialized)
690        {
691            initialize(state);
692        }
693
694        state->setDynamicObjectCount(sceneView->getDynamicObjectCount());
695
696        if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
697        {
698            // OSG_NOTICE<<"Completed in cull"<<std::endl;
699            state->getDynamicObjectRenderingCompletedCallback()->completed(state);
700        }
701
702        bool acquireGPUStats = stats && _querySupport && stats->collectStats("gpu");
703
704        if (acquireGPUStats)
705        {
706            _querySupport->checkQuery(stats, state, _startTick);
707        }
708
709        // do draw traversal
710        if (acquireGPUStats)
711        {
712            _querySupport->checkQuery(stats, state, _startTick);
713            _querySupport->beginQuery(frameNumber, state);
714        }
715
716        osg::Timer_t beforeDrawTick;
717
718
719        bool serializeDraw = sceneView->getDisplaySettings()->getSerializeDrawDispatch();
720
721        if (serializeDraw)
722        {
723            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_drawSerializerMutex);
724            beforeDrawTick = osg::Timer::instance()->tick();
725            sceneView->draw();
726        }
727        else
728        {
729            beforeDrawTick = osg::Timer::instance()->tick();
730            sceneView->draw();
731        }
732
733        _availableQueue.add(sceneView);
734
735        if (acquireGPUStats)
736        {
737            _querySupport->endQuery(state);
738            _querySupport->checkQuery(stats, state, _startTick);
739        }
740
741        //glFlush();
742
743        osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
744
745//        OSG_NOTICE<<"Time wait for draw = "<<osg::Timer::instance()->delta_m(startDrawTick, beforeDrawTick)<<std::endl;
746//        OSG_NOTICE<<"     time for draw = "<<osg::Timer::instance()->delta_m(beforeDrawTick, afterDrawTick)<<std::endl;
747
748        if (stats && stats->collectStats("rendering"))
749        {
750            stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
751            stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
752            stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick));
753        }
754
755        sceneView->clearReferencesToDependentCameras();
756    }
757
758    DEBUG_MESSAGE<<"end draw() "<<this<<std::endl;
759}
760
761void Renderer::cull_draw()
762{
763    DEBUG_MESSAGE<<"cull_draw() "<<this<<std::endl;
764
765    osgUtil::SceneView* sceneView = _sceneView[0].get();
766    if (!sceneView || _done) return;
767
768    if (_done)
769    {
770        OSG_INFO<<"Render::release() causing cull_draw to exit"<<std::endl;
771        return;
772    }
773
774    updateSceneView(sceneView);
775
776    if (_compileOnNextDraw)
777    {
778        compile();
779    }
780
781    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
782
783    // OSG_NOTICE<<"RenderingOperation"<<std::endl;
784
785    // pass on the fusion distance settings from the View to the SceneView
786    if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
787
788    osg::Stats* stats = sceneView->getCamera()->getStats();
789    osg::State* state = sceneView->getState();
790    const osg::FrameStamp* fs = state->getFrameStamp();
791    unsigned int frameNumber = fs ? fs->getFrameNumber() : 0;
792
793    if (!_initialized)
794    {
795        initialize(state);
796    }
797
798    bool acquireGPUStats = stats && _querySupport && stats->collectStats("gpu");
799
800    if (acquireGPUStats)
801    {
802        _querySupport->checkQuery(stats, state, _startTick);
803    }
804
805    // do cull traversal
806    osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
807
808    sceneView->inheritCullSettings(*(sceneView->getCamera()));
809    sceneView->cull();
810
811    osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
812
813    if (stats && stats->collectStats("scene"))
814    {
815        collectSceneViewStats(frameNumber, sceneView, stats);
816    }
817
818#if 0
819    if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
820    {
821        state->getDynamicObjectRenderingCompletedCallback()->completed(state);
822    }
823#endif
824
825
826    // do draw traversal
827    if (acquireGPUStats)
828    {
829        _querySupport->checkQuery(stats, state, _startTick);
830        _querySupport->beginQuery(frameNumber, state);
831    }
832
833    osg::Timer_t beforeDrawTick;
834
835    bool serializeDraw = sceneView->getDisplaySettings()->getSerializeDrawDispatch();
836
837    if (serializeDraw)
838    {
839        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_drawSerializerMutex);
840
841        beforeDrawTick = osg::Timer::instance()->tick();
842        sceneView->draw();
843    }
844    else
845    {
846        beforeDrawTick = osg::Timer::instance()->tick();
847        sceneView->draw();
848    }
849
850    if (acquireGPUStats)
851    {
852        _querySupport->endQuery(state);
853        _querySupport->checkQuery(stats, state, _startTick);
854    }
855
856    osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
857
858    if (stats && stats->collectStats("rendering"))
859    {
860        DEBUG_MESSAGE<<"Collecting rendering stats"<<std::endl;
861
862        stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
863        stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
864        stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
865
866        stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
867        stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
868        stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick));
869    }
870
871    DEBUG_MESSAGE<<"end cull_draw() "<<this<<std::endl;
872
873}
874
875void Renderer::operator () (osg::Object* object)
876{
877    osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
878    if (context) operator()(context);
879
880    osg::Camera* camera = dynamic_cast<osg::Camera*>(object);
881    if (camera) cull();
882}
883
884void Renderer::operator () (osg::GraphicsContext* context)
885{
886    if (_graphicsThreadDoesCull)
887    {
888        cull_draw();
889    }
890    else
891    {
892        draw();
893    }
894}
895
896void Renderer::release()
897{
898    OSG_INFO<<"Renderer::release()"<<std::endl;
899    _done = true;
900
901    _availableQueue.release();
902    _drawQueue.release();
903}
904
905void Renderer::setCameraRequiresSetUp(bool flag)
906{
907    for (int i = 0; i < 2; ++i)
908    {
909        osgUtil::SceneView* sv = getSceneView(i);
910        osgUtil::RenderStage* rs = sv ? sv->getRenderStage() : 0;
911        if (rs) rs->setCameraRequiresSetUp(flag);
912    }
913}
914
915bool Renderer::getCameraRequiresSetUp() const
916{
917    bool result = false;
918    for (int i = 0; i < 2; ++i)
919    {
920        const osgUtil::SceneView* sv = getSceneView(i);
921        const osgUtil::RenderStage* rs = sv ? sv->getRenderStage() : 0;
922        if (rs) result = result || rs->getCameraRequiresSetUp();
923    }
924    return result;
925}
Note: See TracBrowser for help on using the browser.