0
\$\begingroup\$

Good morning,

I have an Indexbuffer created with usage D3D11_USAGE_DEFAULT and CPUAccessFlags 0. Now I want to read data from this buffer regularly (it is a terrain index buffer). But the problem is that I am not allowed to read data from the buffer, because the buffer is not created with the flag D3D11_CPU_ACCESS_READ.

Even if I make the buffer dynamic, I still am not allowed to read from the buffer. This is because the CPUAccessFlag D3D11_CPU_ACCESS_READ is not allowed to be used together with usage D3D11_USAGE_DYNAMIC.

Could anyone please give me advice on how to properly read data from a vertex or index buffer in Direct3D11. In my case I want to read data from it frequently.

\$\endgroup\$
2
\$\begingroup\$

You really don't want to read from buffers because you never know where it is in the pipeline and you will normally end up with +20ms of GPU-CPU synchronization.

Even with a copy to a staging resource marked for reading you will still have a large stall if the buffer is still in use on the GPU before you copy it to the staging resource.

If you need access to the vertex\index buffer then just use the CPU side data you had before you built your buffer and then just reupload with a map\unmap or updatesubresource call if the data has changed.

To read from a buffer that is non readable you first need to setup a staging resource that can not be bound to the pipeline in anyway then you copy your vertex\index buffer to the staging resource and then read from that buffer.

Setting up the staging resource:

bufferDescription.BindFlags = BindFlags.None;
bufferDescription.SizeInBytes = TerrainVertex.Stride;   //your terrain vertex size * count
bufferDescription.StructureByteStride = TerrainVertex.Stride;   // your terrain vertex size
bufferDescription.OptionFlags = ResourceOptionFlags.BufferStructured;
bufferDescription.CpuAccessFlags = CpuAccessFlags.Read;
bufferDescription.Usage = ResourceUsage.Staging;

DebugBuffer = _device.CreateBuffer(bufferDescription);

Copy the buffer:

// You should wait a few frames before you try to use the Debugbuffer as the copy is async and will stall the pipeline if you try to use it before the copy is done by the GPU

_Context.CopyResource(CurrentTerrainVertexBuffer, DebugBuffer);

Reading the Staging resource:

TerrainVertex[] CPUTerrainData = new TerrainVertex[vertcoun - 1] {};

DataBox dbox = _context.MapSubresource(DebugBuffer, 0, MapMode.Read, Direct3D11.MapFlags.None);
readout(dbox.DataPointer, CPUTerrainData);
_context.UnmapSubresource(DebugBuffer, 0);
dbox = null;

I'm using sharpDX but its only a wrapper around nativeDX so you should be able to work out what I'm doing as the naming is very close between sharpDX and nativeDX.

Once again this will be slow so as long as you don't want to do it every frame you should be ok and remember that GPU-CPU sync time is +20ms so do not read from the staging resource until a few frames have passed so you can avoid a stall if the GPU hasn't copied the data yet.

\$\endgroup\$
  • \$\begingroup\$ I considered your idea, but the problem is that the terrain has millions of vertices and indices. It would use a lot of memory. I hoped that there was a better solution because in Direct3D9 it is possible to read from index/vertex buffers. \$\endgroup\$ – Joey Muiser Jan 8 '17 at 23:02
  • \$\begingroup\$ like I said you can read from index and vertex buffers but its slow. I have a few billion vertices and indices in my terrain and its not that much data to store. Ill update my answer with the staging resource stuff I was talking about \$\endgroup\$ – Justin William Stanley Bryant Jan 8 '17 at 23:13
  • \$\begingroup\$ You were right about millions of vertices in the terrain not being too much of a big deal. I went that way and I am happy with it so far =). At buffer creation I simply memcpy the vertices to my CPU copy. Whenever I want to update the dynamic buffer I edit the CPU copy and call Map(). I think that is what you suggested. Also thanks for the explanation of the staging stuff. \$\endgroup\$ – Joey Muiser Jan 11 '17 at 10:28

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.