[osg-users] Multi-view Performance Issue with Statesets
Hi everyone, I've seen a lot of threads on performance issues in the mailing list but none of them seemed to address my particular problem precisely, either because the problem description was vague or the replies were covering a matter far too vast to include everything in a single message. So I've decided to expose my problem and share my observations and potential solution. My goal here is to understand why it does what it does and maybe help some other users with similar problems. Here's my system configuration: Dell XPS, Intel Core2 Quad Q9300 @ 2.5 Ghz, 4 GB RAM, NVidia GeForce GTX 280. The application uses MFC classes (extended from the OSGViewerMFC exemple) and is run under Windows Vista 32-bit. So, I have this multi-view application with textured terrains generated from osgGIS. I eliminated all LODs to eliminate this factor in my performance comparison. On those terrains, we add road segments with a stateset: mGeometrie = new osg::Geometry; mGeometrie-setVertexArray(lListe); mGeometrie-addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,1)); mGeometrie-addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,1)); ((osg::DrawArrays*)mGeometrie-getPrimitiveSet(0))-setCount(lListe-size()); ((osg::DrawArrays*)mGeometrie-getPrimitiveSet(1))-setCount(lListe-size()); osg::ref_ptrosg::StateSet lStateSet = mGeometrie-getOrCreateStateSet(); lStateSet-setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::ref_ptrosg::Vec4Array lCouleur = new osg::Vec4Array; lCouleur-push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); mGeometrie-setColorArray(lCouleur); mGeometrie-setColorBinding(osg::Geometry::BIND_OVERALL); We also add a larger invisible road segment above to make things easier for the user to select a segment (the collision is detected in a visitor): osg::ref_ptrosg::Geometry lGeometrieSelection = new osg::Geometry; lGeometrieSelection-setVertexArray(lListeSelection); lGeometrieSelection-addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,1)); lGeometrieSelection-addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,1)); ((osg::DrawArrays*)lGeometrieSelection-getPrimitiveSet(0))-setCount(lListeSelection-size()); ((osg::DrawArrays*)lGeometrieSelection-getPrimitiveSet(1))-setCount(lListeSelection-size()); osg::ref_ptrosg::StateSet lStateset = lGeometrieSelection-getOrCreateStateSet(); osg::ref_ptrosg::Material lMateriel = dynamic_castosg::Material*(lStateset-getAttribute(osg::StateAttribute::MATERIAL)); if (!lMateriel) lMateriel = new osg::Material; lMateriel-setTransparency(osg::Material::FRONT_AND_BACK, 1.0f); lStateset-setAttributeAndModes( lMateriel, osg::StateAttribute::PROTECTED | osg::StateAttribute::ON); lStateset-setRenderingHint(osg::StateSet::TRANSPARENT_BIN); osg::ref_ptrosg::Vec4Array lCouleurSelection = new osg::Vec4Array; lCouleurSelection-push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); lGeometrieSelection-setColorArray(lCouleurSelection); lGeometrieSelection-setColorBinding(osg::Geometry::BIND_OVERALL); Now, I noticed a lot of things while doing my performance experiments: - First of all: Statesets seem to affect performance drastically and the code above generates a lot of them. I have 4 views sharing a scene containing 4 terrain with 15 segments each. Without the road segments, I reach 56 FPS with 237 statesets, 512K vertices and 970K primitives. When I add the road segments, I drop to 24 FPS with 781 statesets, 544K vertices and +1M primitives. - Primitives and vertices count also affect performance but the effect is less significant. Indeed, I can put 5 terrains without the road segments and I'm still at 55 FPS with only 257 statesets, 625K vertices and +1.2M primitives. I drop to 30 FPS with 514 statesets, 1.2M vertices and 2.4M primitives (10 terrains with no road segments). - With a single view, the stateset effect is far less significant. Maybe my multi-view is not set properly? - The FOV (set in the camera's projection matrix) also seem to affect performance negatively and worsen the stateset effect. For now, I set it to 170 degrees (to be able to cull everything for CAVE rendering) but I think I will need to optimize this value with tracker coordinates. I remember Robert saying that we should avoid independent statesets. This raises a lot of questions since I don't fully understand this functionality yet... For instance, what is the typical amount of statesets in a commercial application? How can we combine statesets for multiple objects potentially in different states from each others? Finally, do you have any idea how I could solve my particular selection problem without having to add more statesets for the invisible but larger
Re: [osg-users] Multi-view Performance Issue with Statesets
Let's say I want to change the color of my road segment (when selected for instance). We're currently doing this modification that way: osg::Vec4Array* lCouleur = (osg::Vec4Array*)(mGeometrie-getColorArray()); *(lCouleur-begin()) = pCouleur; mGeometrie-dirtyDisplayList(); From what you're saying, I guess we should create a different stateset for every color instead of a stateset for every segment? Maybe I should ask first if the color is indeed part of the stateset anyway! If not, we could reduce the stateset count even more! Thanks! Frederic Drolet, M. Sc. Computing Solutions and Experimentations | Solutions informatiques et expérimentations Systems of Systems | Systèmes de systèmes DRDC Valcartier | RDDC Valcartier 2459, boul. Pie-XI North Quebec, Quebec G3J 1X5 CANADA Phone | Téléphone: (418) 844-4000 ext : 4820 Fax | Télécopieur: (418) 844-4538 E-mail | Courriel: frederic.dro...@drdc-rddc.gc.ca Web : www.valcartier.drdc-rddc.gc.ca -Original Message- From: osg-users-boun...@lists.openscenegraph.org [mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of Thrall, Bryan Sent: Friday, March 12, 2010 10:39 AM To: OpenSceneGraph Users Subject: Re: [osg-users] Multi-view Performance Issue with Statesets Drolet, Frederic wrote on 2010-03-12: osg::ref_ptrosg::StateSet lStateSet = mGeometrie- getOrCreateStateSet(); lStateSet-setMode(GL_LIGHTING, osg::StateAttribute::OFF); OpenGL performance is very sensitive to state changes, so it is a good idea to minimize them as much as possible. OSG groups Drawables with the same state as part of this (the exception is transparent drawables that require a certain ordering to render correctly, so they can't be grouped), but it just compares the StateSet pointers rather than a (much more expensive) comparison of what OpenGL state the StateSet pointers represent. Therefore, if you have a bunch of StateSets that are identical, like you seem to have, it is a really good idea to just use the same StateSet object everywhere you need it, rather than create a new instance every time. HTH, -- Bryan Thrall FlightSafety International bryan.thr...@flightsafety.com ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] CompositeViewer context cleanup and missing textures
Hello J.P., I see it's a good thing this thread got my attention! I have similar missing texture issues in another application that creates and deletes window contexts applied to viewer slaves (also created and deleted dynamically). Here's the way we create our textures: osg::ref_ptrosg::Texture2D lTex = new osg::Texture2D; lTex-setDataVariance(osg::Object::DYNAMIC); // load an image by reading a file: CString lIconFileName = (...)TextureFilename + .png; osg::Image* lIconImage = osgDB::readImageFile(lIconFileName.GetBuffer()); // Assign the texture to the image we read from file: lTex-setImage(lIconImage); // Make sure the texture is not unreferenced in memory after it's applied in GL states lTex-setUnRefImageDataAfterApply(false); Unfortunately, my understanding of OpenGL is relatively limited but I know this last line of code is crucial for dynamical views handling to maintain the texture in user memory for later access. However, even with this, it happens sometimes that the texture disappear after a few create and delete views operations (sometimes, the textures is on a view but not on another!). It happens most of the time with objects loaded from file. Since we don't have direct access to the textures, we can't make the call to setUnRefImageDataAfterApply(). Would there be another way? Now, as for the modified CompositeViewer example, I tried it on Windows Vista and it simply crashes the first time I hit ESC or the X button. In fact, the problem occurs during the second call to viewer.run(). First, I simply tried to add a sleep before the viewer's deletion to wait for potential asynchronous cleanup stuff after the call to the viewer's run() method but it didn't work. Then, I did a little debug job to find out that the second time the viewer is created, the application crashes during the rendering traversal of the first call to frame() in the run thread loop. More precisely the application crashes in osgUtil::ScreneView::init() the first time the cull_draw operation is launched. Here's the call stack: ntdll.dll!778f9a94() [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] ntdll.dll!778f92c4() kernel32.dll!76a5e87b() nvoglv32.dll!69638b8f() nvoglv32.dll!695a15d0() osg55-osgd.dll!osg::getGLVersionNumber() Line 48 + 0xd bytes C++ osg55-osgd.dll!osg::isGLExtensionOrVersionSupported(unsigned int contextID=0, const char * extension=0x5ac7a277, float requiredGLVersion=3.4028235e+038) Line 82 + 0x5 bytes C++ osg55-osgd.dll!osg::isGLExtensionSupported(unsigned int contextID=0, const char * extension=0x5ac7a277) Line 73 + 0x17 bytes C++ osg55-osgUtild.dll!osgUtil::SceneView::init() Line 312 + 0x2d bytes C++ osg55-osgUtild.dll!osgUtil::SceneView::draw() Line 1026 + 0x1d bytes C++ osg55-osgViewerd.dll!osgViewer::Renderer::cull_draw() Line 588 + 0xf bytes C++ osg55-osgViewerd.dll!osgViewer::Renderer::operator()(osg::GraphicsContext * context=0x023591b0) Line 689 + 0xf bytes C++ osg55-osgd.dll!osg::GraphicsContext::runOperations() Line 688 + 0x33 bytes C++ osg55-osgViewerd.dll!osgViewer::ViewerBase::renderingTraversals() Line 772 + 0x15 bytesC++ osg55-osgViewerd.dll!osgViewer::ViewerBase::frame(double simulationTime=1.7976931348623157e+308) Line 609 + 0xf bytes C++ osg55-osgViewerd.dll!osgViewer::ViewerBase::run() Line 581 + 0x1b bytesC++ osg55-osgViewerd.dll!osgViewer::CompositeViewer::run() Line 233 C++ osgcompositeviewerd.exe!main(int argc=3, char * * argv=0x02330ed8) Line 311 + 0xf bytesC++ osgcompositeviewerd.exe!__tmainCRTStartup() Line 582 + 0x19 bytes C osgcompositeviewerd.exe!mainCRTStartup() Line 399 C kernel32.dll!76a94911() ntdll.dll!778de4b6() ntdll.dll!778de489() I forced the single thread mode (the only thing on the command line was the filename of my 3D model). By the way, is there a better solution to wait for the viewer completion after the run() method? What OS are you using? Maybe I should try on XP to see if it does the same thing. Hope we can help each other! Cheers, Frederic Drolet, M. Sc. Computing Solutions and Experimentations | Solutions informatiques et expérimentations Systems of Systems | Systèmes de systèmes DRDC Valcartier | RDDC Valcartier 2459, boul. Pie-XI North Quebec, Quebec G3J 1X5 CANADA Phone | Téléphone: (418) 844-4000 ext : 4820 Fax | Télécopieur: (418) 844-4538 E-mail | Courriel: frederic.dro...@drdc-rddc.gc.ca Web : www.valcartier.drdc-rddc.gc.ca -Original Message- From: osg-users-boun...@lists.openscenegraph.org [mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of J.P. Delport Sent:
Re: [osg-users] Texture loading problem
Hello Aydin, See current thread CompositeViewer context cleanup and missing textures for real-time solution! Cheers, Frederic Drolet, M. Sc. Computing Solutions and Experimentations | Solutions informatiques et expérimentations Systems of Systems | Systèmes de systèmes DRDC Valcartier | RDDC Valcartier 2459, boul. Pie-XI North Quebec, Quebec G3J 1X5 CANADA Phone | Téléphone: (418) 844-4000 ext : 4820 Fax | Télécopieur: (418) 844-4538 E-mail | Courriel: frederic.dro...@drdc-rddc.gc.ca Web : www.valcartier.drdc-rddc.gc.ca -Original Message- From: osg-users-boun...@lists.openscenegraph.org [mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of Aydin Uluc Sent: November-24-09 9:50 AM To: osg-users@lists.openscenegraph.org Subject: [osg-users] Texture loading problem Hi, My first actual post here:). Just started to learn OSG and I have a scene that I load into OSG and everything runs fine. But after loading the scene the 2nd time the textures won't load. Everything is white. Please let me know if you need more info. Anyone else experienced this problem or someone can help me regarding this problem? ... Thank you! Cheers, Aydin -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=20253#20253 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Would someone be willing to help me diagnose aperformance issue?
Hello Frank, You should try to create the 52 models cache outside the rendering tree (in a separate list or a distinct tree detached from the camera). Even if the visibility is turned off, I think the rendering visitors (update, cull, etc.) are still browsing the whole tree. Also, don't forget that if you full your RAM with all the cached models, you'll have to use virtual memory on the hard drive which is much less efficient. As for the threading model, I don't think this should affect performance much if you have only one display window. If you have multiple rendering context, it's very important to use multithreading if you wand reasonable performance. You can change the threading model through the osgViewer::Viewer::setThreadingModel() method. Hope this helps! Frederic Drolet, M. Sc. Computing Solutions and Experimentations | Solutions informatiques et expérimentations Systems of Systems | Systèmes de systèmes DRDC Valcartier | RDDC Valcartier 2459, boul. Pie-XI North Quebec, Quebec G3J 1X5 CANADA Phone | Téléphone: (418) 844-4000 ext : 4820 Fax | Télécopieur: (418) 844-4538 E-mail | Courriel: frederic.dro...@drdc-rddc.gc.ca Web : www.valcartier.drdc-rddc.gc.ca http://www.valcartier.drdc-rddc.gc.ca From: osg-users-boun...@lists.openscenegraph.org [mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of Philip Lowman Sent: November-10-09 12:52 PM To: osg-users@lists.openscenegraph.org Subject: Re: [osg-users] Would someone be willing to help me diagnose aperformance issue? Slowly minimize the differences between the slow machine and the fast machine until the problem goes away. When it does, you have isolated the problem. Also bear in mind it could be the machine itself (hardware, drivers, etc.) On Nov 10, 2009 12:42 PM, Frank Sullivan knarf.navil...@gmail.com wrote: Hello, I have two applications, both of which are displaying basically the same scene. One application runs at 230+ fps while the other runs at about 45 fps. I'm trying to figure out what is causing this performance difference. Using high-precision timers, I've been able to determine that the difference occurs somewhere in the rendering of the scene graph, but I'm not 100% sure where. I have a couple of ideas, but each will take some amount of time to investigate, and so I was hoping someone might be able to lead me towards the most-correct answer. The first idea I had concerns differences in how the scene graphs are structured in each application. The quick app works simply by loading the three models that it needs (from FLT files, so these 'models' are in fact complex sub-graphs) and attaches them to the root node, and sets that root node as the scene data. The slow app loads every model that could possibly ever be used (52 in all, and again each 'model' could actually be a complex sub-graph). These 52 nodes are then attached to the root, and their visibility is turned off by setting their node mask to 0. Then, if the user of the application wants to see a model, the app will copy the node (and all of it's children) and then add this copy to the scene root group, with the visibility turned on. This way, if the user of the app wants to populate the scene with many instances of the same model, they can do so, because each time they do it, a separate copy of the node is made. I realize that there are a lot of things that can be done to make the slow app more memory-efficient. For instance, it could use lazy loading to load a model only when it is needed (although this may cause a noticeable delay, but that would probably be fine). And if the user wants to see several instances of this model, this could be accomplished without copying the model's entire subgraph. Instead, we could simply create a new matrix transform, and add THAT to the root, and add the model's node as a child of this new matrix transform (at which point, the model's node will have more than one Matrix Transform parent). However, these issues seem to pertain more towards memory efficiency than rendering efficiency, so I'm not sure if this is going to solve my immediate problem (although it is almost certainly something I will implement later on). Related to this, I was wondering if anyone had an explanation as to what the Camera / View statistics referred to. I read the Quick Start Guide, and it had excellent information about the Event/Update/Cull/Draw/GPU chart at the top of the statistics screen, but I'm not exactly sure what the statistics in the Camera / View windows refer to. For instance, does the Vertices stat refer to the total number of vertices in all of the drawables, whether those drawables are visible or not? The reason I ask is that, in terms of these statistics, both the Quick App and the Slow App have nearly-identical numbers in the
Re: [osg-users] Texture missing when adding slaves dynamically to osgViewer
Hello, I tried with Texture::setUnRefImageDataAfterApply(false) and it works well. However, as I read about this, texture memory is now duplicated (once in OpenGL and once in OSG). Isn't there a way to do the same thing in OpenGL by sharing the contexts or something like that? As I said, I tried to share a single context in the traits configuration but it didn't work. For now, our application doesn't use too much memory but this could become a problem when we'll be generating visual data from our database! As for the osgUtil::Optimizer, we're not using it anywhere in our code... Is it called by the Viewer class during initialization or something? Would there be another way to enable texture sharing for dynamically created rendering contexts while optimizing memory usage? Thanks again for your help! Frédéric Drolet -Original Message- From: osg-users-boun...@lists.openscenegraph.org [mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of Robert Osfield Sent: October-08-09 5:01 PM To: OpenSceneGraph Users Subject: Re: [osg-users] Texture missing when adding slaves dynamically toosgViewer Hi Frederic, If you are creating new graphics contexts and applying and old scene graph to it then you can't use the Texture::setUnRefImageDataAfterApply(true) feature of osg::Texture as this will discard the imagery once it's applied to all the graphics contexts that it knows about. By default the osgUtil::Optimizer will switch this on to save memory, so try not calling the Optimizer to see if makes a difference. It's possible that the original database also has this options set, but for most databases it'll be off, which is the default. Robert. On Thu, Oct 8, 2009 at 8:21 PM, Drolet, Frederic frederic.dro...@drdc-rddc.gc.ca wrote: Hello, I'm having trouble with textures on slave cameras added to an osgViewer. Textures won't appear if I add the slaves after a first call to osgViewer::frame(). My application is composed of a rendering thread calling osgViewer::frame() every 15 ms (for a 60 Hz framerate) and a main thread handling windows and menus interactions (using MFC on Windows). One of those interactions is to add and remove camera slaves on the go (adding a projection and camera offset for multiple points of view). Here's the steps I follow to add a slave camera: · Pause my rendering thread calling osgViewer::frame() and wait for it to be idle; · Call osgViewer::stopThreading() to make sure the last frame is done drawing; · Create a child window with its own graphics context; · Add a slave to osgViewer using the newly created window handle (each slave camera uses its own osg::GraphicsContext object); · Call osgViewer::realize() to reinitialize the viewer and start threading again; · Unpause my rendring thread which starts calling osgViewer::frame() again. I use a similar approach to destroy slaves. Everything works fine except for the textures which are not displayed on the slave windows (but I can see the primitives). Note that if I add slaves before the first call to osgViewer::frame(), textures are ok. But removing and adding them again makes the textures disappear. I tried all the threading models in osgViewer, I also tried to share the master context in the osg::GraphicsContext::Traits object of every slave. None of those solutions is working. My comprehension of OpenGL state sets is limited so I'm probably missing something here. What am I doing wrong? Is adding slaves dynamically to an osgViewer even possible? Thanks for your help! Frederic Drolet, M. Sc. Computing Solutions and Experimentations | Solutions informatiques et expérimentations Systems of Systems | Systèmes de systèmes DRDC Valcartier | RDDC Valcartier 2459, boul. Pie-XI North Quebec, Quebec G3J 1X5 CANADA Phone | Téléphone: (418) 844-4000 ext : 4820 Fax | Télécopieur: (418) 844-4538 E-mail | Courriel: frederic.dro...@drdc-rddc.gc.ca Web : www.valcartier.drdc-rddc.gc.ca ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
[osg-users] Texture missing when adding slaves dynamically to osgViewer
Hello, I'm having trouble with textures on slave cameras added to an osgViewer. Textures won't appear if I add the slaves after a first call to osgViewer::frame(). My application is composed of a rendering thread calling osgViewer::frame() every 15 ms (for a 60 Hz framerate) and a main thread handling windows and menus interactions (using MFC on Windows). One of those interactions is to add and remove camera slaves on the go (adding a projection and camera offset for multiple points of view). Here's the steps I follow to add a slave camera: · Pause my rendering thread calling osgViewer::frame() and wait for it to be idle; · Call osgViewer::stopThreading() to make sure the last frame is done drawing; · Create a child window with its own graphics context; · Add a slave to osgViewer using the newly created window handle (each slave camera uses its own osg::GraphicsContext object); · Call osgViewer::realize() to reinitialize the viewer and start threading again; · Unpause my rendring thread which starts calling osgViewer::frame() again. I use a similar approach to destroy slaves. Everything works fine except for the textures which are not displayed on the slave windows (but I can see the primitives). Note that if I add slaves before the first call to osgViewer::frame(), textures are ok. But removing and adding them again makes the textures disappear. I tried all the threading models in osgViewer, I also tried to share the master context in the osg::GraphicsContext::Traits object of every slave. None of those solutions is working. My comprehension of OpenGL state sets is limited so I'm probably missing something here. What am I doing wrong? Is adding slaves dynamically to an osgViewer even possible? Thanks for your help! Frederic Drolet, M. Sc. Computing Solutions and Experimentations | Solutions informatiques et expérimentations Systems of Systems | Systèmes de systèmes DRDC Valcartier | RDDC Valcartier 2459, boul. Pie-XI North Quebec, Quebec G3J 1X5 CANADA Phone | Téléphone: (418) 844-4000 ext : 4820 Fax | Télécopieur: (418) 844-4538 E-mail | Courriel: frederic.dro...@drdc-rddc.gc.ca mailto:frederic.dro...@drdc-rddc.gc.ca Web : www.valcartier.drdc-rddc.gc.ca http://www.valcartier.drdc-rddc.gc.ca ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org