DirectX 11 Buffer Headache

Started by
6 comments, last by Jason Z 10 years, 9 months ago

The topic says it all. In DirectX 9 you can create a Vertex/Index buffer and then when you map it you give it an hint to tell it how you are going to access the buffer, easy to use. In DirectX 11 on the other hand we can no longer specify the map type unless CPUAccessResource is set to either Read,Write or Read/Write which is ok. But the problem comes from whenever you have a READ/WRITE resource the resource cannot be bind to anything. DX11 Provide different Access flags, but there is no flags that I can set where I can access the resource as a Read/Write on the CPU and at the same time have it bind to an vertex or index buffer. So how in DirectX11 are you supposed to create a buffer that you want to READ/Write from on the CPU side and be able to use that same buffer to render onto the screen. The buffer system in DirectX11 is definitely a step backward. If anyone has any idea, please let me know. Because right now the only way I can see to do that is to create an Staging resource and a Dynamic resource. Then copy staging resource data to the dynamic resource using an map. Doing that would force me to duplicate buffers, so I know there has to be a better way to do this.

Advertisement

The topic says it all. In DirectX 9 you can create a Vertex/Index buffer and then when you map it you give it an hint to tell it how you are going to access the buffer, easy to use. In DirectX 11 on the other hand we can no longer specify the map type unless CPUAccessResource is set to either Read,Write or Read/Write which is ok. But the problem comes from whenever you have a READ/WRITE resource the resource cannot be bind to anything. DX11 Provide different Access flags, but there is no flags that I can set where I can access the resource as a Read/Write on the CPU and at the same time have it bind to an vertex or index buffer. So how in DirectX11 are you supposed to create a buffer that you want to READ/Write from on the CPU side and be able to use that same buffer to render onto the screen. The buffer system in DirectX11 is definitely a step backward. If anyone has any idea, please let me know. Because right now the only way I can see to do that is to create an Staging resource and a Dynamic resource. Then copy staging resource data to the dynamic resource using an map. Doing that would force me to duplicate buffers, so I know there has to be a better way to do this.

It'd be helpful if we knew why you're reading back data from the buffer on the CPU? That sounds a little counterproductive to me.

Are you saying that the issue is that you can't map the buffer while it is bound to the pipeline? If so, why don't you just un-bind it by setting a null to that buffer slot?

Vertex and index buffers most certainly can be mapped and directly used, so I'm not really sure what the issue is that you are facing...

The old D9D9 way of dealing with resources was completely broken in terms of how GPU's actually work. When you put a resource in GPU memory it's no longer accessible to the CPU, since it's a completely different memory pool that's not accessible to userspace code. In order to support the old (broken) D3D9 semantics drivers had to do crazy things behind the scenes, and the D3D runtime usually had to keep a separate copy of the resource contents in CPU memory. Starting with D3D10 they cleaned all of this up in order to better reflect the way CPU's work, and to also force programs to use the "fast path" by default by not giving them traps to fall into that would cause performance degradation or excessive memory allocation by the runtime or driver. Part of this is that you can no longer just grab GPU resources on the CPU, and you have explicitly specify up-front what behavior you want from a resource.

That said, why would you ever need to read back vertex buffer data? If you've provided the data, then you surely already have access to that data and you can keep it around for later. You wouldn't be wasting any memory compared to the old D3D9 behavior or using a staging buffer, and it would be more efficient to boot.

Are you saying that the issue is that you can't map the buffer while it is bound to the pipeline? If so, why don't you just un-bind it by setting a null to that buffer slot?

Vertex and index buffers most certainly can be mapped and directly used, so I'm not really sure what the issue is that you are facing...

I am not talking about when I am binding it through the binding stage. I mean at creation time when setting the Bind Flags stages the buffer will mapped to. The Bind

Flag stage can only be set if the buffer will not be read from the CPU which means staging. Therefore preventing me from creating any type of resource view using the buffer.

