Best way to write to a dynamic buffer is like this:
//Build Grass Buffer
Dim BufferDescription As New BufferDescription() With {
.BindFlags = BindFlags.ShaderResource,
.SizeInBytes = GrassNode.Stride * 85000,
.StructureByteStride = GrassNode.Stride,
.OptionFlags = ResourceOptionFlags.BufferStructured,
.CpuAccessFlags = CpuAccessFlags.Write,
.Usage = ResourceUsage.Dynamic
}
Dim srvDescription As New ShaderResourceViewDescription() With {
.Dimension = ShaderResourceViewDimension.Buffer,
.Format = DXGI.Format.Unknown,
.Buffer = New ShaderResourceViewDescription.BufferResource() With {
.FirstElement = 0,
.ElementCount = 85000
}
}
GrassNodesBuffer = _Device.CreateBuffer(BufferDescription)
GrassNodesView = _Device.CreateShaderResourceView(GrassNodesBuffer, srvDescription)
//Map
Dim dbox As DataBox = _context.MapSubresource(GrassNodesBuffer, 0, MapMode.WriteDiscard, Direct3D11.MapFlags.None)
Dim offset As IntPtr = dbox.DataPointer
//Write
For gg As Integer = 0 To ccnode.Grass.Count - 1
offset = Utilities.WriteAndPosition(offset, ccnode.Grass(gg))
Next
//Unmap
_context.UnmapSubresource(GrassNodesBuffer, 0)
dbox = Nothing
This way you don't need a datastream and you can write directly to the unmanged memory. Its faster and much less garbage.
I call map just before I need to write to the buffer, with MapMode.WriteDiscard you get new memory each time, that way you don't really need to worry about whats happening on the GPU, just write the data and render when needed.
I try do all my mapping and updatesubresource stuff at the start of the frame and use copyresource or copyresource if I need to update stuff later in the frame.
I update most of my perframe buffers this way.
As per the MSDN docs on the usage pattern D3D11_MAP_WRITE_NO_OVERWRITE, can only be used for vertex or index buffers
D3D11_MAP_WRITE_NO_OVERWRITE
Resource is mapped for writing; the existing contents of the resource cannot > be overwritten (see Remarks). This flag is only valid on vertex and index buffers. The resource must have been created with write access (see D3D11_CPU_ACCESS_WRITE). Cannot be used on a resource created with the D3D11_BIND_CONSTANT_BUFFER flag.
A common use of these two flags involves filling dynamic index/vertex buffers with geometry that can be seen from the camera's current position. The first time that data is entered into the buffer on a given frame, Map is called with D3D11_MAP_WRITE_DISCARD; doing so invalidates the previous contents of the buffer. The buffer is then filled with all available data.
Subsequent writes to the buffer within the same frame should use D3D11_MAP_WRITE_NO_OVERWRITE. This will enable the CPU to access a resource that is potentially being used by the GPU as long as the restrictions described previously are respected.
My understanding is that you only use D3D11_MAP_WRITE_NO_OVERWRITE if you plan on writing to the buffer more than once per frame and I have never found a use for that so I just use D3D11_MAP_WRITE_DISCARD.