Advertisement

How to create a "dynamic" buffer?

Started by December 08, 2017 05:13 PM
1 comment, last by MJP 7 years, 1 month ago

I have a vertex buffer on a default heap. I need a CPU pointer to that buffer in order to loop through the vertices and change one value in some vertices (the color value). In the past this was possible by creating the buffer with the flag D3DUSAGE_DYNAMIC/D3D11_USAGE_DYNAMIC and using IDirect3DVertexBuffer9::Lock or ID3D11DeviceContext::Map to get a pointer.

What is the correct way to do the same in DX 12? As far as I understand, the method ID3D12Resource::Map cannot be used on a default heap because default heaps cannot be accessed directly from the CPU. The documentation says that upload heaps are intended for CPU-write-once, GPU-read-once usage, so I don't think these are equivalent to the "dynamic" buffers. Is the readback heap equivalent to what was called a dynamic buffer? Or should I create a custom heap?

I am thinking to do the following:

-Create a temporary readback heap.

-Copy the data from the default heap to the readback heap using UpdateSubresources.

-Get a CPU pointer to the readback heap using Map and edit the data.

-Copy the data back to the default heap using UpdateSubresources.

What do you think about this?

There's some discussion on this very same topic going on in this thread, so you should check that out. Broadly speaking, there's two different ways of implementing dynamic buffers that can be updated by the CPU:

  1. Create the the buffer in an UPLOAD heap, and directly write to it from the CPU using the pointer that you get from Map. 
  2. Create the buffer in a DEFAULT heap, and update it by first having the CPU write the data to a temporary buffer in an UPLOAD heap, and then kick off a GPU Copy operation to copy from the UPLOAD resource to the DEFAULT resource.

The first one is easier to start with, since it's simpler. You just need to make sure that you don't write to a buffer that the GPU is currently reading from, which is most easily achieved by having N buffers where N is the number of frames in flight (usually 2). The second one is more useful for cases where the GPU is going to be reading the data multiple times, and/or the buffer is very big and will need maximum bandwidth.

You do not want to use READBACK for this, that's intended for having the CPU read data that was written to by the GPU (as in having the CPU "read back" the data from the GPU).

This topic is closed to new replies.

Advertisement