Sign in to follow this  
BornToCode

DX11 DirectX 11 Buffer Headache

Recommended Posts

BornToCode    1185

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.

Edited by BornToCode

Share this post


Link to post
Share on other sites
Tape_Worm    2807

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.

Share this post


Link to post
Share on other sites
Jason Z    6434

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...

Share this post


Link to post
Share on other sites
MJP    19754

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.

Share this post


Link to post
Share on other sites
BornToCode    1185

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.

Edited by BornToCode

Share this post


Link to post
Share on other sites
Jason Z    6434

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.

Share this post


Link to post
Share on other sites
BornToCode    1185

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.

Edited by BornToCode

Share this post


Link to post
Share on other sites
Jason Z    6434

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).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By gsc
      Hi! I am trying to implement simple SSAO postprocess. The main source of my knowledge on this topic is that awesome tutorial.
      But unfortunately something doesn't work... And after a few long hours I need some help. Here is my hlsl shader:
      float3 randVec = _noise * 2.0f - 1.0f; // noise: vec: {[0;1], [0;1], 0} float3 tangent = normalize(randVec - normalVS * dot(randVec, normalVS)); float3 bitangent = cross(tangent, normalVS); float3x3 TBN = float3x3(tangent, bitangent, normalVS); float occlusion = 0.0; for (int i = 0; i < kernelSize; ++i) { float3 samplePos = samples[i].xyz; // samples: {[-1;1], [-1;1], [0;1]} samplePos = mul(samplePos, TBN); samplePos = positionVS.xyz + samplePos * ssaoRadius; float4 offset = float4(samplePos, 1.0f); offset = mul(offset, projectionMatrix); offset.xy /= offset.w; offset.y = -offset.y; offset.xy = offset.xy * 0.5f + 0.5f; float sampleDepth = tex_4.Sample(textureSampler, offset.xy).a; sampleDepth = vsPosFromDepth(sampleDepth, offset.xy).z; const float threshold = 0.025f; float rangeCheck = abs(positionVS.z - sampleDepth) < ssaoRadius ? 1.0 : 0.0; occlusion += (sampleDepth <= samplePos.z + threshold ? 1.0 : 0.0) * rangeCheck; } occlusion = saturate(1 - (occlusion / kernelSize)); And current result: http://imgur.com/UX2X1fc
      I will really appreciate for any advice!
    • By isu diss
       I'm trying to code Rayleigh part of Nishita's model (Display Method of the Sky Color Taking into Account Multiple Scattering). I get black screen no colors. Can anyone find the issue for me?
       
      #define InnerRadius 6320000 #define OutterRadius 6420000 #define PI 3.141592653 #define Isteps 20 #define Ksteps 10 static float3 RayleighCoeffs = float3(6.55e-6, 1.73e-5, 2.30e-5); RWTexture2D<float4> SkyColors : register (u0); cbuffer CSCONSTANTBUF : register( b0 ) { float fHeight; float3 vSunDir; } float Density(float Height) { return exp(-Height/8340); } float RaySphereIntersection(float3 RayOrigin, float3 RayDirection, float3 SphereOrigin, float Radius) { float t1, t0; float3 L = SphereOrigin - RayOrigin; float tCA = dot(L, RayDirection); if (tCA < 0) return -1; float lenL = length(L); float D2 = (lenL*lenL) - (tCA*tCA); float Radius2 = (Radius*Radius); if (D2<=Radius2) { float tHC = sqrt(Radius2 - D2); t0 = tCA-tHC; t1 = tCA+tHC; } else return -1; return t1; } float RayleighPhaseFunction(float cosTheta) { return ((3/(16*PI))*(1+cosTheta*cosTheta)); } float OpticalDepth(float3 StartPosition, float3 EndPosition) { float3 Direction = normalize(EndPosition - StartPosition); float RayLength = RaySphereIntersection(StartPosition, Direction, float3(0, 0, 0), OutterRadius); float SampleLength = RayLength / Isteps; float3 tmpPos = StartPosition + 0.5 * SampleLength * Direction; float tmp; for (int i=0; i<Isteps; i++) { tmp += Density(length(tmpPos)-InnerRadius); tmpPos += SampleLength * Direction; } return tmp*SampleLength; } static float fExposure = -2; float3 HDR( float3 LDR) { return 1.0f - exp( fExposure * LDR ); } [numthreads(32, 32, 1)] //disptach 8, 8, 1 it's 256 by 256 image void ComputeSky(uint3 DTID : SV_DispatchThreadID) { float X = ((2 * DTID.x) / 255) - 1; float Y = 1 - ((2 * DTID.y) / 255); float r = sqrt(((X*X)+(Y*Y))); float Theta = r * (PI); float Phi = atan2(Y, X); static float3 Eye = float3(0, 10, 0); float ViewOD = 0, SunOD = 0, tmpDensity = 0; float3 Attenuation = 0, tmp = 0, Irgb = 0; //if (r<=1) { float3 ViewDir = normalize(float3(sin(Theta)*cos(Phi), cos(Theta),sin(Theta)*sin(Phi) )); float ViewRayLength = RaySphereIntersection(Eye, ViewDir, float3(0, 0, 0), OutterRadius); float SampleLength = ViewRayLength / Ksteps; //vSunDir = normalize(vSunDir); float cosTheta = dot(normalize(vSunDir), ViewDir); float3 tmpPos = Eye + 0.5 * SampleLength * ViewDir; for(int k=0; k<Ksteps; k++) { float SunRayLength = RaySphereIntersection(tmpPos, vSunDir, float3(0, 0, 0), OutterRadius); float3 TopAtmosphere = tmpPos + SunRayLength*vSunDir; ViewOD = OpticalDepth(Eye, tmpPos); SunOD = OpticalDepth(tmpPos, TopAtmosphere); tmpDensity = Density(length(tmpPos)-InnerRadius); Attenuation = exp(-RayleighCoeffs*(ViewOD+SunOD)); tmp += tmpDensity*Attenuation; tmpPos += SampleLength * ViewDir; } Irgb = RayleighCoeffs*RayleighPhaseFunction(cosTheta)*tmp*SampleLength; SkyColors[DTID.xy] = float4(Irgb, 1); } }  
    • By amadeus12
      I made my obj parser
      and It also calculate tagent space for normalmap.
      it seems calculation is wrong..
      any good suggestion for this?
      I can't upload my pics so I link my question.
      https://gamedev.stackexchange.com/questions/147199/how-to-debug-calculating-tangent-space
      and I uploaded my code here


      ObjLoader.cpp
      ObjLoader.h
    • By Alessandro Pozzer
      Hi guys, 

      I dont know if this is the right section, but I did not know where to post this. 
      I am implementing a day night cycle on my game engine and I was wondering if there was a nice way to interpolate properly between warm colors, such as orange (sunset) and dark blue (night) color. I am using HSL format.
      Thank  you.
    • By thefoxbard
      I am aiming to learn Windows Forms with the purpose of creating some game-related tools, but since I know absolutely nothing about Windows Forms yet, I wonder:
      Is it possible to render a Direct3D 11 viewport inside a Windows Form Application? I see a lot of game editors that have a region of the window reserved for displaying and manipulating a 3D or 2D scene. That's what I am aiming for.
      Otherwise, would you suggest another library to create a GUI for game-related tools?
       
      EDIT:
      I've found a tutorial here in gamedev that shows a solution:
      Though it's for D3D9, I'm not sure if it would work for D3D11?
       
  • Popular Now