Frame drawing

Started by
1 comment, last by DadleFish 17 years, 11 months ago
Hi all, I was considering the task of a frame drawing, when it comes down to displaying all the models, with or without effects, in some order as required, each with their own textures etc. This thread is intended to be more of a discussion and less of a question - I'm just pouring my thoughts in hope of some useful insights. If you were to do it naively, you would draw each model (or say a group of models) by first setting all the different render states needed, then you would actually draw the vertex buffer, and then you would reset all the render states back to their defaults. The last step is vital because in this naive form, one model doesn't know anything about the last model that was displayed, and therefore cannot assume anything regarding the render states; so if you always reset the state to a default one, you have a "clean sheet" and can act freely on it. However, this is of course very unuseful; one model may setup a texture which is needed for the next model as well; maybe a pixel shader had been set and can be used; not to mention setting a VB and just changing an IB (or vice versa), and the list goes on and on. I started thinking about a way to optimize this process, at least of a single frame if not for a bunch of frames. So I came up with one plan of preparing a "frame program", meaning that the renderer will store all the commands it gets, somehow, and then will optimize it itself and draw the whole frame. This of course requires quite a management system, and also adds some overhead to the process. In addition, the optimization itself is not VERY trivial and might as well take so much time that it will not be worth it. I also thought about some way for storing the whole state of the graphics in a single struct, and having a static struct in each model telling "what should be changed", and then make a really fast memory comparison function that will identify the places that need to be changed. This currently sounds like quite a good idea to me, and it also works between frames. Another approach is to attack the problem from a totally different perspective, having my scene graph(s) getting the models into bunches of operations, and propagating all the render state changes one level up the stream, therefore neglecting them in the model level and taking care of them - together - in the upper level. However, this will be problematic due to choices that the scene graph(s) can make which might not be ideal; also it informs the upper level too much about the little details of the model drawing, which is another disadvantage. Any ideas will be greatly appreciated. Thanks!
Dubito, Cogito ergo sum.
Advertisement
My current system uses effects, and most of them have only one pass. In my renderer I use a 'lazy' endpass/end method, where the renderer doesn't end the current effect but until when the next effect should be applied. So if the system is rendering the same mesh five times, it would just call the effect begin and end once, since they have the same effect.

My previous fixed pipeline renderer had a system similar to this. The renderer stored the state of (almost) everything, textures, shaders, vertex streams & formats, some blending funcs... Then when a mesh/primitive rendering is applied, the renderer checks which states can go unaltered. This of course, just gives a simple (but some if -overheaded) state batching ability, but what you really require in addition is that you ultimately sort your objects to make use of this state batching. (my profiling showed that in my case the lazy effect/parameter ending didn't significantly increase performance, because most of the objects used a different texture/effect anyway, and those that did have the same effect, were drawn out-of-order so I needed to sort).

Thanks for the reply.

Even with a lazy endpass, however, I believe there will be too many unnecessary changes in between drawing, if the current object doesn't know what went on before it.

For example, say that you have an object that enables alpha blending along with all its details. Then you want to draw an object that doesn't want any alpha blending. You basically have two options now:

1. The first object will remove all the alpha blending states (even if in a lazy method like you describe);
2. The second object will remove all the alpha blending states before it draws itself.

Obviously, the 2nd option here is not so good, because besides alpha blending there are a lot more states and if every object would do that, it will result in even worse performance.

However, I still don't want the first object to remove the states itself, because maybe some of them are good for the next one. Basically I want something in between. The 2nd object will just know "what to do" in order to get the current state just like it needs it, with as little change as possible.
Dubito, Cogito ergo sum.

This topic is closed to new replies.

Advertisement