Added collateReferencesToDependentCameras() and clearReferencesToDependentCameras() methods into RenderStage and SceneView, and use

of these methods in src/osgViewer/Renderer.cpp to make sure that the draw thread keeps references to all in scene graph Cameras
that are being used by the drawing threads, to keep the Camera's alive even when the main thread removes these Cameras from the scene graph.
This commit is contained in:
Robert Osfield
2009-06-05 19:05:37 +00:00
parent 482a18b9f2
commit aa69137fb8
6 changed files with 84 additions and 8 deletions

View File

@@ -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<RenderStage> > RenderStageOrderPair;
typedef std::list< RenderStageOrderPair > RenderStageList;
typedef std::vector< osg::ref_ptr<osg::Camera> > Cameras;
bool _stageDrawnThisFrame;
RenderStageList _preRenderList;
RenderStageList _postRenderList;
Cameras _dependentCameras;
// viewport x,y,width,height.
osg::ref_ptr<osg::Viewport> _viewport;
@@ -271,8 +280,7 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
mutable osg::Matrix _inheritedPositionalStateContainerMatrix;
mutable osg::ref_ptr<PositionalStateContainer> _inheritedPositionalStateContainer;
mutable osg::ref_ptr<PositionalStateContainer> _renderStageLighting;
};

View File

@@ -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); }

View File

@@ -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)
{}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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() "<<this<<std::endl;