[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
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
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] Multi-view Performance Issue with Statesets
Drolet, Frederic wrote on 2010-03-12: 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! The color array is independent from the StateSet. It appears you are only using the StateSet to turn lighting off; if that is true, you could just create a single StateSet that turns lighting off and put it near the top of your scene graph. The color arrays and modifying them should not affect performance as much as the OpenGL state changes that come from many StateSets. -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