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

Revision 7858, 18.3 kB (checked in by robert, 10 years ago)

From Bryan Thrall, "moved the prints to a higher notify level
(DEBUG_FP) so they are only printed at the most verbose level."

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
21#include <osgViewer/Renderer>
22#include <osgViewer/View>
23
24#include <osgDB/DatabasePager>
25
26#include <osg/io_utils>
27
28#include <sstream>
29
30using namespace osgViewer;
31
32//#define DEBUG_MESSAGE osg::notify(osg::NOTICE)
33#define DEBUG_MESSAGE osg::notify(osg::DEBUG_FP)
34
35
36OpenGLQuerySupport::OpenGLQuerySupport():
37    _startTick(0),
38    _initialized(false),
39    _timerQuerySupported(false),
40    _extensions(0),
41    _previousQueryTime(0.0)
42{
43}
44
45void OpenGLQuerySupport::checkQuery(osg::Stats* stats)
46{
47    for(QueryFrameNumberList::iterator itr = _queryFrameNumberList.begin();
48        itr != _queryFrameNumberList.end();
49        )
50    {
51        GLuint query = itr->first;
52        GLint available = 0;
53        _extensions->glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &available);
54        if (available)
55        {
56            GLuint64EXT timeElapsed = 0;
57            _extensions->glGetQueryObjectui64v(query, GL_QUERY_RESULT, &timeElapsed);
58
59            double timeElapsedSeconds = double(timeElapsed)*1e-9;
60            double currentTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
61            double estimatedEndTime = (_previousQueryTime + currentTime) * 0.5;
62            double estimatedBeginTime = estimatedEndTime - timeElapsedSeconds;
63
64            stats->setAttribute(itr->second, "GPU draw begin time", estimatedBeginTime);
65            stats->setAttribute(itr->second, "GPU draw end time", estimatedEndTime);
66            stats->setAttribute(itr->second, "GPU draw time taken", timeElapsedSeconds);
67
68
69            itr = _queryFrameNumberList.erase(itr);
70            _availableQueryObjects.push_back(query);
71        }
72        else
73        {
74            ++itr;
75        }
76
77    }
78    _previousQueryTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
79}
80
81GLuint OpenGLQuerySupport::createQueryObject()
82{
83    if (_availableQueryObjects.empty())
84    {
85        GLuint query;
86        _extensions->glGenQueries(1, &query);
87        return query;
88    }
89    else
90    {
91        GLuint query = _availableQueryObjects.back();
92        _availableQueryObjects.pop_back();
93        return query;
94    }
95}
96
97void OpenGLQuerySupport::beginQuery(int frameNumber)
98{
99    GLuint query = createQueryObject();
100    _extensions->glBeginQuery(GL_TIME_ELAPSED, query);
101    _queryFrameNumberList.push_back(QueryFrameNumberPair(query, frameNumber));       
102}
103
104void OpenGLQuerySupport::endQuery()
105{
106    _extensions->glEndQuery(GL_TIME_ELAPSED);
107}
108
109void OpenGLQuerySupport::initialize(osg::State* state)
110{
111    if (_initialized) return;
112
113    _initialized = true;
114    _extensions = osg::Drawable::getExtensions(state->getContextID(),true);
115    _timerQuerySupported = _extensions && _extensions->isTimerQuerySupported();
116    _previousQueryTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
117}
118
119///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
120//
121//
122//  TheadSafeQueue
123
124Renderer::TheadSafeQueue::TheadSafeQueue()
125{
126    _block.set(false);
127}
128
129Renderer::TheadSafeQueue::~TheadSafeQueue()
130{
131}
132
133osgUtil::SceneView* Renderer::TheadSafeQueue::takeFront()
134{
135    if (_queue.empty()) _block.block();
136
137    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
138    if (_queue.empty()) return 0;
139
140    osgUtil::SceneView* front = _queue.front();
141    _queue.pop_front();
142
143    if (_queue.empty()) _block.set(false);
144   
145    return front;
146}
147
148void Renderer::TheadSafeQueue::add(osgUtil::SceneView* sv)
149{
150    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
151    _queue.push_back(sv);
152    _block.set(true);
153}
154
155static OpenThreads::Mutex s_drawSerializerMutex;
156
157///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158//
159//
160//  Renderer
161Renderer::Renderer(osg::Camera* camera):
162    osg::GraphicsOperation("Renderer",true),
163    OpenGLQuerySupport(),
164    _camera(camera),
165    _done(false),
166    _graphicsThreadDoesCull(true)
167{
168
169    DEBUG_MESSAGE<<"Render::Render() "<<this<<std::endl;
170
171    _sceneView[0] = new osgUtil::SceneView;
172    _sceneView[1] = new osgUtil::SceneView;
173
174    unsigned int sceneViewOptions = osgUtil::SceneView::HEADLIGHT;
175
176    osg::Camera* masterCamera = _camera->getView() ? _camera->getView()->getCamera() : camera;
177    osg::StateSet* stateset = masterCamera->getOrCreateStateSet();
178    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
179
180    osg::DisplaySettings* ds = _camera->getDisplaySettings() ?  _camera->getDisplaySettings() :
181                               ((view && view->getDisplaySettings()) ?  view->getDisplaySettings() :  osg::DisplaySettings::instance());
182
183    _sceneView[0]->setGlobalStateSet(stateset);
184    _sceneView[1]->setGlobalStateSet(stateset);
185   
186    _sceneView[0]->setDefaults(sceneViewOptions);
187    _sceneView[1]->setDefaults(sceneViewOptions);
188
189    _sceneView[0]->setDisplaySettings(ds);
190    _sceneView[1]->setDisplaySettings(ds);
191
192    _sceneView[0]->setCamera(_camera.get(), false);
193    _sceneView[1]->setCamera(_camera.get(), false);
194
195    // lock the mutex for the current cull SceneView to
196    // prevent the draw traversal from reading from it before the cull traversal has been completed.
197    _availableQueue.add(_sceneView[0].get());
198    _availableQueue.add(_sceneView[1].get());
199       
200    DEBUG_MESSAGE<<"_availableQueue.size()="<<_availableQueue._queue.size()<<std::endl;
201
202    _flushOperation = new osg::FlushDeletedGLObjectsOperation(0.1);
203}
204
205Renderer::~Renderer()
206{
207    DEBUG_MESSAGE<<"Render::~Render() "<<this<<std::endl;
208}
209
210void Renderer::setGraphicsThreadDoesCull(bool flag)
211{
212    if (_graphicsThreadDoesCull==flag) return;
213
214    _graphicsThreadDoesCull = flag;
215}
216
217void Renderer::updateSceneView(osgUtil::SceneView* sceneView)
218{
219    osg::Camera* masterCamera = _camera->getView() ? _camera->getView()->getCamera() : _camera.get();
220    osg::StateSet* stateset = masterCamera->getOrCreateStateSet();
221
222    if (sceneView->getGlobalStateSet()!=stateset)
223    {
224        sceneView->setGlobalStateSet(stateset);
225    }
226   
227    osg::GraphicsContext* context = _camera->getGraphicsContext();
228    osg::State* state = context ? context->getState() : 0;
229    if (sceneView->getState()!=state)
230    {
231        sceneView->setState(state);
232    }
233
234    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
235    osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
236    sceneView->getCullVisitor()->setDatabaseRequestHandler(databasePager);
237   
238    sceneView->setFrameStamp(view ? view->getFrameStamp() : state->getFrameStamp());
239   
240    if (databasePager) databasePager->setCompileGLObjectsForContextID(state->getContextID(), true);
241   
242    osg::DisplaySettings* ds = _camera->getDisplaySettings() ?  _camera->getDisplaySettings() :
243                               ((view &&view->getDisplaySettings()) ?  view->getDisplaySettings() :  osg::DisplaySettings::instance());
244
245    sceneView->setDisplaySettings(ds);
246
247    if (view) _startTick = view->getStartTick();
248}
249
250
251void Renderer::cull()
252{
253    DEBUG_MESSAGE<<"cull()"<<std::endl;
254
255    if (_done || _graphicsThreadDoesCull) return;
256
257    // note we assume lock has already been acquired.
258    osgUtil::SceneView* sceneView = _availableQueue.takeFront();
259
260    DEBUG_MESSAGE<<"cull() got SceneView "<<sceneView<<std::endl;
261
262    if (sceneView)
263    {
264        updateSceneView(sceneView);
265
266        // osg::notify(osg::NOTICE)<<"Culling buffer "<<_currentCull<<std::endl;
267
268        // pass on the fusion distance settings from the View to the SceneView
269        osgViewer::View* view = dynamic_cast<osgViewer::View*>(sceneView->getCamera()->getView());
270        if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
271
272        osg::Stats* stats = sceneView->getCamera()->getStats();
273        osg::State* state = sceneView->getState();
274        const osg::FrameStamp* fs = state->getFrameStamp();
275        int frameNumber = fs ? fs->getFrameNumber() : 0;
276
277        // do cull traversal
278        osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
279
280        sceneView->inheritCullSettings(*(sceneView->getCamera()));
281        sceneView->cull();
282
283        osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
284
285#if 0
286        if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
287        {
288            // osg::notify(osg::NOTICE)<<"Completed in cull"<<std::endl;
289            state->getDynamicObjectRenderingCompletedCallback()->completed(state);
290        }
291#endif
292        if (stats && stats->collectStats("rendering"))
293        {
294            DEBUG_MESSAGE<<"Collecting rendering stats"<<std::endl;
295       
296            stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
297            stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
298            stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
299        }
300
301        _drawQueue.add(sceneView);
302
303    }
304
305    DEBUG_MESSAGE<<"end cull() "<<this<<std::endl;
306}
307
308void Renderer::draw()
309{
310    DEBUG_MESSAGE<<"draw() "<<this<<std::endl;
311
312    osg::Timer_t startDrawTick = osg::Timer::instance()->tick();
313
314    osgUtil::SceneView* sceneView = _drawQueue.takeFront();
315
316    DEBUG_MESSAGE<<"draw() got SceneView "<<sceneView<<std::endl;
317
318    osg::GraphicsContext* compileContext = sceneView ? osg::GraphicsContext::getCompileContext(sceneView->getState()->getContextID()) : 0;
319    osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0;
320
321    if (sceneView || _done)
322    {
323        osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
324        osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
325
326        // osg::notify(osg::NOTICE)<<"Drawing buffer "<<_currentDraw<<std::endl;
327
328        if (_done)
329        {
330            osg::notify(osg::INFO)<<"Renderer::release() causing draw to exit"<<std::endl;
331            return;
332        }
333
334        if (_graphicsThreadDoesCull)
335        {
336            osg::notify(osg::INFO)<<"Renderer::draw() completing early due to change in _graphicsThreadDoesCull flag."<<std::endl;
337            return;
338        }
339
340        // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
341
342        osg::Stats* stats = sceneView->getCamera()->getStats();
343        osg::State* state = sceneView->getState();
344        int frameNumber = state->getFrameStamp()->getFrameNumber();
345
346        if (!_initialized)
347        {
348            initialize(state);
349        }
350
351        state->setDynamicObjectCount(sceneView->getDynamicObjectCount());
352
353        if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
354        {
355            // osg::notify(osg::NOTICE)<<"Completed in cull"<<std::endl;
356            state->getDynamicObjectRenderingCompletedCallback()->completed(state);
357        }
358
359        bool acquireGPUStats = stats && _timerQuerySupported && stats->collectStats("gpu");
360
361        if (acquireGPUStats)
362        {
363            checkQuery(stats);
364        }
365
366        // do draw traversal
367        if (acquireGPUStats)
368        {
369            checkQuery(stats);
370            beginQuery(frameNumber);
371        }
372
373        osg::Timer_t beforeDrawTick;
374       
375       
376        bool serializeDraw = sceneView->getDisplaySettings()->getSerializeDrawDispatch();
377
378        if (serializeDraw)
379        {
380            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_drawSerializerMutex);
381            beforeDrawTick = osg::Timer::instance()->tick();
382            sceneView->draw();
383        }
384        else
385        {
386            beforeDrawTick = osg::Timer::instance()->tick();
387            sceneView->draw();
388        }
389
390        _availableQueue.add(sceneView);
391
392        double availableTime = 0.004; // 4 ms
393        if (databasePager && databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID()))
394        {
395            databasePager->compileGLObjects(*(sceneView->getState()), availableTime);
396        }
397
398        if (compileThread)
399        {
400            compileThread->add(_flushOperation.get());
401        }
402        else
403        {
404            sceneView->flushDeletedGLObjects(availableTime);
405        }
406
407        if (acquireGPUStats)
408        {
409            endQuery();
410            checkQuery(stats);
411        }
412
413        //glFlush();
414       
415        osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
416
417//        osg::notify(osg::NOTICE)<<"Time wait for draw = "<<osg::Timer::instance()->delta_m(startDrawTick, beforeDrawTick)<<std::endl;
418//        osg::notify(osg::NOTICE)<<"     time for draw = "<<osg::Timer::instance()->delta_m(beforeDrawTick, afterDrawTick)<<std::endl;
419
420        if (stats && stats->collectStats("rendering"))
421        {
422            stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
423            stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
424            stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick));
425        }
426    }
427
428    DEBUG_MESSAGE<<"end draw() "<<this<<std::endl;
429}
430
431void Renderer::cull_draw()
432{
433    DEBUG_MESSAGE<<"cull_draw() "<<this<<std::endl;
434
435    osgUtil::SceneView* sceneView = _sceneView[0].get();
436    if (!sceneView || _done) return;
437
438    updateSceneView(sceneView);
439
440    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
441    osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
442
443    osg::GraphicsContext* compileContext = osg::GraphicsContext::getCompileContext(sceneView->getState()->getContextID());
444    osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0;
445
446    if (_done)
447    {
448        osg::notify(osg::INFO)<<"Render::release() causing cull_draw to exit"<<std::endl;
449        return;
450    }
451
452    // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
453
454    // pass on the fusion distance settings from the View to the SceneView
455    if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
456
457    osg::Stats* stats = sceneView->getCamera()->getStats();
458    osg::State* state = sceneView->getState();
459    const osg::FrameStamp* fs = state->getFrameStamp();
460    int frameNumber = fs ? fs->getFrameNumber() : 0;
461
462    if (!_initialized)
463    {
464        initialize(state);
465    }
466
467    bool acquireGPUStats = stats && _timerQuerySupported && stats->collectStats("gpu");
468
469    if (acquireGPUStats)
470    {
471        checkQuery(stats);
472    }
473
474    // do cull traversal
475    osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
476
477    sceneView->inheritCullSettings(*(sceneView->getCamera()));
478    sceneView->cull();
479
480    osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
481
482#if 0
483    if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
484    {
485        state->getDynamicObjectRenderingCompletedCallback()->completed(state);
486    }
487#endif
488
489
490    // do draw traversal
491    if (acquireGPUStats)
492    {
493        checkQuery(stats);
494        beginQuery(frameNumber);
495    }
496
497    osg::Timer_t beforeDrawTick;
498
499    bool serializeDraw = sceneView->getDisplaySettings()->getSerializeDrawDispatch();
500
501    if (serializeDraw)
502    {
503        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_drawSerializerMutex);
504       
505        beforeDrawTick = osg::Timer::instance()->tick();
506        sceneView->draw();
507    }
508    else
509    {
510        beforeDrawTick = osg::Timer::instance()->tick();
511        sceneView->draw();
512    }
513
514    double availableTime = 0.004; // 4 ms
515    if (databasePager && databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID()))
516    {
517        databasePager->compileGLObjects(*(sceneView->getState()), availableTime);
518    }
519
520    if (compileThread)
521    {
522        compileThread->add(_flushOperation.get());
523    }
524    else
525    {
526        sceneView->flushDeletedGLObjects(availableTime);
527    }
528
529    if (acquireGPUStats)
530    {
531        endQuery();
532        checkQuery(stats);
533    }
534
535    osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
536
537    if (stats && stats->collectStats("rendering"))
538    {
539        DEBUG_MESSAGE<<"Collecting rendering stats"<<std::endl;
540
541        stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
542        stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
543        stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
544
545        stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
546        stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
547        stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick));
548    }
549
550    DEBUG_MESSAGE<<"end cull_draw() "<<this<<std::endl;
551
552}
553
554void Renderer::operator () (osg::Object* object)
555{
556    osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
557    if (context) operator()(context);
558
559    osg::Camera* camera = dynamic_cast<osg::Camera*>(object);
560    if (camera) cull();
561}
562
563void Renderer::operator () (osg::GraphicsContext* context)
564{
565    if (_graphicsThreadDoesCull)
566    {
567        cull_draw();
568    }
569    else
570    {
571        draw();
572    }
573}
574
575void Renderer::release()
576{
577    osg::notify(osg::INFO)<<"Renderer::release()"<<std::endl;
578    _done = true;
579
580    _availableQueue.release();
581    _drawQueue.release();
582}
Note: See TracBrowser for help on using the browser.