8
\$\begingroup\$

From what I understood (from reading various pages) there are 2 ways to update a buffer:

  1. UpdateSubresource() (when buffer is created with DEFAULT usage)
  2. Map(), copy the new data, Unmap() (when buffer is created with DYNAMIC usage)

In the first case do I only call this one function (nothing more)? Because I've seen people say they map the buffer and then update subresource, or maybe I misunderstood them.

Also is there any other way (doubt it :P)? Do I understand things correctly?

\$\endgroup\$
12
\$\begingroup\$

There's a good presentation about this: Don't Throw It All Away: Efficient Buffer Management by John McDonald at NVIDIA. It covers various topics, but on the subject of your question, the general advice is to create buffers with dynamic usage and use Map() with D3D11_MAP_WRITE_DISCARD, when the data needs to be updated frequently (like every frame, or multiple times per frame). This would be used for constant buffers, vertex buffers for particle systems, and suchlike.

According to the presentation, default usage / UpdateSubresource() incurs more CPU overhead than dynamic usage / Map(). However, he does recommend default usage / UpdateSubresource() for data that needs to be updated only once in awhile, such as data streamed in from disk in an open-world game.

And yes, in the case where you use UpdateSubresource(), you would use it by itself, not in combination with Map().

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ Uncanny, you both responded in the same minute and posted the same link. \$\endgroup\$ – NPS Aug 12 '13 at 21:36
  • \$\begingroup\$ In other thread you wrote: "You do not need to bind the buffer to update it with UpdateSubresource. In fact, it shouldn't be bound when you update it". Does this mean I should always unbind all buffers before updating them? If so, how do I unbind a buffer? \$\endgroup\$ – NPS Aug 12 '13 at 22:51
  • 1
    \$\begingroup\$ @NPS First of all, it'll be implicitly unbound if you already bound something else in its place. Otherwise, you can explicitly bind NULL to unbind a buffer. For instance, you can do ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv); to unbind a texture from slot 0. \$\endgroup\$ – Nathan Reed Aug 12 '13 at 23:04
  • \$\begingroup\$ I knew about the implicit one but needed the explicit one, thx. But you didn't answer my first question - do I have to do this always for all buffers that I inted to update? \$\endgroup\$ – NPS Aug 12 '13 at 23:09
  • 1
    \$\begingroup\$ @NPS Ideally, the buffer shouldn't be in use by the GPU at the time when you update it on the CPU. But the GPU and CPU run asynchronously, so this isn't easy to ensure. I would say don't worry about it unless you find it's an actual performance problem. \$\endgroup\$ – Nathan Reed Aug 12 '13 at 23:16
2
\$\begingroup\$

They may have been referring to the actual act of updating a resource and not to the actual function call. In general, UpdateSubResource should be used for default resources that are not subject to frequent updates (i.e.: not every frame. In this case, it is more likely that the buffer could be to be copied to a temporary buffer accessible from the command buffer (due to race conditions for example). It will also allow you the update sub resources (in textures, for example).

Map/Unmap should be used when a resource is going to be updated very frequently (i.e. every frame), such as some constant buffers. The most common case is when you are overwriting the whole buffer with WriteDiscard. There's an nVidia presentation where they reccommend this practice.

| improve this answer | |
\$\endgroup\$

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.