Yes, Map
can force synchronization in some situations.
In D3D11, the driver handles GPU command recording, submission and synchronization. When you make D3D11 calls, generally they don't get submitted to the GPU immediately; rather, the driver tries to batch up a large amount of work into a command buffer and then submit it all at once (because submission is expensive).
What this means for your vertex buffer is that every time you use MAP_WRITE_DISCARD
, the driver is internally "renaming" your vertex buffer and giving you a new, fresh buffer into which to write. It can't actually overwrite the previous buffer because the work that uses that buffer hasn't executed on the GPU yet. So each time you do a discard, you're effectively allocating more memory, and the driver is buffering up all those vertex buffers and draw commands for the GPU to access at a later time.
The driver uses various hints/heuristics to determine that it's time to submit work to the GPU. Usually it submits when you call Flush
or Present
, but probably another heuristic it uses is the amount of memory allocated that's waiting for the GPU to consume it before it can be reclaimed. So at a certain point, when you've done a large enough number of discards, the driver decides it had better submit the pending work and wait for it so that it can reclaim the memory for all those buffers.
To work around this, you can help out the driver by managing the memory yourself. Allocate a vertex buffer large enough to hold all N draw calls' worth of data, fill it all in with a single Map
, then do the draw calls using the StartVertexLocation
parameter to point each one at its corresponding data within the buffer. Or even better, combine all the draw calls into one large one (assuming you don't need to change states between them).