0
\$\begingroup\$

I've looked through a lot of archives but still cannot figure out how it works. Taking this overridden one for example. public DataBox MapSubresource(Buffer resource, MapMode mode, MapFlags flags, out DataStream stream)

  1. Is this method aiming to change the resource with stream. If it is, why would the stream be marked out as if it is an output value rather than input?
  2. If the above one is true, where can I stream my data into the stream to update the buffer? Has it to be between the Map and Unmap methods? And typically how should I stream it (Take vertex buffer for example, what would the format of streaming be like?)
  3. Is it advisable to call the MapSubresource method whenever GPU access is finished(after every frame), and call the UnmapSubresource next frame to allow GPU access so it may save more time when I am keep updating the data?

Thank you!

| improve this question | | | | |
\$\endgroup\$
0
\$\begingroup\$

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.

| improve this answer | | | | |
\$\endgroup\$
  • \$\begingroup\$ Thank you, but I don't think I should use MapMode.WriteDiscard if I want to keep the original data in the buffer, right? Does mapping take a lot of time if I want to update many times in a frame? \$\endgroup\$ – 王凯越 Kaiyue Wang Nov 6 '16 at 8:44
  • \$\begingroup\$ Mapping is fast, I do it for all my instance\particle\any other buffer and its very fast. Why do you want to keep the old data? what data are you adding? More info because maybe in can update my answer. \$\endgroup\$ – Justin William Stanley Bryant Nov 6 '16 at 8:51
  • \$\begingroup\$ I am expecting to make a scatter plot. I keep the original ones while adding new points on it \$\endgroup\$ – 王凯越 Kaiyue Wang Nov 6 '16 at 11:46
  • \$\begingroup\$ And, also, do you know what the equivalence is for Utilities.WriteAndPosition in C#. I didn't even know that SharpDX can work in VB before \$\endgroup\$ – 王凯越 Kaiyue Wang Nov 6 '16 at 13:51
  • \$\begingroup\$ Utilities.WriteAndPosition is a sharpDX function, look in sharpDX.Utilities. I never keep values around I just resend them all to the GPU at once every time. Ill update my answer with a bit more info, have a look in 10-15mins \$\endgroup\$ – Justin William Stanley Bryant Nov 6 '16 at 22:42

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.