Skip to main content
gamedev.net
🔒 Locked

Render-Order Sorting

Started by Devnull 1 reply 2.1k views
Original Post
Devnull
Devnull
I'm trying to figure out what the sort-ordering of my drawing calls should be for pre-sorting for rendering. Currently, I sort by the following criteria (in this order): 1. Effect 2. Texture 3. Model (Mesh/Vertex Buffer/Index Buffer) 4. Secondary VB or Mesh Frame # 5. Index Buffer or Mesh Subset 6. Mesh LOD Each of my Effects, Texture-combos, models, vertex buffers, etc. have 16-bit IDs that I use for sorting, so this is relatively painless to do. This also happens post-frustum-culling, so I don't sort things that aren't actually going to be rendered. However, in reading ATI's document Performance Optimization Techniques for ATI Graphics Hardware with DirectX 9.0, they talk about the importance of pre-sorting your drawing calls in a couple different ways. In section 4, they say:
Quote:
To reduce the number of state changes and associated overhead, applications can sort and batch rendered objects by shaders or rather "effects" that include combination of shaders, textures and other states. On the other hand it might be beneficial to sort objects by distance for HYPER Z optimizations. Sorting objects by effect/state quite often conflicts with sorting by distance used in front to back rendering. One possible solution to this problem is described in discussion on When Multiple Render Passes Are Better than One.
They say that a possible solution might be to use multiple rendering passes (which contrary to intuition, actually speeds up rendering in this case):
Quote:
On the first render pass just initialize the depth buffer with proper depth values for your scene by rendering all geometry without any pixel shaders and outputting only depth and no color information. Since no shaders are used, it is possible to render everything in the front to back order without causing any major render state changing overhead. Then render everything once again with proper shaders. Because depth buffer is already initialized with proper depth values, the early pixel rejection can happen due to HYPER ZÆË optimizations, thus creating effective overdraw of one on the shader pass.
So, I have a few questions from all this: 1. For the first pass, do I need to sort things by Z-Order myself or can I just throw everything at the video card and have it do the work? Should I just use my original sorting before doing the first pass? Do I need to re-sort the render list for the second pass? 2. How do I actually DO what ATI is talking about here "just initialize the depth buffer with proper depth values for your scene by rendering all geometry without any pixel shaders and outputting only depth and no color information."? (I'm using DirectX 9.0 Oct 2004 and C++) 3. Is my original sorting order good or should I sort them by different criteria? Did I forget something important?
How''s my programming? Call 1-800-DEV-NULLwww.devnullsoftware.com
Graylien
Graylien
I'll try an answer for each of your three questions (in order).

1. You do not need to sort your scene manually. The author of the paper you cite isn't clear when he says "it is possible to render everything in the front to back order without causing any major render state changing overhead" because that's always true if you never change the render state. The mention of "front to back order" seems to imply that you have to sort your own geometry, but I don't believe this is what the author really means. He just means that render states don't affect the depth values in the z-buffer in this situation.

2. Firstly you want to ensure that when you use the one of the Direct3D Clear() methods instead of, say, rendering a black rectangle at maximum depth to achieve a "similar" effect. (Some people still do this.) For ATI cards employing HyperZ this is crucial to the proper behaviour of their pipeline optimizations.

At this point you can render your geometry in the absence of any lighting, textures, pixel shaders, etc. When rasterizing naked vertices the real target is the depth/stencil buffer and not the frame buffer.

After doing this, you render your scene as you normally would. The idea here is that the HyperZ technology will kill many pixels very early in the pipeline, thus saving the expense of actually going through the pixel shaders or whatever.

3. I think maybe the author's mention of minimizing render state changes in both quotes is what's confusing you. In this example of multi-pass rendering you're populating the depth buffer by quickly rendering naked vertices: No render states, let alone state changes. Afterwards in the second pass (which you order however you wish) HyperZ kicks in to trivially reject some pixels ... although you'll still want to watch your state changes.
------When thirsty for life, drink whisky. When thirsty for water, add ice.
DonnieDarko
DonnieDarko
You can use the D3DRS_COLORWRITEENABLE state to disable writes to the color buffer. Also I think you should z-order your first pass to avoid z overdraw.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.