Draw Calls and Vertex Buffers

View previous topic View next topic Go down

Draw Calls and Vertex Buffers

Post by Gump on Mon May 30, 2011 8:58 am

Hi there,

First off saying I have followed you videos on youtube for a while now and absolutely love your work.

I am writing my own little engine and have run into a few architectural problems....

In other posts I have read you use 8 meshes. One for each side of the cubes, and one for water and one for something else. Is this 8 meshes per chunk? or for the whole world.

Reason being is if I have a vertex buffer for each chuck, and do draw calls on each of those buffers, I get major FPS slow downs, but If I put all my vertices in one buffer, I get great draw performance, but if I update the world I have to rebuild the entire world buffer(as opposed to a chunks buffer).

I am using XNA4. Any information would be great on your VertexBuffer and Draw techniques! Do you get around slowdowns by rebuilding the vertex buffers in a separate thread?

Thanks!

Gump

Posts : 3
Join date : 2011-05-30

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Slaihne on Mon May 30, 2011 10:45 am

Cheers for your support.

I think you may be better of using a single vertex / index buffer per chunk with XNA. One of the other guys developing an engine was using XNA and he reckoned that 6+ buffers per chunk was killing his frame rate but 1 buffer per chunk was fine.

Another reason i use more buffers is that i use a different format for the 'model blocks' and also the liquid blocks than for the plain square blocks.

With the 1 buffer per chunk approach you lose the ability to 'not draw' the sides of the blocks that you cannot see, EG. the west faces of blocks from a chunk that is to the NorthWest of the player.

I don't think the single whole buffer for the world will work, or at least it will be very complex if you do get it to work.

****

I currently have 2 threads. One that does the drawing and another that basically does everything else. The second thread gets the chunk to the mesh stage and then flags it for the first thread to transfer it to GPU memory. The first thread then uploads any required buffers to GPU memory before issuing the next set of draw calls.

This means that the main thread is just (sometimes) uploading stuff to the GPU, and then issuing a bunch of draw calls as quickly as possible.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by S33m3 on Mon May 30, 2011 1:45 pm

Slaihne wrote:Cheers for your support.
...
With the 1 buffer per chunk approach you lose the ability to 'not draw' the sides of the blocks that you cannot see, EG. the west faces of blocks from a chunk that is to the NorthWest of the player.
...

I remember at the beggining, I have tried both possibilities : Store the cubes faces inside chunks grouped by faces type or not ?

And it was pretty clear to me : The less draw call the better ! Why ? The draw call are handled by cpu/driver and so will CPU bound your application.

Exemple :
With 1 VB/IB per chunk : I have 1024 chunks in my landscape, with frustum culling it makes an average of 512 indexed draw call for refreshing a frame.
With 6 VB/IB per chunk : 3072 draw call per frame, that's a lot, and really too much !

Now XNA4 is based on DirectX9, that is more sensible than DirectX 10/11 to the number of draw call. You should as most as possible limit the number of draw call before trying to reduce the qt of informations send to the GPU. The main reason is that except for really low end computer, the GPU tends to be more powerfull than the CPU !

But all in all it's just a mater of balancing all, if the application is CPU bound = Reduce the number of Call. If your are GPU bound, limit the qt of informations treated by the GPU.

Having "PIXelified" Blockworld from my laptop (not so powerfull graphic card), I'm already CPU bound. It means that even if Slaihne send less data to GPU (by not sending a specific cube face) the performance improvement won't come from the fact that the GPU will have less work to do (as it is already idle 20% of the time waiting for data from the CPU), but simply the number of draw call that will reduce the CPU/driver work.

XNA should be able to issue 1000 draw call par frame without problems even on low end hardware. If you have performances problem it must come from somewhere else.

S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Slaihne on Mon May 30, 2011 2:16 pm

S33m3 may be right here.
I'll have to try a single buffer for the blocks.

But also i reckon that my drawing code could do with some optimization. It's pretty much just the original code i wrote and is probably doing wayyy to much work on the CPU with state setting calls etc. So, i'll have to take a look into that also.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Gump on Mon May 30, 2011 9:49 pm

S33m3 wrote:

With 1 VB/IB per chunk : I have 1024 chunks in my landscape, with frustum culling it makes an average of 512 indexed draw call for refreshing a frame......


This is exactly what I am doing. I have 1 VB/IB for each chunk. Then for each chunk I call:

device.SetVertexBuffer(chunkVertexBuffer);
device.Indices = chunkIndexBuffer;
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, NUMBER_OF_VERTICES, 0, NUMBER_OF_TRIANGLES);

The above code gets called on each chunk, If I start to scale above 100 chunks I get major FPS slow down. 150 chunks shows under 20fps.

S33m3 wrote:
.....XNA should be able to issue 1000 draw call par frame without
problems even on low end hardware. If you have performances problem it
must come from somewhere else.

If this is indeed the case I must be doing something really wrong. Ill go step through my code again, and make sure im not doing anything silly every draw call.

By the way Slaihne, I really enjoy the music you compose on your videos, the James Bond theme one was brilliant.

Gump

Posts : 3
Join date : 2011-05-30

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by S33m3 on Mon May 30, 2011 11:45 pm

To see if you have missed something do a quick PIX profiling of your application.

What's your average "NUMBER_OF_TRIANGLES" by chunk ?

S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by S33m3 on Tue May 31, 2011 12:44 am

For Slaihne :

I ran a PIX of BlockWorld vs MyEngine just to see where you are with your states and draw call.

I set my engine to draw with 160 block distance, I have 2 VB/IB per chunk (1 for solid one for liquid mesh). But don't have other VB for custom model.
I'm using slimDX DirectX11 with DirectX10 compatibility mode (You should really go to DirectX11 if you already have a font and sprite engine ! ==> Better driver support and performance with pure DirectX11, really no reasons to stay with directX10 API)

Here are the results per frame (for 400 chunks in total - for an average of +/- 300.000 primitives displayed) :

BlockWorld :

Draw Indexed primitive call : 821
Draw Primitive call : 28
VertexBuffer Lock : 24
Index Buffer Lock : 24
SetRenderState calls : 1156
Shaders Set : 1134
SetTexture : 1133

Utopia :

Draw Indexed primitive call : 220
Draw Primitive call : 0
VertexBuffer Lock : 0
Index Buffer Lock : 0
SetRenderState calls : 17
Shaders Set : 512
SetTexture : 512

You should really do something with your SetRenderState ! Smile
Also (like me) avoid to set Shader/Texture linked with no draw ==> It's sending Constant buffer data for the shadder for nothing. In fact in theory Draw calls >= ShaderSet


S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Slaihne on Tue May 31, 2011 2:24 am

Lol, I should get you to do QA for me S33m3 Wink

I'll have to take a close look at this area soon. I knew there was probably a load of inefficiency there but didn't realise how much. Sad

It goes to show, though, how forgiving DirectX 10 can be. Especially when you consider that i'm going through the Managed => Unmanaged code thing via SlimDX which adds its own set of overheads for each of those excess calls.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Gump on Tue May 31, 2011 7:13 am

S33m3 wrote: What's your average "NUMBER_OF_TRIANGLES" by chunk ?

Thank you so much S33m3. Turns out some old code was setting the NUMBER_OF_TRIANGLES variable to a hardcoded value I was using when I was testing with 1 world VB. It was over 150000. I am now using chunkVertexBuffer.Count to get verts and chunkIndexBuffer.Count / 3 to get the triangles, I now have over 1000 draw calls working at over 60fps.

Such a stupid mistake, I cant believe I missed it. PIX helped me find it so thankyou so much, I have been stuck on this for a week or so.

For brevity, my average triangle count is abit over 1000. I hope I will be able to decrease this number, because there are a few optimisations to be done there yet. For instance, I have read about laying down "strips" of textures when the same blocks are sitting next to eachother. So instead of having a texture map thats 16x16, its 16x256. Its bound to reduce poly counts.

Thanks again Smile

Gump

Posts : 3
Join date : 2011-05-30

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by S33m3 on Tue May 31, 2011 7:53 am

No problem Smile
Just a tip : A common "beginner" mistake is to try to ease the GPU work by doing CPU optimization (Like creating strips, doing crazy math to avoid a draw call, ... ...), 80% of the time our program are CPU bound, it means doing these type of optimization is really a bad idea (in the beginning).

After, if you see that you are GPU bound then in this case it is worth investigating such optimization. But believe me, when I was beginning, sometime i was spending weeks trying to optimize things for the GPU (draw calls, states changes, ...). In the end it results in poor GPU performance increase, lost of CPU cycles for "nothing" and lines of codes more difficult to debug.


S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Slaihne on Tue May 31, 2011 8:46 am

S33m3 's tip is a good one. The GPU is very good at handling lots of things being thrown at it.

It's worthwhile doing optimisations if you can half the number of triangles your are drawing but a reduction of 20% isn't really that worthwhile, at least not while you are developing. Things like keeping your vertex size small are more important than complex optimisations. Also, watch out for overdraw; 1000 fullscreen quads is 2000 triangles, but they have a hell of an overdraw (depending on the order you draw them) and this can kill performance too.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Draw Calls and Vertex Buffers

Post by Sponsored content


Sponsored content


Back to top Go down

View previous topic View next topic Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum