Sign in to follow this  

instancing with multiple meshes

This topic is 669 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

If you had multiple meshes in one buffer, is there any way to render them in a single call.

 

For instance, if you had 2 simple variations of an asteroid stored in one buffer just with different indices (i.e.0-300 is mesh one and 300 - 600 is mesh two).

 

Sure you could just render two batches of instances but suppose there were 10 variations or maybe 256.

 

The only way I could think of doing it would be to assign a shape id to each variation and then add that detail to the instance attributes.

Then as each triangle is processed any with non matching ids could move themselves off-screen or to 0 scale or something.

 

This would work I think but seems inefficient, is there a better way?

 

Perhaps a better example could be a short amount of 3d text, each character is a small portion of the buffer.

You could then set up some instance attributes that position each character, but every single character would have to be sent though the pipeline per letter. Sure the characters could all be pre-merged into a their own mesh but that just isn't as fun

 

Might not be possible, just floating an idea :D

 

Share this post


Link to post
Share on other sites

Yes, it's possible to draw lots of different variations of an instanced mesh with one draw call.

 

The trick to this is to use an instance buffer with the variations of each model stored within it as an array of values, and then alter each model at the shader level, e.g. colours and textures. You could even use a geometry shader to alter the polygons that make up the model, if i remember correctly. You can and should of course set positions and scale and other translations in the instance buffer as a basic minimum.

 

How you represent these values is down to you and the requirements of your game.  I found this tutorial very useful in understanding how instancing works and what things are possible with it, and ended up using instancing as a simple particle generator. This isn't the best way to solve that problem, but as with all things, there's more than one way to skin any cat.

 

Hope this helps!

Share this post


Link to post
Share on other sites
IIRC DX11 doesn't have the equivalent of that; you have to issue multiple indirect draw calls however that still requires N draw calls for N sets of instances (bit of API tricky in the GL world; still breaks down to multiple draw packets on the backend.)

If you want to do 'multiple meshes in one draw call' then, depending on your hardware target, the OP's original idea will work.

You require a buffer with all the vertex data in, and another buffer which lets you offset index in to it on a per instance (or, I guess, per group of instances) frequency.
Bind the buffers as inputs, but not as traditional vertex buffers.
Then issue your instancing draw with the correct vertices and instance count (which would be total required).
In your vertex shader you'd use the incoming values (vertex id and instance id) to index in to the offset and vertex buffers as required to pull the vertex data yourself. (vertex and index buffers can be 'null' for this.)
At which point you proceed as normal.

One important point with this method is that your meshes have to have the same vertex count; this is because vertex count is a function of the input to the draw call so you'll always get say 64 vertices processed per instance. You could, of course, use degenerate triangles to have meshes with varying numbers of output verts but you'll still pay the vertex shader cost for them.

D3D12 (and I assume Vulkan) offer more interesting ways of doing this as you can construct your own multi-draw indirect buffers from a compute shader which also allows changing of vertex buffers per draw packet; that's a tad more complicated however ;)

On the D3D11/Vertex shader route however this presentation covers what I wrote above, but maybe in a slightly clearer way; http://www.gdcvault.com/play/1020624/Advanced-Visual-Effects-with-DirectX - the bit in question is 'Merge Instancing'.

Share this post


Link to post
Share on other sites

IIRC DX11 doesn't have the equivalent of that; you have to issue multiple indirect draw calls however that still requires N draw calls for N sets of instances (bit of API tricky in the GL world; still breaks down to multiple draw packets on the backend.)

AMD supports it in Dx11 via their "AMD GPU services" extension library (in their GPUOpen GitHub). They also do support it in HW - the GPU's command processing front-end decodes the single multi-draw-call.

Share this post


Link to post
Share on other sites

Thanks guys! Looks like it was as expected, possible - but requiring modern apis. Which is a shame as I am limited to older ones but at least I was along the right track :-D

 

Will experiment with passing in ids in a buffer and degenerating triangles. I have a feeling it might still be a faster approach than the additional draw calls.

Share this post


Link to post
Share on other sites
You can do all the VS-based custom vertex pulling trickery on the D3D9/GL2 APIs, by storing your vertex data in a floating point texture instead of a buffer ;)

Before you bother though, first make sure that you actually do need to dramatically optimise your CPU-side GL/D3D time per frame.

Share this post


Link to post
Share on other sites

IIRC DX11 doesn't have the equivalent of that; you have to issue multiple indirect draw calls however that still requires N draw calls for N sets of instances (bit of API tricky in the GL world; still breaks down to multiple draw packets on the backend.)

AMD supports it in Dx11 via their "AMD GPU services" extension library (in their GPUOpen GitHub). They also do support it in HW - the GPU's command processing front-end decodes the single multi-draw-call.


Ah, I stand corrected.
Note to self; re-read the GCN docs at some point...

Share this post


Link to post
Share on other sites

You can do all the VS-based custom vertex pulling trickery on the D3D9/GL2 APIs, by storing your vertex data in a floating point texture instead of a buffer ;)

Before you bother though, first make sure that you actually do need to dramatically optimise your CPU-side GL/D3D time per frame.

 

Ahh sneaky, and just move texture lookup locations to point to the correct "mesh".

I doubt it will make it into any sort of production, but I like to find alternatives and put them though their paces, better the devil you know ey

Share this post


Link to post
Share on other sites
One technique I used for drawing a large number of small mesh's was to abuse the tessellator. This of course won't work for D3D9 level hardware, but I thought I'd mention it none-the-less.

In the vertex shader I computed all the per-instance data (one vertex per instance). The hull shader computed the number of triangles needed for the given instance and created a quad patch with enough triangles to render all the triangles in the mesh. The Hull shader did nothing but pass on the per-instance data. The geometry shader would then transform each triangle created from the tessellator using the per-instance data passed in, and looking up the specific instances vertex data from a SRV. It did mean duplication of some vertex computations, but it also meant that you got very efficient culling/LOD, and that per-instance data only needed to be calculated once, and there was no intermediary UAVs, streams outs, etc...

Now I never benchmarked the performance, and after watching the wonderful link by Phantom I have a feeling that it would probably be slower than other options, but it seemed pretty cool at the time smile.png

Share this post


Link to post
Share on other sites

This topic is 669 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