Thread: [Algorithms] Statebuffering etc
Brought to you by:
vexxed72
From: Stefan M. <me...@sk...> - 2002-08-28 10:00:51
|
Hi, I'm currently banging my head against the wall and I'm hoping that it makes my mind clear ;) I want a practical way to buffer the current states in my 3D engine. I check wether or not a given state is already set when doing a SetState() call but this is not enough. In fact, the states can be set by different parts within the engine : I have a 2D output that configures it's states and I have my mesh output that configures the states depending on the way it has to be rendered. Now, my current approach is "rely on a given preset state and only change what is needed for me to be rendered as should". The result is that Mesh A alters states on which Mesh B relies on as "set to default value". There are 2 alternatives : a) Force the meshes to set *all* states that they need and not only those that alter from a "default" status. b) Create a push/pop state something, that pushes the current states onto a stack, copies the states and the allows to alter them. It would reset the states that have been altered on a pop. While a) makes a lot of SetState calls that are filtered since it checks wether or not the state already has the right value, it results in a lot of unnecessary SetState calls. b) would result in much less filtered SetState calls but there's an additional cost for the push/pop. I don't think that b) is applicable if there are a lot of rendered objects (in my case up to 2/3k) since the push/pop cost would pull down the performance. a) is critical since you might *forget* to set a needed state. What is your approach to this problem and what are the alternatives ? Kind regards, Stefan |
From: U2 P. T. <u2...@fr...> - 2002-08-28 11:26:50
|
Personnaly i use the SceneGraph as a state manager. Yes because if you consider that some Node of your Graph can set GPU attributes ( or states ) you have an efficient system who can manage all configuration and have minimum overhead. imagine somehting like that : NODEPushTexture1() is the parent node and Shape1 and Shape2 or meshes ( or VertexBuffer/IndexBuffer states ) who are node placed under this parent. Then when you walk though this Graph you will apply only Texture1 for Shape1 and Shape2 who need this texture. whith "Special" Node who can managed more complex state you can introduce the notion of Shaders in a very efficient way. AS Shader are node who will walk though his children several time with differents states setted for each time. i hope this will help you even if my english skill is very bad :)) see ya! ============================ -- U2 / PoPsY TeAm ---------------------- -- http://www.popsyteam.org --------- ============================ ----- Original Message ----- From: "Stefan Maton" <me...@sk...> To: "Algorithms" <GDA...@li...> Sent: Wednesday, August 28, 2002 12:01 PM Subject: [Algorithms] Statebuffering etc > Hi, > > I'm currently banging my head against the wall > and I'm hoping that it makes my mind clear ;) > > I want a practical way to buffer the current > states in my 3D engine. I check wether or not > a given state is already set when doing a > SetState() call but this is not enough. In > fact, the states can be set by different > parts within the engine : I have a 2D output > that configures it's states and I have my > mesh output that configures the states > depending on the way it has to be rendered. > > Now, my current approach is "rely on a given > preset state and only change what is needed > for me to be rendered as should". The result > is that Mesh A alters states on which Mesh > B relies on as "set to default value". > > There are 2 alternatives : > > a) Force the meshes to set *all* states > that they need and not only those that alter > from a "default" status. > > b) Create a push/pop state something, that > pushes the current states onto a stack, copies > the states and the allows to alter them. It would > reset the states that have been altered on a pop. > > While a) makes a lot of SetState calls that are > filtered since it checks wether or not the state > already has the right value, it results in a lot > of unnecessary SetState calls. > > b) would result in much less filtered SetState > calls but there's an additional cost for the > push/pop. > > I don't think that b) is applicable if there are > a lot of rendered objects (in my case up to 2/3k) > since the push/pop cost would pull down the performance. > > a) is critical since you might *forget* to set a > needed state. > > What is your approach to this problem and what are > the alternatives ? > > Kind regards, > Stefan > > > > ------------------------------------------------------- > This sf.net email is sponsored by: Jabber - The world's fastest growing > real-time communications platform! Don't just IM. Build it in! > http://www.jabber.com/osdn/xim > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_id=6188 > |
From: Jim O. <j.o...@cr...> - 2002-08-28 11:51:12
|
Hi, > Personnaly i use the SceneGraph as a state manager. > Yes because if you consider that some Node of your Graph can set GPU > ... > walk though his children several time with differents states setted for each > time. While this seems very elegant at first, I've found that using the scenegraph in such way can quickly amount to very complicated code, because there is just so many different types of nodes for different things - specially if you also include things that are not related to rendering. Also, IMHO parent-child relations such as MaterialNode | +- ModelNode are counter-intuitive. Conceptually, they just don't make any sense. A model *is* not a child of a material, a model *has* one or more materials applied to it. But I suppose we're straying from the subject of the original thread here... Jim Offerman Crevace Games www.crevace.com www.jimofferman.nl |
From: U2 P. T. <u2...@fr...> - 2002-08-28 13:24:44
|
----- Original Message ----- From: "Jim Offerman" <j.o...@cr...> Cc: <gda...@li...> Sent: Wednesday, August 28, 2002 1:51 PM Subject: Re: [Algorithms] Statebuffering etc > Hi, > > > Personnaly i use the SceneGraph as a state manager. > > Yes because if you consider that some Node of your Graph can set GPU > > ... > > walk though his children several time with differents states setted for each > > time. > > While this seems very elegant at first, I've found that using the > scenegraph in such way can quickly amount to very complicated code, > because there is just so many different types of nodes for different > things - specially if you also include things that are not related to > rendering. > > Also, IMHO parent-child relations such as > > MaterialNode > | > +- ModelNode > > are counter-intuitive. Conceptually, they just don't make any sense. > A model *is* not a child of a material, a model *has* one or more > materials applied to it. > > But I suppose we're straying from the subject of the original thread > here... > > Jim Offerman > Crevace Games > www.crevace.com > > www.jimofferman.nl Yes you're right if you includes Matrix transformation into your SceneGraph with Shaders Node it will be unusefull but i solve the problem with that ! Transformation Hierarchy and so on are in an another graphs ( the Hierrachy graph ). and my "SceneGraph" only apply Attribute on the GPU ( like lights, renderstat, Vertex buffer, Pixel Shaders etc.. ) and i think it's a good approch because it's coherent to have something like that: LightNode + | +--- ShaderNode1 | + | | | +-- InstanceMesh1 | | | +-- InstanceMesh2 | +----- ShaderNode2 + | +---InstanceMesh1 and the InstanceMesh can be subdivided into this little Graph PushMeshMatrixNode + | +----PushVertexBufferNode etc... and the PushMeshMatrixNode have a reference of a Matrix in the HierachyGraph. i don't reason in term of model and material in the graph but in term of Attribute who can be pushed or poped for a Context. ( a model is only a VertexBuffer who can be treated as a Texture or a Light by the system ). ============================ -- U2 / PoPsY TeAm ---------------------- -- http://www.popsyteam.org --------- ============================ |
From: Richard B. <ri...@cr...> - 2002-08-28 15:07:24
|
We use a simplified system where almost off of the interesting states are expressed as enums that get or'ed together, we then xor the requested state with the current state and optimise for those changes. We have tried defering the change until render time to remove completely redundant ones, but that wasn't necessary. -----Original Message----- From: gda...@li... [mailto:gda...@li...]On Behalf Of Stefan Maton Sent: 28 August 2002 11:02 To: Algorithms Subject: [Algorithms] Statebuffering etc Hi, I'm currently banging my head against the wall and I'm hoping that it makes my mind clear ;) I want a practical way to buffer the current states in my 3D engine. I check wether or not a given state is already set when doing a SetState() call but this is not enough. In fact, the states can be set by different parts within the engine : I have a 2D output that configures it's states and I have my mesh output that configures the states depending on the way it has to be rendered. Now, my current approach is "rely on a given preset state and only change what is needed for me to be rendered as should". The result is that Mesh A alters states on which Mesh B relies on as "set to default value". There are 2 alternatives : a) Force the meshes to set *all* states that they need and not only those that alter from a "default" status. b) Create a push/pop state something, that pushes the current states onto a stack, copies the states and the allows to alter them. It would reset the states that have been altered on a pop. While a) makes a lot of SetState calls that are filtered since it checks wether or not the state already has the right value, it results in a lot of unnecessary SetState calls. b) would result in much less filtered SetState calls but there's an additional cost for the push/pop. I don't think that b) is applicable if there are a lot of rendered objects (in my case up to 2/3k) since the push/pop cost would pull down the performance. a) is critical since you might *forget* to set a needed state. What is your approach to this problem and what are the alternatives ? Kind regards, Stefan ------------------------------------------------------- This sf.net email is sponsored by: Jabber - The world's fastest growing real-time communications platform! Don't just IM. Build it in! http://www.jabber.com/osdn/xim _______________________________________________ GDAlgorithms-list mailing list GDA...@li... https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=6188 |
From: Jon W. <hp...@mi...> - 2002-08-28 18:42:14
|
> a) Force the meshes to set *all* states > that they need and not only those that alter > from a "default" status. I do this. Specifically, I end up bundling most state into a "material" object, and then ask the material to render geometry. The material will turn around and ask the hardware renderer to configure state based on itself, and then submit geometry. This works well. Especially if you let the hardware renderer poke at the material directly, in which case the "configure()" function looks something like: HwRenderer::configure( Material & m ) { if( m.diffuseTexture != curMaterial.texture ) { applyDiffuseTexture( m.diffuseTexture ); } if( m.blendFunc != curMaterial.blendFunc ) { applyBlendFunc( m.blendFunc ); } ... } At this level, there's no superfluous "setstate" calls, as the "state" is bundled into the material object. The material object, in turn, implements a pure virtual interface, which is what external users see, and the HwRenderer acts as a factory of concrete materials, so it's kosher for HwRenderer to poke at the implementation internals (there's actually a little more jiggering going on to turn the abstract Material interface into a HwMaterial implementation reference, but you get the idea). I don't like the idea of restoring a default state, because that results in superfluous state changes. Even if they don't end up being passed into the hardware layer, it just seems un-clean and un-necessary. Assuming you have perfect coverage in your material state management, this approach leads to the minimum necessary hardware calls (assuming you sort on materials before issuing actual render requests). Cheers, / h+ |
From: Stefan M. <me...@sk...> - 2002-08-28 20:47:14
|
> At this level, there's no superfluous "setstate" calls, as the > "state" is bundled into the material object. The material object, > in turn, implements a pure virtual interface, which is what > external users see, and the HwRenderer acts as a factory of > concrete materials, so it's kosher for HwRenderer to poke at the > implementation internals (there's actually a little more jiggering > going on to turn the abstract Material interface into a HwMaterial > implementation reference, but you get the idea). I get the idea and I think that's what I will stick to since it's almost what I have implemented... I've taken a look at the other solutions that have been discussed but they have all the same result : Send all necessary state changes through a in between layer that handles un-necessary state changes and don't look at the calls that could be skipped. I like the idea if pure virtual interfaces since this is what our engine is based upon. Unfortunately this implies that the user is able to implement the interface himself and pass the implementation as (in our example) the material. We have a GetInterface() function that takes a 4 byte identifier to return a special interface (ie. an implementation). I could rely on this to "force" the engine to only use "in-engine" implementation of the interfaces. > > I don't like the idea of restoring a default state, because that > results in superfluous state changes. Even if they don't end up > being passed into the hardware layer, it just seems un-clean and > un-necessary. Assuming you have perfect coverage in your material > state management, this approach leads to the minimum necessary > hardware calls (assuming you sort on materials before issuing actual > render requests). The un-necessary state calls are what led me to ask this question. Unfortunately this leads to solution a) that has been described in my first mail. Kind regards, Stefan |
From: Jim O. <j.o...@cr...> - 2002-08-29 05:42:37
|
Hey, > We have a GetInterface() function that takes a 4 byte identifier > to return a special interface (ie. an implementation). I could > rely on this to "force" the engine to only use "in-engine" > implementation of the interfaces. Why don't you just use a dynamic_cast? I.e.: void HwRenderSystem::SetMaterial(Material *material) { HwMaterial *hwMaterial = dynamic_cast<HwMaterial *>(material); if (hwMaterial) { ... } } Clean and simple IMHO. Jim Offerman Crevace Games www.crevace.com |
From: Stefan M. <me...@sk...> - 2002-08-29 08:44:02
|
> Hey, > > > We have a GetInterface() function that takes a 4 byte identifier > > to return a special interface (ie. an implementation). I could > > rely on this to "force" the engine to only use "in-engine" > > implementation of the interfaces. > > Why don't you just use a dynamic_cast? I.e.: > > void HwRenderSystem::SetMaterial(Material *material) > { > HwMaterial *hwMaterial = dynamic_cast<HwMaterial *>(material); > > if (hwMaterial) > { > ... > } > } To use dynamic_cast you must enable RTTI and that sucks down the performance quite a lot... Stefan |
From: Jim O. <j.o...@cr...> - 2002-08-29 09:15:13
|
Stefan wrote: > To use dynamic_cast you must enable RTTI and that sucks down > the performance quite a lot... Just out of curiousity: Is that last part an opinion or a fact? I haven't profiled the cost of dynamic_cast, but I also haven't noticed any significant slowdowns since I switched from using homebrew QueryInterface like methods to doing dynamic casts in the right places... Jim Offerman Crevace Games www.crevace.com www.jimofferman.nl |
From: Stefan M. <me...@sk...> - 2002-08-29 09:44:27
|
> Stefan wrote: > > To use dynamic_cast you must enable RTTI and that sucks down > > the performance quite a lot... > > Just out of curiousity: Is that last part an opinion or a fact? > > I haven't profiled the cost of dynamic_cast, but I also haven't > noticed any significant slowdowns since I switched from using > homebrew QueryInterface like methods to doing dynamic casts in > the right places... That's a fact. At least 4 years ago ;) At that time we were developing a real time animation system that made heavy use of RTTI. During the optimization phase, I changed the system to not use RTTI anymore and only that got me a speed up of 30%... It is possible that the performance hit is not this high anymore but I doubt that it got much better... Kind regards, Stefan PS : I admit that this opinion has been forged by old data. |
From: Tom v. D. <to...@ri...> - 2002-08-29 09:57:36
|
Last time I looked into it, I disassambled the dynamic_cast code, and came across 140+ asm instructions... so every cast takes at least 140 cycles, not taking stalls, and branches into account... but then again, I could be totally wrong, since it is at least 2 years back... I desides not to use it though, and use my own RTTI-like stuff where needed. Tom van Dijck. mudGE Entertainment. > Stefan wrote: > > To use dynamic_cast you must enable RTTI and that sucks down > > the performance quite a lot... > > Just out of curiousity: Is that last part an opinion or a fact? > > I haven't profiled the cost of dynamic_cast, but I also haven't > noticed any significant slowdowns since I switched from using > homebrew QueryInterface like methods to doing dynamic casts in > the right places... > > Jim Offerman > Crevace Games > www.crevace.com > > www.jimofferman.nl > > > > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_id=6188 > |
From: Jim O. <j.o...@cr...> - 2002-08-29 11:01:21
|
Tom, Stefan, > That's a fact. At least 4 years ago ;) At that time we were [snip] > Last time I looked into it, I disassambled the dynamic_cast code, and came > across 140+ asm instructions... [snip] We're rapidly plunging into the OT domain here, so let's just conclude that, while elegant, the use of dynamic_cast<> *might* be to costly, depending on circumstances. Jim Offerman Crevace Games www.crevace.com www.jimofferman.nl |
From: Yordan G. <yo...@gy...> - 2002-08-29 18:30:12
|
If the goal is to have HW independent render state stuff you can try the visitor pattern (as opposed to dynamic_casting). Have a base class: class RenderState { } derived classes: Material : RenderState Alpha : RenderState ... RenderStateSet - a collection of RenderState pointers... have a method that can make a difference between RenderSet objecs Changes = NewSet - LastSet; LastSet = NewSet; then visit the collection with the Visitor... Changes.Visit(Visitor) where the Visitor can be created by HW dependent factory... (abstract factory patt) Of course this utilizes virtual functions and some may consider them slow for this particular part of their engines. -Yordan |