Questions about Map/UpdateSubResource

Started by
18 comments, last by 360GAMZ 12 years, 2 months ago
I'm finding the whole change from Lock/Unlock to Map/Unmap and UpdateSubResource to be a little perplexing.

So, here's how I handle when to use Map and when to use UpdateSubResource:
For dynamic usage buffers, I use Map/Unmap (UpdateSubResource doesn't like dynamic from what I gather), and for default usage I use UpdateSubResource. Is this a good rule of thumb? Or does this change depending on the type of buffer? For constant buffers I tend to just use default usage and UpdateSubResource, but I've read that UpdateSubResource for Textures and Vertex/Index buffers is on the slow side.

Secondly, with Lock in D3D9, you can Lock a region of the buffer. Am I able to Map a region of a buffer? Or how about UpdateSubResource on a particular portion of the buffer? I've read that when you update a constant buffer, you have to do the entire buffer. For textures you can update a region of the buffer, and for vertex/index buffers... well, I've read about people suggesting to update a portion of those buffers, but I've not found any concrete examples of anyone actually doing it. So is it possible with Vertex/Index buffers? If you can, how in the hell do you map it out so that you map at an offset of 16 bytes in the buffer and a range of 32 bytes? This whole stride/index/rowpitch thing is a little weird for a linear buffer.

I'm not a big fan of the API layout thus far. Having the Map/UpdateSubResource on the context and not the object with the "kitchen sink" parameters is a little more than confusing and what I've found in the docs don't really explain in detail what applies to what, or more accurately, they don't seem to say what -not- to do.

Sorry if this all sounds really dumb, but I'm quite new to the API and trying to make sense of it. Thanks in advance for any insight.
Advertisement
Map is used to map a complete subresource - for buffers that means the whole buffer, and for textures that can mean a lot of different things depending on the dimension, array size, and mip levels. UpdateSubResource has the ability to update only a portion of a subresource, which can be an advantage in some cases.

I personally use Map to update my constant buffers in Hieroglyph3, but I think either method can be used...

Map is used to map a complete subresource - for buffers that means the whole buffer, and for textures that can mean a lot of different things depending on the dimension, array size, and mip levels. UpdateSubResource has the ability to update only a portion of a subresource, which can be an advantage in some cases.


How do you map a subresource into a position in an array of another?

[quote name='Jason Z' timestamp='1327099831' post='4904714']
Map is used to map a complete subresource - for buffers that means the whole buffer, and for textures that can mean a lot of different things depending on the dimension, array size, and mip levels. UpdateSubResource has the ability to update only a portion of a subresource, which can be an advantage in some cases.


How do you map a subresource into a position in an array of another?
[/quote]Sorry, I don't understand the question - do you mean mapping a texture subresource to another texture array subresource? If so, then for mapping you just map the two subresources and then copy the data directly. With UpdateSubResource you more or less specify the locations in the parameter arguments and the function does the copying for you.
In general, I believe dynamic buffers are best if you want to use them the same frame as you update them. If you have a lot of data and want to update once and then use the same data multiple times on the GPU, default buffers with UpdateSubResource are probably better.

[quote name='jsedlak' timestamp='1327117203' post='4904749']
[quote name='Jason Z' timestamp='1327099831' post='4904714']
Map is used to map a complete subresource - for buffers that means the whole buffer, and for textures that can mean a lot of different things depending on the dimension, array size, and mip levels. UpdateSubResource has the ability to update only a portion of a subresource, which can be an advantage in some cases.


How do you map a subresource into a position in an array of another?
[/quote]Sorry, I don't understand the question - do you mean mapping a texture subresource to another texture array subresource? If so, then for mapping you just map the two subresources and then copy the data directly. With UpdateSubResource you more or less specify the locations in the parameter arguments and the function does the copying for you.
[/quote]

I'm probably not asking the right question... (and yes, sorry for the hijack)
http://www.gamedev.net/topic/618817-using-texture2darray-and-shaderresourceview/

Map is used to map a complete subresource - for buffers that means the whole buffer, and for textures that can mean a lot of different things depending on the dimension, array size, and mip levels. UpdateSubResource has the ability to update only a portion of a subresource, which can be an advantage in some cases.

I personally use Map to update my constant buffers in Hieroglyph3, but I think either method can be used...


So, you can update a portion of a vertex buffer with UpdateSubResource then? I'm just wondering how I would pass the offset within the buffer and the number of bytes to update to the UpdateSubResource method? Can you use UpdateSubResource to update a portion of a constant buffer?
You can also update just part of it with Map, if you use D3D11_MAP_WRITE instead of D3D11_MAP_WRITE_DISCARD. I'm not sure what restrictions apply to the usage and bind-flags for uncommon cases, but that is easy to look up or test.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476181%28v=vs.85%29.aspx
You probably don't want to do that for a constant-buffer, as they are usually relatively small. Doubtful it's ever worth it compared to overwriting the whole thing with a discarding map.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476259%28v=vs.85%29.aspx has additional discussion on dynamic usage.
In the remarks on this page, it explicitly says that you can't update a portion of a constant buffer, but there is no mention of doing it for a vertex buffer (although it mentions updating vertex buffers in general, so it should be possible). I've never explicitly tried it, but I would assume that you use the same addressing concept for the destination box as you would for a 1D texture (there is also a sample of that on the link above).

It would probably be worth doing a quick test, where you create a vertex buffer that is all zeros, then update only the second element with all ones. If it works in that case (which can be verified with PIX) then you should be good to go.

As a side note, the two methods are similar enough that it shouldn't be too hard to build support for either method and dynamically decide which one to use. This would be ideal so that you can profile and see how fast one or the other is. In the end, they both end up doing the same thing - copying data from CPU memory to a resource in GPU memory. There is some difference in the way that the driver handles it, but I suspect there isn't much performance difference between the two methods. To be honest, I've never heard anyone say that one is better than the other...

And one final point - notice the comments about deferred contexts at the bottom of the linked page!

EDIT: I also found this link, which has some good discussion about the topic. In there it says that mapping a buffer uses bytes in the D3D11_BOX, while textures use pixels for the units...

You can also update just part of it with Map, if you use D3D11_MAP_WRITE instead of D3D11_MAP_WRITE_DISCARD. I'm not sure what restrictions apply to the usage and bind-flags for uncommon cases, but that is easy to look up or test.
http://msdn.microsof...v=vs.85%29.aspx
You probably don't want to do that for a constant-buffer, as they are usually relatively small. Doubtful it's ever worth it compared to overwriting the whole thing with a discarding map.
http://msdn.microsof...v=vs.85%29.aspx has additional discussion on dynamic usage.

Mapping with write will end up mapping the whole sub-resource too, as far as I know. There are some specialized cases where a vertex or index buffer can be partially updated with WRITE_DISCARD and WRITE_NO_OVERWRITE flags, but they are very special cases (building dynamic vertex / index buffers as opposed to dynamically updating the contents of the buffers).

This topic is closed to new replies.

Advertisement