So basically I need to reformulate the question: Can we use the update operations to induce more parallelism?
P.S. While your approach might not fit anyone's need, is there some code for an example which might be shared with the community? My biggest concern with OSG right now is performance, or the fact that performance loss is obfuscated.
First of all, I didn't know that cull and draw traversal can execute in parallel on a single scene. I always thought that cull and draw can only execute sequential (serial) in all available threading models. Anyway, what I know for sure is that update and draw traversal can indeed execute in parallel within some threading models, and that is the reason why we need DYNAMIC variance, to tell drawing thread it must process dynamic elements first, and then immediately allow execution of the update traversal in a main thread while STATIC elements are still being rendered in a draw thread. I also suspect that next frame cannot start before all the static+dynamic elements are rendered. If I'm correct on this one, then few DYNAMIC elements should not affect frame rate at all, because there is plenty of time to do the processing while STATIC elements are still being rendered.
Sebastian, here is my understanding.
StateSets and Drawables must be marked as DYNAMIC is you plan to change them. That's because they are used by the rendering stage, which can overlap the next frame's update.
Everything else (scene graph structure, etc.) is safe to change during the Update traversal/callbacks.
Hope this helps.
Thanks for the explanation. I'm still puzzled by the question which elements can be updated in the update-phase without setting them to dynamic. I always was under the impression, that the update is performed before cull/draw are actually executed.
Right now I need some thread safe "time slot" to change the scene graph in terms of inserting nodes, updating transforms etc. I guess it is totally okay to do this in the update callback/operation.
But for changes to images, text, an arrays of drawables I need to set them to DYNAMIC if I understood you correctly. So basically what I got is, that I could put the draw of those elements as far to beginning of the draw as possible.
As for the double buffering: Can it be done at drawable level? Like swapping the front/back drawable back and forth, effectively doubling the geometry/image space needed?
Thanks for your insights. I know the biggest concern is the structure of the scene-graph but at some point one will get stuck or will simply have to live with the sheer number of drawables spit out by external tools (I also cannot merge certain geometries due to additional attributes that need to be per-primitive)
In my scenario I have a extremely high number of nodes in the scene, which need to stay where they are in terms of structure. Let's assume that I have purely static scene. It will perform with a decent framerate (100Hz for instance).
As soon as I add some HUD-Camera containing osgText::Text nodes it will almost drop to 50Hz, as the cull and draw are no longer able to execute in parallel, by simply adding one HUD-text node.
Right now I add them as post-render camera/child of the main camera, so maybe the problem is my camera arrangement.
Apart from this, there might be the use case, where the scene is mainly static with some elements drawn on top, which are dynamic, which cause the same frame-rate degradation.
In my case, the scene loaded with the osgviewer has double the frame-rate from my viewer, which adds some dynamic text on top, which is not really satisfying. If you want some example illustrating this, I can totally provide some as a "DON'T DO THIS" example.
I'm simply was wondering, why the update overlaps the draw/cull. I was under the impression, that cull/draw can be parallelized, as long as the data rendered is updated in the update phase. But of course, there are changes which need to sent down the pipe.
I guess the optimizations I'm looking for are simply restrained by the way OpenGL works and might be relaxed with Vulkan etc