From fd0ea388c27091983efb1b3b0bbe633cf7ed7736 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 29 Jan 2007 22:44:29 +0000 Subject: [PATCH] Began work on providing support for threading camera cull traversals in parallel with the previous frames draw traversal. Changes range from osg::State, through osgUtil::RenderBin, through to osgViewer --- include/osg/State | 44 +++++++++++++++++++++++ include/osgUtil/Optimizer | 28 +++++++++++++-- include/osgUtil/RenderBin | 3 ++ include/osgUtil/RenderLeaf | 12 +++++-- include/osgUtil/RenderStage | 5 +-- include/osgUtil/StateGraph | 11 ++++-- include/osgViewer/View | 24 +++++++++++++ include/osgViewer/Viewer | 11 +++++- src/osg/Drawable.cpp | 2 ++ src/osg/State.cpp | 2 ++ src/osg/StateSet.cpp | 2 +- src/osgUtil/Optimizer.cpp | 55 +++++++++++++++++++++++++++-- src/osgUtil/RenderBin.cpp | 51 ++++++++++++++++++++++++++- src/osgUtil/RenderLeaf.cpp | 5 +++ src/osgUtil/RenderStage.cpp | 24 +++++++++++++ src/osgUtil/SceneView.cpp | 8 +++++ src/osgViewer/View.cpp | 57 ++++++++++++++++++++++++++++++ src/osgViewer/Viewer.cpp | 69 ++++++++++++++++++++++++++++++------- 18 files changed, 387 insertions(+), 26 deletions(-) diff --git a/include/osg/State b/include/osg/State index 8cab54d79..de38ae86f 100644 --- a/include/osg/State +++ b/include/osg/State @@ -753,6 +753,47 @@ class OSG_EXPORT State : public Referenced * if true steps should be taken to complete rendering early.*/ bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; } + + struct DynamicObjectRenderingCompletedCallback : public osg::Referenced + { + virtual void completed(osg::State*) = 0; + }; + + /** Set the callback to be called when the dynamic object count hits 0.*/ + void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; } + + /** Get the callback to be called when the dynamic object count hits 0.*/ + DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); } + + /** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/ + void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false) + { + if (_dynamicObjectCount != count) + { + _dynamicObjectCount = count; + if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid()) + { + _completeDynamicObjectRenderingCallback->completed(this); + } + } + } + + /** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/ + unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; } + + /** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the + * DynamicObjectRenderingCompletedCallback to inform of completion.*/ + inline void decrementDynamicObjectCount() + { + --_dynamicObjectCount; + if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid()) + { + _completeDynamicObjectRenderingCallback->completed(this); + } + } + + + enum CheckForGLErrors { /** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this @@ -1028,6 +1069,9 @@ class OSG_EXPORT State : public Referenced DisableVertexAttribProc _glDisableVertexAttribArray; void initializeExtensionProcs(); + unsigned int _dynamicObjectCount; + osg::ref_ptr _completeDynamicObjectRenderingCallback; + }; inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList) diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index f2eb113f2..cab8a0578 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -82,6 +82,7 @@ class OSGUTIL_EXPORT Optimizer MERGE_GEODES = 0x1000, FLATTEN_BILLBOARDS = 0x2000, TEXTURE_ATLAS_BUILDER = 0x4000, + STATIC_OBJECT_DETECTION = 0x8000, DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | REMOVE_LOADED_PROXY_NODES | @@ -89,7 +90,8 @@ class OSGUTIL_EXPORT Optimizer SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | CHECK_GEOMETRY | - OPTIMIZE_TEXTURE_SETTINGS, + OPTIMIZE_TEXTURE_SETTINGS | + STATIC_OBJECT_DETECTION, ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | REMOVE_LOADED_PROXY_NODES | @@ -102,7 +104,8 @@ class OSGUTIL_EXPORT Optimizer COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS | - TEXTURE_ATLAS_BUILDER + TEXTURE_ATLAS_BUILDER | + STATIC_OBJECT_DETECTION }; /** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/ @@ -740,6 +743,27 @@ class OSGUTIL_EXPORT Optimizer }; + /** Optimize the setting of StateSet and Geometry objects in scene so that they have a STATIC DataVariance + * when they don't have any callbacks associated with them. */ + class OSGUTIL_EXPORT StaticObjectDetectionVisitor : public BaseOptimizerVisitor + { + public: + + /// default to traversing all children. + StaticObjectDetectionVisitor(Optimizer* optimizer=0): + BaseOptimizerVisitor(optimizer, STATIC_OBJECT_DETECTION) {} + + virtual void apply(osg::Node& node); + + virtual void apply(osg::Geode& geode); + + protected: + + void applyStateSet(osg::StateSet& stateset); + + void applyDrawable(osg::Drawable& drawable); + + }; }; inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const diff --git a/include/osgUtil/RenderBin b/include/osgUtil/RenderBin index 4bd3d71d4..93d032940 100644 --- a/include/osgUtil/RenderBin +++ b/include/osgUtil/RenderBin @@ -140,6 +140,9 @@ class OSGUTIL_EXPORT RenderBin : public osg::Object /** Extract stats for current draw list. */ bool getStats(Statistics& primStats) const; + + /** Compute the number of dynamic RenderLeaves.*/ + virtual unsigned int computeNumberOfDynamicRenderLeaves() const; void copyLeavesFromStateGraphListToRenderLeafList(); diff --git a/include/osgUtil/RenderLeaf b/include/osgUtil/RenderLeaf index 5eda6c771..2c5ad0dc1 100644 --- a/include/osgUtil/RenderLeaf +++ b/include/osgUtil/RenderLeaf @@ -39,16 +39,20 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced _drawable(drawable), _projection(projection), _modelview(modelview), - _depth(depth) {} + _depth(depth) + { + _dynamic = (drawable->getDataVariance()==osg::Object::DYNAMIC); + } inline void set(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* modelview, float depth=0.0f) { _parent = 0; _drawable = drawable; - _projection = projection, - _modelview = modelview, + _projection = projection, + _modelview = modelview, _depth = depth; + _dynamic = (drawable->getDataVariance()==osg::Object::DYNAMIC); } inline void reset() @@ -58,6 +62,7 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced _projection = 0; _modelview = 0; _depth = 0.0f; + _dynamic = false; } virtual void render(osg::RenderInfo& renderInfo,RenderLeaf* previous); @@ -72,6 +77,7 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced osg::ref_ptr _projection; osg::ref_ptr _modelview; float _depth; + bool _dynamic; private: diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index 4fa797236..6716b574e 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -201,9 +201,10 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin /** Extract stats for current draw list. */ bool getStats(Statistics& stats) const; + /** Compute the number of dynamic RenderLeaves.*/ + virtual unsigned int computeNumberOfDynamicRenderLeaves() const; - - struct Attachment + struct Attachment { osg::ref_ptr _image; GLenum _imageReadPixelFormat; diff --git a/include/osgUtil/StateGraph b/include/osgUtil/StateGraph index bffa5955c..b71188647 100644 --- a/include/osgUtil/StateGraph +++ b/include/osgUtil/StateGraph @@ -58,6 +58,7 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced osg::ref_ptr _userData; + bool _dynamic; StateGraph(): osg::Referenced(false), @@ -66,7 +67,8 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced _depth(0), _averageDistance(0), _minimumDistance(0), - _userData(NULL) + _userData(NULL), + _dynamic(false) { } @@ -77,9 +79,13 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced _depth(0), _averageDistance(0), _minimumDistance(0), - _userData(NULL) + _userData(NULL), + _dynamic(false) { if (_parent) _depth = _parent->_depth + 1; + + if (_parent && _parent->_dynamic) _dynamic = true; + else _dynamic = stateset->getDataVariance()==osg::Object::DYNAMIC; } ~StateGraph() {} @@ -176,6 +182,7 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced _minimumDistance = FLT_MAX; // signify dirty. _leaves.push_back(leaf); leaf->_parent = this; + if (_dynamic) leaf->_dynamic = true; } } diff --git a/include/osgViewer/View b/include/osgViewer/View index ace67ae79..176f506b8 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -25,6 +25,30 @@ namespace osgViewer { +class OSGVIEWER_EXPORT EndOfDynamicDrawBlock : public osg::State::DynamicObjectRenderingCompletedCallback +{ + public: + + EndOfDynamicDrawBlock(); + + void completed(osg::State* state); + + void block(); + + void release(); + + void set(unsigned int blockCount); + + protected: + + ~EndOfDynamicDrawBlock(); + + OpenThreads::Mutex _mut; + OpenThreads::Condition _cond; + unsigned int _blockCount; +}; + + /** View holds a single view on a scene, this view may be composed of one or more slave cameras.*/ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter { diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 64e22c5f9..06e4b1fda 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -63,6 +63,13 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** Get the threading model the rendering traversals will use.*/ ThreadingModel getThreadingModel() const { return _threadingModel; } + /** Set whether the main thread, calling frame(), should be used for the rendering traversals.*/ + void setUseMainThreadForRenderingTraversals(bool flag); + + /** Get whether the main thread, calling frame(), should be used for the rendering traversals.*/ + bool getUseMainThreadForRenderingTraversals() const { return _useMainThreadForRenderingTraversal; } + + enum BarrierPosition { BeforeSwapBuffers, @@ -148,11 +155,13 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View int _keyEventSetsDone; bool _quitEventSetsDone; - ThreadingModel _threadingModel; + ThreadingModel _threadingModel; + bool _useMainThreadForRenderingTraversal; BarrierPosition _endBarrierPosition; osg::ref_ptr _startRenderingBarrier; osg::ref_ptr _endRenderingDispatchBarrier; + osg::ref_ptr _endDynamicDrawBlock; unsigned int computeNumberOfThreadsIncludingMainRequired(); diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 9c34c4b64..6d924c5a1 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -246,6 +246,8 @@ void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*c Drawable::Drawable() { + setDataVariance(osg::Object::STATIC); + _boundingBoxComputed = false; // Note, if your are defining a subclass from drawable which is diff --git a/src/osg/State.cpp b/src/osg/State.cpp index abe21295f..b26cbca65 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -53,6 +53,8 @@ State::State() _glVertexAttribPointer = 0; _glEnableVertexAttribArray = 0; _glDisableVertexAttribArray = 0; + + _dynamicObjectCount = 0; } State::~State() diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp index 5e4566813..c793cb98b 100644 --- a/src/osg/StateSet.cpp +++ b/src/osg/StateSet.cpp @@ -80,7 +80,7 @@ bool osg::isTextureMode(StateAttribute::GLMode mode) StateSet::StateSet() { - setDataVariance(osg::StateAttribute::STATIC); + setDataVariance(osg::Object::STATIC); _renderingHint = DEFAULT_BIN; diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index e2d28a674..09c172c32 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -47,7 +47,7 @@ void Optimizer::reset() { } -static osg::ApplicationUsageProxy Optimizer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_OPTIMIZER \" []\"","OFF | DEFAULT | FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | MERGE_GEODES | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS | REMOVE_LOADED_PROXY_NODES | TESSELLATE_GEOMETRY | CHECK_GEOMETRY | FLATTEN_BILLBOARDS | TEXTURE_ATLAS_BUILDER"); +static osg::ApplicationUsageProxy Optimizer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_OPTIMIZER \" []\"","OFF | DEFAULT | FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | MERGE_GEODES | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS | REMOVE_LOADED_PROXY_NODES | TESSELLATE_GEOMETRY | CHECK_GEOMETRY | FLATTEN_BILLBOARDS | TEXTURE_ATLAS_BUILDER | STATIC_OBJECT_DETECTION"); void Optimizer::optimize(osg::Node* node) { @@ -108,6 +108,9 @@ void Optimizer::optimize(osg::Node* node) if(str.find("~TEXTURE_ATLAS_BUILDER")!=std::string::npos) options ^= TEXTURE_ATLAS_BUILDER; else if(str.find("TEXTURE_ATLAS_BUILDER")!=std::string::npos) options |= TEXTURE_ATLAS_BUILDER; + + if(str.find("~STATIC_OBJECT_DETECTION")!=std::string::npos) options ^= STATIC_OBJECT_DETECTION; + else if(str.find("STATIC_OBJECT_DETECTION")!=std::string::npos) options |= STATIC_OBJECT_DETECTION; } else @@ -299,7 +302,13 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) node->accept(sv); sv.divide(); } - + + if (options & STATIC_OBJECT_DETECTION) + { + StaticObjectDetectionVisitor sodv; + node->accept(sodv); + } + if (osg::getNotifyLevel()>=osg::INFO) { stats.reset(); @@ -4104,3 +4113,45 @@ void Optimizer::TextureAtlasVisitor::optimize() } } + + + +//////////////////////////////////////////////////////////////////////////// +// StaticObjectDectionVisitor +//////////////////////////////////////////////////////////////////////////// + +void Optimizer::StaticObjectDetectionVisitor::apply(osg::Node& node) +{ + if (node.getStateSet()) applyStateSet(*node.getStateSet()); + + traverse(node); +} + +void Optimizer::StaticObjectDetectionVisitor::apply(osg::Geode& geode) +{ + if (geode.getStateSet()) applyStateSet(*geode.getStateSet()); + + for(unsigned int i=0; ifirst<0; + ++rbitr) + { + count += rbitr->second->computeNumberOfDynamicRenderLeaves(); + } + + // draw fine grained ordering. + for(RenderLeafList::const_iterator rlitr= _renderLeafList.begin(); + rlitr!= _renderLeafList.end(); + ++rlitr) + { + RenderLeaf* rl = *rlitr; + if (rl->_dynamic) ++count; + } + + + // draw coarse grained ordering. + for(StateGraphList::const_iterator oitr=_stateGraphList.begin(); + oitr!=_stateGraphList.end(); + ++oitr) + { + + for(StateGraph::LeafList::const_iterator dw_itr = (*oitr)->_leaves.begin(); + dw_itr != (*oitr)->_leaves.end(); + ++dw_itr) + { + RenderLeaf* rl = dw_itr->get(); + if (rl->_dynamic) ++count; + } + } + + // draw post bins. + for(; + rbitr!=_bins.end(); + ++rbitr) + { + count += rbitr->second->computeNumberOfDynamicRenderLeaves(); + } + + return count; +} diff --git a/src/osgUtil/RenderLeaf.cpp b/src/osgUtil/RenderLeaf.cpp index 221bd794c..ca19b6dbe 100644 --- a/src/osgUtil/RenderLeaf.cpp +++ b/src/osgUtil/RenderLeaf.cpp @@ -74,5 +74,10 @@ void RenderLeaf::render(osg::RenderInfo& renderInfo,RenderLeaf* previous) _drawable->draw(renderInfo); } + if (_dynamic) + { + state.decrementDynamicObjectCount(); + } + // osg::notify(osg::NOTICE)<<"RenderLeaf "<<_drawable->getName()<<" "<<_depth<second->computeNumberOfDynamicRenderLeaves(); + } + + count += RenderBin::computeNumberOfDynamicRenderLeaves(); + + for(RenderStageList::const_iterator post_itr = _postRenderList.begin(); + post_itr != _postRenderList.end(); + ++post_itr) + { + count += post_itr->second->computeNumberOfDynamicRenderLeaves(); + } + + return count; +} + diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index debcc0275..82fe96f56 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -777,6 +777,11 @@ void SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& mod // a clean has been used instead to try to minimize the amount of // allocation and deleteing of the StateGraph nodes. rendergraph->prune(); + + // set the number of dynamic objects in the scene. + getState()->setDynamicObjectCount( getState()->getDynamicObjectCount() + renderStage->computeNumberOfDynamicRenderLeaves()); + + // osg::notify(osg::NOTICE)<<"SceneView cull() DynamicObjectCount"<getDynamicObjectCount()<setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE); } } + + // osg::notify(osg::NOTICE)<<"SceneView draw() DynamicObjectCount"<getDynamicObjectCount()< mutlock(_mut); + if (_blockCount>0) + { + --_blockCount; + + if (_blockCount==0) + { + // osg::notify(osg::NOTICE)<<"Released"< mutlock(_mut); + if (_blockCount) + _cond.wait(&_mut); +} + +void EndOfDynamicDrawBlock::release() +{ + OpenThreads::ScopedLock mutlock(_mut); + if (_blockCount) + { + _blockCount = 0; + _cond.broadcast(); + } +} + +void EndOfDynamicDrawBlock::set(unsigned int blockCount) +{ + OpenThreads::ScopedLock mutlock(_mut); + if (blockCount!=_blockCount) + { + if (blockCount==0) _cond.broadcast(); + _blockCount = blockCount; + } +} + +EndOfDynamicDrawBlock::~EndOfDynamicDrawBlock() +{ + release(); +} diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 40ea37830..0f0fd37aa 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -170,6 +170,16 @@ void Viewer::setThreadingModel(ThreadingModel threadingModel) if (_threadingModel!=SingleThreaded) startThreading(); } +void Viewer::setUseMainThreadForRenderingTraversals(bool flag) +{ + if (_useMainThreadForRenderingTraversal==flag) return; + + if (_threadingModel!=SingleThreaded) stopThreading(); + + _useMainThreadForRenderingTraversal = flag; + + if (_threadingModel!=SingleThreaded) startThreading(); +} void Viewer::setEndBarrierPosition(BarrierPosition bp) { @@ -259,12 +269,9 @@ unsigned int Viewer::computeNumberOfThreadsIncludingMainRequired() return 1; } - bool firstContextAsMainThread = _threadingModel == ThreadPerContext; - - return firstContextAsMainThread ? contexts.size() : contexts.size()+1; + return _useMainThreadForRenderingTraversal ? contexts.size() : contexts.size()+1; } - void Viewer::startThreading() { unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired(); @@ -310,11 +317,21 @@ void Viewer::startThreading() _numThreadsOnBarrier = numThreadsIncludingMainThread; _startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); -#if 1 - _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); -#else - _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::GL_FINISH); -#endif + + + if (_threadingModel==ThreadPerContext) + { + #if 1 + _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION); + #else + _endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::GL_FINISH); + #endif + } + else + { + _endDynamicDrawBlock = new EndOfDynamicDrawBlock; + } + osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); Contexts::iterator citr = contexts.begin(); @@ -326,12 +343,15 @@ void Viewer::startThreading() ++citr; } + for(; citr != contexts.end(); ++citr, ++processNum) { osg::GraphicsContext* gc = (*citr); + + gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get()); // create the a graphics thread for this context gc->createGraphicsThread(); @@ -346,7 +366,7 @@ void Viewer::startThreading() // add the rendering operation itself. gc->getGraphicsThread()->add(new ViewerRunOperations()); - if (_endBarrierPosition==BeforeSwapBuffers) + if (_endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); @@ -355,7 +375,7 @@ void Viewer::startThreading() // add the swap buffers gc->getGraphicsThread()->add(swapOp.get()); - if (_endBarrierPosition==AfterSwapBuffers) + if (_endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) { // add the endRenderingDispatchBarrier gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); @@ -561,6 +581,10 @@ struct ViewerRenderingOperation : public osg::GraphicsOperation _sceneView->cull(); osg::Timer_t afterCullTick = osg::Timer::instance()->tick(); + if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback()) + { + state->getDynamicObjectRenderingCompletedCallback()->completed(state); + } // do draw traveral if (_aquireGPUStats) @@ -1187,11 +1211,24 @@ void Viewer::renderingTraversals() Contexts contexts; getContexts(contexts); + + Contexts::iterator itr; + if (_endDynamicDrawBlock.valid()) + { + unsigned int numToBlock = 0; + for(itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + if (((*itr)->getGraphicsThread())) ++numToBlock; + } + + _endDynamicDrawBlock->set(numToBlock); + } // dispatch the the rendering threads if (_startRenderingBarrier.valid()) _startRenderingBarrier->block(); - Contexts::iterator itr; for(itr = contexts.begin(); itr != contexts.end(); ++itr) @@ -1207,6 +1244,14 @@ void Viewer::renderingTraversals() // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<tick(); + _endDynamicDrawBlock->block(); + // osg::notify(osg::NOTICE)<<"Time waiting "<delta_m(startTick, osg::Timer::instance()->tick())<block();