I'm currently creating a system that essentially creates a world at run-time based on a seed I choose. In this system, I made it so that there are certain "chunks" that divide up different sections of the world, and in these sections, I have different meshes that are completely unique to that chunk. Each chunk is also divided into 4 subchunks, which are exactly half the width and height of it's chunk.

The purpose of the chunks and subchunks is so as the player, you could walk around the level, with the current chunk, as well as the adjacent chunks stored into memory with their meshes, and those adjacent chunks, which cannot be seem from where the player is, are loaded, however their meshes are not currently loaded, and as the player moves, the system will load and unload these chunks meshes into memory, that way only the meshes needed to render are loaded in at this time.

The problem that I'm having is when I move from one chunk to another, and load the new chunks meshes, and unload the unnecessary chunks meshes, there's a lag spike that only lasts for about half a second. (But it quite noticable) The spike IS NOT coming from the loading and unloading of the mesh, (my memory manager is fast with allocation and deallocation and the loading and unloading are handled on a separate thread) the problem is when I go to change the memory inside the vertex and index buffers. (Which whenever there is a swap, adds AND removes 4 times each during one game loop.

Does anyone have any idea on how I should handle my open world objects? A good reference would be something along the lines of Skyrim or World of Warcraft; They have the large terrain in these worlds and they are most definitely not 100% loaded in the game at once, so how would I go about making it that so as you progress through the world, objects are handled with little to no skip?

Thanks a lot for the help in advance, and if there is clarification needed, simply ask.

Edit: Added code showing my AddVerts function, which is used to pass vertex data to the GPU.

// unsigned int* AddVerts(const VertexFormat *pVerts, const unsigned int nNumVerts)
// returns  :   unsigned int*           offset in buffer to where the mesh is located
// ins      :   const VertexFormat*     vertices to pass on to the GPU
//              const unsigned int      number of vertices allocated for the const VertexFormat*
void *buffer = nullptr;
unsigned int nSize = nNumVerts*sizeof(VertexFormat);

if( ( m_unBufferFlags & D3DUSAGE_DYNAMIC ) != 0 )
    m_pVertexBuffer->Lock(nVertLocation*sizeof(VertexFormat), nSize, &buffer, D3DLOCK_NOOVERWRITE);
    m_pVertexBuffer->Lock(nVertLocation*sizeof(VertexFormat), nSize, &buffer, 0);

// copy data to buffer
memcpy(buffer, pVerts, nNumVerts*sizeof(VertexFormat));


return &(m_dllOffsets.GetTail()->element);
  • \$\begingroup\$ you could post some code or add some explanation on how you manage your GPU Buffers, maybe there are some optmisations you can make to reduce the lag \$\endgroup\$ – Luis W Aug 12 '13 at 13:55

What you can do is use multiple vertex buffers for the chunks. When you call the map function, you deny gpu access to that resource, so the gpu must wait for you to be done with the buffer before it can use it again (see link). If you have multiple vertex buffers, say one for filling and one for rendering, the gpu does not have to wait and this might reduce your lag. Think it as the front- and back buffer approach most render systems use to render the result to the screen. One buffer is used for drawing and one is used for displaying, so you don't see the frame being drawn. I think the same approach could help you reduce or even remove the lag spike.

EDIT: my bad, I see now that you use the lock method instead.. You can still give it a try though...

  • \$\begingroup\$ Yeah, I thought of this the day I posted the question and have already started the implementation. I'm making it so every time it want's to add/remove verts, it will copy the current buffer into a temporary buffer, do the add/remove operation, then, when our main thread's available, copy the data from the temporary to the main buffer. I'll get back to you if this solution works. \$\endgroup\$ – iNightfaller Aug 14 '13 at 12:19
  • \$\begingroup\$ Okay, I finished the system, and with the power of multithreading, this multiple buffer thing was possible. Thank you very much everyone who helped. \$\endgroup\$ – iNightfaller Aug 16 '13 at 4:37
  • \$\begingroup\$ Did it help reduce the lag spikes? \$\endgroup\$ – Krienie Aug 16 '13 at 14:13
  • 1
    \$\begingroup\$ Yes it did, what was once a .5 second lag spike every time I transitioned into new area's is now so minimal the game maintains 60fps. (w/Vsync) I also did make another optimization where each main chunk had it's own vertex buffer for it's 4 subchunks as well, which made it so I wasn't calling memcpy on hundreds of thousands of verts. \$\endgroup\$ – iNightfaller Aug 16 '13 at 16:10

One approach to reduce the lag is to divide the buffer change costs to multiple frames, that way the lag of a half second gets divided to e.g. 3 seconds, so it gets not that noticable.

  • \$\begingroup\$ This simple sounding answer is how almost everything I've worked on handles the situation, Unreal etc... It could also be that your "chunks" are way too large and need to be divided into bite sized blocks that are easily digestible by this piecemeal solution. \$\endgroup\$ – Patrick Hughes Aug 13 '13 at 12:37

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.