I am currently working on a project that does 2D sprite-like graphics on Windows 8 (Metro-style app). For that purpose I am using Direct3D with quads to act as sprites.

My problem is that it get's very slow (30fps at 100 sprites) and profiling led me to believe that the bottleneck is withing the CreateBuffer call. How can I solve that problem in an elegant way? Wouldn't gathering copying vertex data from all elements that share the same texture in a single, bigger, buffer be more cost-prohibitive, as it is all done on the CPU?

  • \$\begingroup\$ Are you creating a new buffer every frame? You should be reusing your buffers. \$\endgroup\$
    – Jimmy
    Jan 17 '13 at 22:39

You shouldn't be creating a new buffer each frame. Memory allocation/deallocation operations are often quite slow, especially when it involves video memory as a CPU/GPU sync point may be introduced.

A better way to work with vertex buffers is to reuse a single vertex buffer, mapping it with the DISCARD and NOOVERWITE flags, as appropriate, to let the driver know what you're doing. This is a topic big enough for an article in itself, but this MSDN page has the basics. If you search for "dynamic vertex buffer" on the web you'll find more articles about this. BTW, this works essentially the same way in all versions of Direct3D, though the API calls and flags are a little different in D3D10-11 vs D3D9.

And, just to be clear, you should definitely group together all the sprites that have the same texture and draw them at once. Texture/shader changes have a nontrivial performance cost, so it's best to minimize the number of such changes.

  • \$\begingroup\$ The only problem with that idea is the fact that deletions don't seem that trivial, anyway, I'll give it a try, thanks for help. \$\endgroup\$
    – Taikand
    Jan 17 '13 at 23:47
  • 1
    \$\begingroup\$ @Taikand If you're talking about deleting the vertices for a sprite that has gone away: many people simply regenerate the entire contents of the vertex buffer each frame, so adding/removing sprites is taken care of automatically. However, you could also just set the positions for a deleted sprite's vertices to zero; the triangles will be degenerate and the GPU will skip them. Having a few degenerate tris isn't a big deal (although having a lot of them will sap performance). \$\endgroup\$ Jan 18 '13 at 0:01
  • \$\begingroup\$ @Nathan Reed: I can understand that, for the GPU, iterating over the vertexbuffer with lots of degenerated tris (vertices set to zero) would sap performance. BUT, would this only be the case if the indexbuffer kept the indices of those tris when the drawcall is invoked? What if the indexbuffer was updated to skip/omit those specific "unused" tris? Wouldn't the GPU render the actual used tris just as fast then, compared to a freshly new vertexbuffer created at just the right size? \$\endgroup\$
    – bigp
    Jan 2 '14 at 11:57
  • \$\begingroup\$ @bigp If you got rid of the indices corresponding to the unused tris, yes, I think that would usually be just as fast. The only reason I can think of why it might not be as fast is if it results in you skipping around in the vertex buffer a lot and getting really bad memory locality. But I think that would be unlikely. \$\endgroup\$ Jan 2 '14 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.