Sign in to follow this  

Vertex Batching

This topic is 4104 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently figuring out a sorting and vertex caching system for my renderer. It's apparent that it's a good idea to batch as many vertices as possible into a single vertex buffer and call as few DrawIndexPrimitive calls as possible. If I was to sort my mesh subsets by shader then texture, how is it possible to minimize the number of calls to DrawIndexedPrimitive when transforms are taken into consideration? I can't envisage any way to call DrawIndexedPrimitive fewer times than I have transforms to set, which is likely to be for every individual subset which needs to be rendered. Does anyone have any advice or knowledge of what I might be missing here?

Share this post


Link to post
Share on other sites
For SM3 (or ATI SM2 cards with a little bit of a hack) use the instancing API (SetStreamSourceFreq). Update a dynamic VB with your transforms in it, and attach it as stream 1, and mark it as instance data. See the SDK and samples for how it works. Basically the card will render your geometry stream of data once for each entry in the instance stream of data.

For lesser cards, depending on what you're doing, there are choices to make.

For static world objects, you can pre-transform many nearby objects, and draw them as a single entity. Some pre-processing needs to be done as your editor prepares the level.

Another instancing idea is to place multiple copies of a mesh, or varieties of a mesh into a single VB. Each mesh has a different ID (first = 0, second = 1, third = 2) as a vertex data element. In your shader, index into an array of world transforms based on the index found in the vertex. This can be used to replicate rocks, weeds, debris, etc. You don't need to replicate the same mesh either, you can have three varieties of grass, and a flower, then repeat these 4 meshes a few times. You will now be able to draw a large number of grass bits and flowers in a single draw.

You can mix this idea of multiple meshes with SM3 instancing to draw a variety of meshes multiple times without storing as much data in the VB. Perhaps each mesh holds an ID (0,1,2,3) and each SM3 instance data item holds an ID (0, 4, 8, 12). Simple add the two ids, and index into a set of transforms.

You can also simplify the transforms in some cases to use less than 3 or 4 constant registers. Perhaps you just need position (3 floats), and rotation (1 float), using sin and cos in the shader to produce the rotation. On earlier hardware you'll need to store 2 floats (sin angle, cos angle). Now that you're at 2 constants, perhaps you will add a scale, or a color tint.

Hopefully you've got some ideas of where you can take it from here.

Share this post


Link to post
Share on other sites
The instancing Ip looks like a good bet and I've read up about it in Game Programming Gems in an article on rendering crowds but my problem is that the SetStreamSourceFreq isn't supported on the 360 which I thought was sm3 but seems to only have sm2 API support.

The XDK does explain how to emulate it using HLSL though using the inline asm vfetch command and an index into an array of vertices which may be an option and this is the idea I think you were explaining for non-sm3 cards.

So, now is the time to be getting to work and looking at ways to get these things up and running.

Thanks for the advice.

Share this post


Link to post
Share on other sites
We just recently got our 360 devkit, so I hadn't seen that earlier. No, this is definately NOT what I was talking about. For 1.1, I meant put an index into your vertex data, and several copies of the data into your VB.

struct
{
float x,y,z;
float nx,ny,nz;
float u,v;
float instanceID;
};

VB = FirstCopyOfMesh(ID=0), SecondCopyOfMesh(ID=1), ThirdCopyOfMesh(ID=2)
For each vertex in the mesh, use same same instanceID. Place several meshes in the VB.

In your shader, have an array of world matrices.
float4x4 worldmats[MAX_INSTANCES];

And pick a matrix based on the ID.
float4x4 world = worldmats[IN.instanceID];

This is much like bones, except using a single matrix per vertex.

To draw extra meshes, just increase the numVertices and primCount parameters of DrawIndexedPrimitive, and set more world matrices in the array.

This 1.1 technique isn't necessarily suited to the 360.

Share this post


Link to post
Share on other sites

This topic is 4104 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this