The old D9D9 way of dealing with resources was completely broken in terms of how GPU's actually work. When you put a resource in GPU memory it's no longer accessible to the CPU, since it's a completely different memory pool that's not accessible to userspace code. In order to support the old (broken) D3D9 semantics drivers had to do crazy things behind the scenes, and the D3D runtime usually had to keep a separate copy of the resource contents in CPU memory. Starting with D3D10 they cleaned all of this up in order to better reflect the way CPU's work, and to also force programs to use the "fast path" by default by not giving them traps to fall into that would cause performance degradation or excessive memory allocation by the runtime or driver. Part of this is that you can no longer just grab GPU resources on the CPU, and you have explicitly specify up-front what behavior you want from a resource.

That said, why would you ever need to read back vertex buffer data? If you've provided the data, then you surely already have access to that data and you can keep it around for later. You wouldn't be wasting any memory compared to the old D3D9 behavior or using a staging buffer, and it would be more efficient to boot.

I know that CPUVM cannot see GPUVM, but that does not matter in that case. Currently the drivers just copies the GPU memory over to the CPU memory whenever you do an map, then copy it back to GPUVM whenever you do Unmap. So those flags are just bogus, all they do is give the driver some hint of which memory pool to put it in.. Even with the implementation of this new system. The driver side has not change on how the buffers are handle today, because CPU still cannot see GPUVM. The only reason they are those restriction is because Microsoft introduced them in the spec. The reason I know about the how the driver works is because last year I work on them. So the two copy in memory in D3D9 like you said is a false statement.

Now to answer your other question, the reason why I want to access it. Let's say I have a buffer X that has been updated and outputted in an OuputStream. How do I read that output stream back on the CPU if I want to that since the CPU cannot read the resource.

Now to answer your other question, the reason why I want to access it. Let's say I have a buffer X that has been updated and outputted in an OuputStream. How do I read that output stream back on the CPU if I want to that since the CPU cannot read the resource.

You use a staging buffer - that is its whole purpose for existing, just to give you CPU read access to the GPU based resource objects. You can write to buffers directly with the appropriate flags, but reading requires a separate buffer. If you don't like hassling with the copy, then just write a small wrapper for your buffers that handles the copying and mirroring of the buffer data for you.

However, I would invest in a technique that could just directly use the stream output buffers without CPU intervention. That will make the whole thing much faster, reducing bandwidth requirements, and eliminating the need for a staging buffer altogether. This of course assumes that you don't need to store the data for whatever reason, but if you are only going to consume the contents then it would be far better just to use it directly.

Now to answer your other question, the reason why I want to access it. Let's say I have a buffer X that has been updated and outputted in an OuputStream. How do I read that output stream back on the CPU if I want to that since the CPU cannot read the resource.

You use a staging buffer - that is its whole purpose for existing, just to give you CPU read access to the GPU based resource objects. You can write to buffers directly with the appropriate flags, but reading requires a separate buffer. If you don't like hassling with the copy, then just write a small wrapper for your buffers that handles the copying and mirroring of the buffer data for you.

However, I would invest in a technique that could just directly use the stream output buffers without CPU intervention. That will make the whole thing much faster, reducing bandwidth requirements, and eliminating the need for a staging buffer altogether. This of course assumes that you don't need to store the data for whatever reason, but if you are only going to consume the contents then it would be far better just to use it directly.

That is what i meant in my first post. I would need to have a staging buffer and and dynamic buffer. Why do i need t o create two buffers. If i did not care about reading the ouput stream, then what you mention would have work and i would not have posted this in the first place. But i want to be able to access the buffer on the CPU for Read Access with a Bind Flag, without having to duplicate anything similar to how DirectX9 works. But it seems like there is no way to do what i want to do in DX11 without having the darn staging buffer. I need to read that buffer on the CPU because after the ouputStream is filled up i am doing something with it on the CPU side. For now i will just do the two buffer route just to get this working. Thanks everyone for the help.

I'm not sure if you saw it yet or not, but in the new features for Direct3D 11.2 there is a new feature which allows mapping of default usage buffers. This fits what you are talking about, and bypasses the staging buffer require in between.

I don't know if Windows 8.1 is a target system for you, but it seems to be in the cards to have this ability. They mentioned in the BUILD presentation that it only works for buffers right now (due to considerations in using the compute shader) but one could foresee this coming to all resources eventually (that's my guess anyways).

This topic is closed to new replies.

Advertisement