Skip to content
March 25, 2011 / racoonacoon

Getting Direct Access to the DepthBuffer in DirectX10

One of the cool things about DirectX 10 is that it allows you to get direct access to the depth buffer. This is in contrast to DirectX 9, which forces the hapless programmer to either run a separate rendering pass to get the depth information, which consumes more GPU cycles, or use Multiple Render Targets (MRTs) to get the depth information in a single pass at the cost of using additional memory. Needless to say, direct depth buffer access was a God send.

Or so I assumed. It was to my surprise that I couldn’t easily find DDBA (Direct Depth Buffer Access) information on the internets. It took a decent amount of searching (and playing around) to get the code up and working, but I’m glad to say that it works now!

Since it took me some time to get it working, I’ll go ahead and post what I did here to help anyone else attempting this handy technique.

Setting up the Depth View

The first thing you need to do to get DDBA working is setting up a view into your depth buffer that allows it to be bound to a shader. The code is a bit lengthy to post here directly, so I pasted it over at pastebin instead. The code is somewhat tailored for use with Claudius, but it should be raw enough to understand.

Accessing the Depth Buffer

Once you have the appropriate depth view set up, the next step is binding the depth buffer to the shader that needs it. But wait! The Depth Buffer cannot be set on the Graphics Device when you set it to the shader. If it is there will be no compile errors, but the depth buffer will be cleared to black. Getting around this problem is trivial, simply pass in NULL to the DepthStencilView portion of GraphicsDevice->OMSetRenderTargets. When you are finished with your shader, restore the buffer as before. I’m doing something like this:

GraphicsManager::GraphicsDevice->OMSetRenderTargets(1, &GraphicsManager::RenderTargetView, NULL);

//Set depth buffer to shader and render.

GraphicsManager::GraphicsDevice->OMSetRenderTargets(1, &GraphicsManager::RenderTargetView, GraphicsManager::DepthStencilView);

Working with the Shaders

When reading in the Depth Buffer inside your shader it is important that you do not use the Sample function. Sample applies Mip and SamplerState calculations to the result and thus could distort the data. Instead we want to read the data directly from the texture without modifying it in any way. This can be accomplished with the Load function. Load takes in a uint3 (A three unit vector  of unsigned ints). The first two values are the x and y positions to sample, and the third value is the mip level to sample from (0 in our case). An interesting side note: Load does not use uv coordinates to sample from the texture. Rather, it uses actual pixel coordinates. We can get the correct positions by using the data inside the SV_POSITION semantic as shown in pastebin.

 

So there you go, you now have the basics necessary to get DDBA working! Oh, I should probably note one issue with this technique. DDBA does not work in DirectX10 if your depth buffer is multisampled. You will have to use 10.1 and up to get that feature. Our game currently does not use multisampling, so this isn’t an issue at the moment.

 

So now CJ can use the Depth Buffer information to build some more realistic water. I look forward to seeing what he comes up with :)

About these ads

10 Comments

Leave a Comment
  1. jh / Mar 25 2011 8:19 pm

    If you’re using stencil buffers, your depth buffer only has 24 bits of precision as opposed to the 32 bits that an R32F render target gets you. But that only matters if you really need all the precision you can get — for the effects you’re looking at here, it likely isn’t an issue. :-)

  2. racoonacoon / Mar 25 2011 9:02 pm

    Thanks for the heads up jh.

  3. bras / May 19 2011 7:14 pm

    Could you post a simple example using this technique? I am new in DirectX and I need the depth info from a scene.

    Thanks.

    • racoonacoon / May 19 2011 7:36 pm

      I’ll see if I can cook something up ;)

    • racoonacoon / May 20 2011 8:01 pm

      Hey bras, I created a sample and posted it on my general programming blog here

      Hope it helps.

  4. rudi / Feb 21 2013 1:18 pm

    I have a couple of problems with getting your shader code to work on Windows Phone 8. First of all, I can’t directly access the data in the SV_POSITION semantic (error X4502: Shader model ps_4_0_level_9_3 doesn’t allow reading from position semantics.)
    When I send the position data separately to the pixel shader there is another problem with the Texture2d.Load function (error X4532: cannot map expression to pixel shader instruction set). As you can probably imagine, this is very frustrating so I would be glad if you could help.

    • racoonacoon / Mar 23 2013 1:38 am

      Hey there rudi,
      I’m not all that up to speed when it comes to DirectX 11, but I believe the problem is the level_9_3 feature set you are using. This is basically saying to DX11 “Hey dude, act like you are DirectX 9, cool?” This likely causes some issues, as DX9 has more constraints when it comes to HLSL than DX11 does.

      I could be wrong, however. Besides doing some conceptual study on DirectX 11 and Feature Levels I have not actually used them. Does WinPhone8 limit you to 9_3? If not, you could moving the bar up a bit.

  5. Cruoris / Aug 13 2013 5:37 pm

    I really had problems when i tried to get it working, because it is like you said. There are no resources about how to do it. But your little tutorial helped me out. My bad that i tried to first set the
    texture as a ps resource and then set the depthstenciltarget to nullptr. Now its working.

    THANKS!

Trackbacks

  1. Growing Pains « bitwisegames
  2. Getting Direct Access to the Depth Buffer in DirectX 10 | Enigmatic Fish

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: