[osg-users] scene graph access in multithreaded mode

Robert Osfield robert.osfield at gmail.com
Thu Sep 4 02:09:02 PDT 2008


Hi Tugkan,

On Wed, Sep 3, 2008 at 9:56 AM, Tugkan Calapoglu <tugkan at vires.com> wrote:
> I am porting an application from OSG0.99 to latest SVN version.

Wow, climb aboard the time machine :-)

> I have two
> questions (both for CullThreadPerCameraDrawThreadPerContext mode):
>
> 1- Is it safe to make changes in the scene graph outside the frame call
> (without using update etc. callbacks )? Or is the only place where we have
> safe scene graph acess is inside a callback? Mailing list and source code
> reading made me think that outside the frame() should be safe but I am
> getting some crashes. Before delving into my own code I'd like that someone
> confirms this.

Modifying the scene graph outside of the frame call is safe in
SingleThreader, and CullDrawThreadPerCamera threading models as they
don't leave any threads active after the end of the
renderingTraversals() method (called from frame()).

With DrawThreadPerContext and CullThreadPerCamewraDrawThreadPerContext
the draw threads will still be active on completion of the
renderingTraversals(), so if you modifying drawables and state that
the thread is still reading from in the draw traversal you will end up
with problems - and potential crashes.  There is a standard mechanism
to deal with this issue - and that is the renderingTraversals() method
to block till all dynamic objects in the draw traversals have been
dispatched.  The way you tell the draw traversal that an drawable or
stateset will be modified dynamically is to set its data variance to
DYNAMIC.

   drawable->setDataVariance(osg::Object::DYNAMIC);
   stateset->setDataVariance(osg::Object::DYNAMIC);

This is mentioned in the "Quick Start Guide" book, as well as many
times on the osg-users mailing list so have a look through the
archives if you want more background reading.


> 2- Is it ok to change the global state set during rendering outside frame
> call? I have following code runing before frame() is called :
>
> osg::Camera* cam = getViewer()->getView(i)->getCamera();
> cam->getOrCreateStateSet()->clear();
> cam->getOrCreateStateSet()->setGlobalDefaults();
> ... And some other changes ...

Same requirement - if you are modifying the stateset then you'll need
to set its data variance to DYNAMIC.  For a StateSet that decorates
the whole scene graph you'll end you holding back the frame till the
whole scene graph is completed, so it won't have any performance
advantage over CullDrawThreadPerContext.  You can double buffer
objects to allow you to retain the STATIC data variance and keep the
threads overlapping, to do this you do:

osg::Camera* cam = getViewer()->getView(i)->getCamera();
cam->setStateSet() = new StateSet;  // this is where we just use a new
StateSet rather than modify the previous one
cam->getOrCreateStateSet()->setGlobalDefaults();
... And some other changes ...

The draw traversal takes a reference to the StateSet and Drawables so
it's safe to go an remove them from the scene graph outside the
frame() call, this isn't something makes then dynamic so you won't
need to set their data variance to DYNAMIC.

Robert.


Robert.



More information about the osg-users mailing list