I have a 3d world in a grid layout where each grid cell contains its separate vertex and index buffer for the mesh/terrain of that cell.

When the player moves outside the boundaries of his cell, i dynamically load more cells in his walking direction based on his viewing distance. This triggers x number of vertex and indexbuffer initializations depending on how many cells that needs to be generated and causes the framerate to drop annoyingly during this time.

The generation of terrain data is handled in a separate thread and runs smoothly. The vertex and index buffers are added during the update cycle of the game loop.

I´ve tried batching the number of cells to be processed to avoid sending too much data at once into the buffers, which worked ok at a shorter viewing distance (about 9 cells to process), but not as well at greater distances with around 30 cells to process.

Any idea how i can optimize this?

  • 1
    \$\begingroup\$ Is your terrain to big the have one big-vertex buffer and a few smaller index buffers? This way you only have to change index buffers, which is a cheaper operation. How many triangles are we talking about for the entire terrain, and terrain cells anyway? \$\endgroup\$
    – Roy T.
    Commented Apr 14, 2011 at 10:23

3 Answers 3


The solution to this seems pretty simple, really:

You're already generating your terrain data on a separate thread. You can create your vertex and index buffers on a separate thread as well!

Also, you are probably best off making your buffers quite huge - thousands of triangles.

  • \$\begingroup\$ Having doubled my buffer capacity the performance has improved and memory consumption gone down. Really nice. However, ive noticed that the actual bottleneck is when the newly created cells are to be added to the list of cells being rendered each render cycle. Adding too many at once will cause more lag (obviously). Is it common to add the newly created cells in smaller batches during several update cycles with a short pause between each batch or do you have a better idea? \$\endgroup\$ Commented Apr 18, 2011 at 17:53
  • \$\begingroup\$ @CodeSpeaker I am not sure I understand what you are doing. What you should probably have is a pool of vertex/index buffers of the appropriate size. When you need a new "chunk", have your worker thread fill a pair of pre-created buffers with data and then hand them over to your main/rendering thread once they're ready. And once they go out of view, return them back to the pool for re-use. Does this help? \$\endgroup\$ Commented Apr 19, 2011 at 5:47
  • \$\begingroup\$ Thats actually a great idea. Thanks for the advice, ill give it a shot :) \$\endgroup\$ Commented Apr 20, 2011 at 11:17

In case anyone follows up on this post, here is how i finally solved it:

Having a VB pool with equally large buffers is a nice idea, but in my case, it ate almost 300mb of ram which only left 200 for the rest of the game (since the target platforms are both pc and xbox 360). This led me to a similar yet cheaper solution after several nights of tweaking :)

I still have a VB pool, but each VB has a custom tailored size for the world data within that cell. When a VB item gets recycled (the cell moves outside the players visibility scope) i check if the next batch has any cells which require a VB of the same size or less. This approach lets me reuse enough buffers to keep the fps smooth, yet resulting in a memory consumption of between 80-90 mb of ram. Not bad!


Do you need to process all the new cells at once or could you queue them up and do a few each frame? Is the terrain data in memory or are you loading it from disk and processing it all on your main thread? (if so, perhaps you could read the data on a background thread).

  • \$\begingroup\$ Thats actually what im doing. I queue them into groups of 10 cells per "batch". The terrain data is always in memory. \$\endgroup\$ Commented Apr 13, 2011 at 21:14
  • \$\begingroup\$ couple of other thoughts if you're not doing this already: 1. you could create a pool of vertex and index buffers and re-use them to avoid some resource creation overhead. 2. Check the usage flags on your SetData calls to see if there's a faster way. 3. is the view distance great enough that you could store your terrain in more than one level of detail? Maybe tessellate as you get closer to each cell? \$\endgroup\$ Commented Apr 13, 2011 at 22:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .