Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Currently, I create a vertex buffer in SlimDX like so:

SlimDX.Direct3D11.BufferDescription Description = new SlimDX.Direct3D11.BufferDescription();

Description.BindFlags = SlimDX.Direct3D11.BindFlags.VertexBuffer;
Description.CpuAccessFlags = SlimDX.Direct3D11.CpuAccessFlags.Write;
Description.OptionFlags = SlimDX.Direct3D11.ResourceOptionFlags.None;
Description.SizeInBytes = _BufferSize;
Description.StructureByteStride = 0;
Description.Usage = SlimDX.Direct3D11.ResourceUsage.Dynamic;

_Buffer = new SlimDX.Direct3D11.Buffer(Parent.Device, Description);

Which I can update:

DataBox box = _Parent.Context.MapSubresource(_Buffer, 0, _BufferSize, SlimDX.Direct3D11.MapMode.WriteDiscard, SlimDX.Direct3D11.MapFlags.None);
box.Data.Position = destStartPosition * _VertexStride;
/* Where T is my vertex structure type */
box.Data.WriteRange<T>(data);
_Parent.Context.UnmapSubresource(_Buffer, 0);

My first question is about the MapSubresource parameter MapMode.WriteDiscard: when the documentation says

"the previous contents of the resource will be undefined"

, does that mean that if I only update part of the buffer, when it is unmapped the remainder could become anything? Or simply that if I read from the DataStream there is no guarantee what I am reading will be valid?

Second, if I specify MapMode.Write, SlimDX will throw an exception (E_INVALIDARG: An invalid parameter was passed to the returning function (-2147024809)). Why is this? The documentation says that I only need to have a writeable buffer for this to be valid, which I do, because that is the same requirement for WriteDiscard which I can pass successfully.

One last question, if I specify:

Description.CpuAccessFlags = (SlimDX.Direct3D11.CpuAccessFlags.Write | SlimDX.Direct3D11.CpuAccessFlags.Read);
Description.Usage = (SlimDX.Direct3D11.ResourceUsage.Dynamic | SlimDX.Direct3D11.ResourceUsage.Staging);

The same exception is thrown, but this is the only combination of flags I can see that would give me a ReadWrite buffer, how can I create one?

share|improve this question
add comment

1 Answer

up vote 4 down vote accepted

I'm not sure it's actually possible to do this, and even if it's possible I doubt it's a good idea. When you run a graphics application, the CPU and GPU are both running at the same time - the GPU is rendering frame n while the CPU is setting up frame n+1. This means any resources, like buffers, that are generated on the CPU and consumed on the GPU need to be double-buffered. There are two (sometimes more) copies of the buffer, one for the CPU to write the next frame's data, and one for the GPU to read the last frame's data. The two get swapped when the CPU hands off a new frame to the GPU (that is, when you call Present).

The Direct3D API hides all the details of this and makes it look like you just have just one buffer. When you map the buffer using WriteDiscard, you're getting the "next frame" copy of the buffer - it does NOT have last frame's data in it (it may have the data from two frames ago, but there are no guarantees). However, if you try to map the buffer in regular read/write mode, you're asking for the "last frame" copy of it - the one currently being consumed by the GPU! The API has to either stall until the GPU finishes rendering, or internally make a copy of the buffer, both of which are expensive operations.

Now, I'm not sure why you're getting an error, as my understanding of the API is that this is legal, even if it's a bad idea. However, this seems like a case where you should think about what you're doing at a higher level and see if there's a way to accomplish that without needing to map a resource that the GPU is currently consuming.

As for your question about combinations of Usage and CPUAccess - when having problems with a wrapper like SlimDX it's often a good idea to go to the source: the real D3D11 docs. :)

Finally, note that the usage is an enum, not flags, so you can't OR multiple usages together like you tried to do in that last code fragment. You only get to pick one usage.

share|improve this answer
    
Thank you Nathan, that makes the use of the Usage setting much clearer. As for the reason, it was more a 'wood-for-trees' case - the SlimDX documentation for MapMode hinted at ReadWrite capabilities so I was preoccupied with why I couldn't use them, currently there is no case in which I would require a read/write buffer. –  sebf Oct 8 '11 at 18:53
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.