sorting render calls...

Started by
5 comments, last by Kalidor 17 years, 11 months ago
Hi, i've modified my renderer in order to sort render calls :

struct mwRenderCall
{
    mat44               modelView;
    mwVertexBuffer*     vbo;
    mwIndexBuffer*      ibo;
    mwMaterial*         material;
    mwShaderProgram*    program;
};

class mwRenderer
{
    ...
    std::vector<mwRenderCall> m_renderCalls;
};
when my objects want to draw a mesh, they call a renderer method which will add a new mwRenderCall to m_renderCalls. at the end of the frame, i loop through m_renderCalls and render all. the question is : what is the best sorting to do on the renderCalls ? for the moment, I sort by vertex program, then by material, then by vertex buffer and then by index buffer. Is this the optimal choice ?
Tchou kanaky ! tchou !
Advertisement
I wouldn't sort by vector program first, because (to my knowledge) they are quite small and would be easy to swtich. Other than that as far as resources go u want to sort by the largest resources first, and group them over the smaller ones. So if u have alot of small objects with large textures, it may make sense to sort by textures first then vertex buffers next, ect...

Conceptualy I would assing each resource (texture, vertex buffer, index buffer) a byte size, then sort by that size first. This would form groups of resoruces with the same size (and obviously 2 identical resources would be the same size). I would then sort these groups so that similar resources were grouped together.

Also there is another thing to consider. If you're just working with opaque objects drawing in a front to back order can also speed things up considerably, so u might want to add that into the sort as well.

Just a few things to consider.
Quote:Original post by Ryan_001
I wouldn't sort by vector program first, because (to my knowledge) they are quite small and would be easy to swtich.


Then you would be horrendously wrong and should really read the Forum FAQ.
A shader change is the single most expensive operation you can perform on a modern GPU, size isnt whats important here, its GPU internal changes, ALOT goes on when you switch a shader.

To answer the OP's question, most of that stuff doesn't really matter.

The idea is to minimise state changes, so based on your list, you'd sort by shader and then by Material, everything else is a much lighter change, although trying to keep index and vertex buffer switches down is important as well. Last on your worry list is that matrix.

See the Forum FAQ for a short list on the cost of state changes.
I don't disagree with u Phatom, but would you have any idea why this is? It seems rather counter-intuative to me. The faq was rather terse to say the least.
Quote:Original post by Ryan_001
I don't disagree with u Phatom, but would you have any idea why this is? It seems rather counter-intuative to me. The faq was rather terse to say the least.


On the shader issue?
The reason is the GPU has todo alot of work, off the top of my head;
- load the code
- setup internal state
- flush various caches

And it has to wait for all drawing operations to be completed, so you've got a sync point right there.

Compared to that, most other operations are alot lighter, infact the only thing more expensive to change right now is a fragment/pixel shader.

When it comes to VBOs there is a chance they will exist or can be copied in blocks to VRAM and this operation could be done async with other drawing operations to hide its cost. So, the main cost with them is the setup and state changes when you draw.

Textures are much the same, these will often live in VRAM or AGP ram and thus can be moved across to VRAM before they are drawn from (although even a texture change requires a cache flush and invalidate, which is why they are the 3rd most expensive change on the Forum FAQ list).
okay so I was doing the right thing if I understood well. Will it be a good idea to sort by modelView Z translation in order to render front to back (before sorting by vbo) or is it a better idea to keep it that way ?

anyway thanks for the answers so far.
Tchou kanaky ! tchou !
Quote:Original post by Mawww
okay so I was doing the right thing if I understood well. Will it be a good idea to sort by modelView Z translation in order to render front to back (before sorting by vbo) or is it a better idea to keep it that way ?

anyway thanks for the answers so far.
Nowadays it's best to forget about sorting by depth (except for transparent objects of course, but that's for correctness and not performance) and just sort by shader, texture, vbo in that order. If you have expensive fragment shaders it can be a big win to do a first pass that just renders the depth of the scene with color writes off (or maybe just outputting ambient color) then render the full scene with depth writing off (and no ambient light if you calculated that in the depth pass). This way you only run the expensive shaders on fragments that are actually visible. Again, transparent objects have to be separate from this.

Depending on your scene and shader complexity this can be a huge gain, it can also be a performance loss however so you should profile it in your particular application.

This topic is closed to new replies.

Advertisement