diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index da7f8bd82..d72f002ab 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -224,20 +224,29 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin GLenum _imageReadPixelFormat; GLenum _imageReadPixelDataType; }; - + void attach(osg::Camera::BufferComponent buffer, osg::Image* image); - + + /** search through any pre and post RenderStage that reference a Camera, and take a reference to each of these cameras to prevent them being deleted while they are still be used by the drawing thread.*/ + void collateReferencesToDependentCameras(); + + /** clear the refence to any any dependent cameras.*/ + void clearReferencesToDependentCameras(); + protected: - + virtual ~RenderStage(); typedef std::pair< int , osg::ref_ptr > RenderStageOrderPair; typedef std::list< RenderStageOrderPair > RenderStageList; + typedef std::vector< osg::ref_ptr > Cameras; bool _stageDrawnThisFrame; RenderStageList _preRenderList; RenderStageList _postRenderList; + Cameras _dependentCameras; + // viewport x,y,width,height. osg::ref_ptr _viewport; @@ -271,8 +280,7 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin mutable osg::Matrix _inheritedPositionalStateContainerMatrix; mutable osg::ref_ptr _inheritedPositionalStateContainer; mutable osg::ref_ptr _renderStageLighting; - - + }; diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index 9d18cf1a1..acb3af417 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -311,6 +311,12 @@ class OSGUTIL_EXPORT SceneView : public osg::Object, public osg::CullSettings osgUtil::RenderStage* getRenderStageRight() { return _renderStageRight.get(); } const osgUtil::RenderStage* getRenderStageRight() const { return _renderStageRight.get(); } + /** search through any pre and post RenderStage that reference a Camera, and take a reference to each of these cameras to prevent them being deleted while they are still be used by the drawing thread.*/ + void collateReferencesToDependentCameras(); + + /** clear the refence to any any dependent cameras.*/ + void clearReferencesToDependentCameras(); + /** Set the draw buffer value used at the start of each frame draw. Note, overridden in quad buffer stereo mode */ void setDrawBufferValue( GLenum drawBufferValue ) { _camera->setDrawBuffer(drawBufferValue); } diff --git a/src/osgSim/LightPointNode.cpp b/src/osgSim/LightPointNode.cpp index 4089b3906..a4311d51e 100644 --- a/src/osgSim/LightPointNode.cpp +++ b/src/osgSim/LightPointNode.cpp @@ -200,11 +200,11 @@ void LightPointNode::traverse(osg::NodeVisitor& nv) } } - // search for a drawable in the RenderLead list equal to the attached the one attached to StateGraph user data + // search for a drawable in the RenderLeaf list equal to the attached the one attached to StateGraph user data // as this will be our special light point drawable. osgUtil::StateGraph::LeafList::iterator litr; for(litr = rg->_leaves.begin(); - litr != rg->_leaves.end() && (*litr)->_drawable.get()!=drawable; + litr != rg->_leaves.end() && (*litr)->_drawable!=drawable; ++litr) {} diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 248c061a0..3db0833ec 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -1350,7 +1350,7 @@ unsigned int RenderStage::computeNumberOfDynamicRenderLeaves() const } -void osgUtil::RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBufferObject* fbo) +void RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBufferObject* fbo) { if (fbo && fbo->isMultisample()) { @@ -1359,3 +1359,45 @@ void osgUtil::RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBuff } _resolveFbo = fbo; } + +void RenderStage::collateReferencesToDependentCameras() +{ + _dependentCameras.clear(); + + for(RenderStageList::iterator itr = _preRenderList.begin(); + itr != _preRenderList.end(); + ++itr) + { + itr->second->collateReferencesToDependentCameras(); + osg::Camera* camera = itr->second->getCamera(); + if (camera) _dependentCameras.push_back(camera); + } + + for(RenderStageList::iterator itr = _postRenderList.begin(); + itr != _postRenderList.end(); + ++itr) + { + itr->second->collateReferencesToDependentCameras(); + osg::Camera* camera = itr->second->getCamera(); + if (camera) _dependentCameras.push_back(camera); + } +} + +void RenderStage::clearReferencesToDependentCameras() +{ + for(RenderStageList::iterator itr = _preRenderList.begin(); + itr != _preRenderList.end(); + ++itr) + { + itr->second->collateReferencesToDependentCameras(); + } + + for(RenderStageList::iterator itr = _postRenderList.begin(); + itr != _postRenderList.end(); + ++itr) + { + itr->second->collateReferencesToDependentCameras(); + } + + _dependentCameras.clear(); +} diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index 6c8cfd8d7..b90997f9e 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -1728,3 +1728,17 @@ bool SceneView::getStats(Statistics& stats) return _renderStage->getStats(stats); } } + +void SceneView::collateReferencesToDependentCameras() +{ + if (_renderStage.valid()) _renderStage->collateReferencesToDependentCameras(); + if (_renderStageLeft.valid()) _renderStageLeft->collateReferencesToDependentCameras(); + if (_renderStageRight.valid()) _renderStageRight->collateReferencesToDependentCameras(); +} + +void SceneView::clearReferencesToDependentCameras() +{ + if (_renderStage.valid()) _renderStage->clearReferencesToDependentCameras(); + if (_renderStageLeft.valid()) _renderStageLeft->clearReferencesToDependentCameras(); + if (_renderStageRight.valid()) _renderStageRight->clearReferencesToDependentCameras(); +} diff --git a/src/osgViewer/Renderer.cpp b/src/osgViewer/Renderer.cpp index 1cc256da8..9240e4335 100644 --- a/src/osgViewer/Renderer.cpp +++ b/src/osgViewer/Renderer.cpp @@ -384,6 +384,11 @@ void Renderer::draw() if (sceneView && !_done) { + // since we are running the draw thread in parallel with the main thread it's possible to unreference Camera's + // that are still being used by this rendering thread, so to prevent this we'll take references to all these + // Camera's and the clear these references once we've completed the whole draw dispatch. + sceneView->collateReferencesToDependentCameras(); + if (_compileOnNextDraw) { compile(); @@ -485,6 +490,7 @@ void Renderer::draw() stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick)); } + sceneView->clearReferencesToDependentCameras(); } DEBUG_MESSAGE<<"end draw() "<