0
\$\begingroup\$

I'm programming a two-pass effect in DirectX 11 (SharpDX). It's supposed to write the depth to a texture in the first pass and then use that texture to extract data on the second one in the pixel shader.

What I get is a white screen, with nothing but the interface and I don't know why nothing is being printed. What could be the problem? I would say I should get at least something from the Depth Texture.

This is how I'm setting the depth texture values:

this.depthBuffer = new Texture2D(device, new Texture2DDescription()
        {
            Format = Format.R32_Typeless,
            ArraySize = 1,
            MipLevels = 1,
            Width = (int)host.ActualWidth,
            Height = (int)host.ActualHeight,
            SampleDescription = new SampleDescription(1, 0),
            Usage = ResourceUsage.Default,
            BindFlags = BindFlags.DepthStencil | BindFlags.ShaderResource,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.None,
        });

this.depthBufferShaderResourceView = new ShaderResourceView(this.device, this.depthBuffer, new ShaderResourceViewDescription()
        {
            Format = Format.R32_Float,
            Dimension = ShaderResourceViewDimension.Texture2D,
            Texture2D = new ShaderResourceViewDescription.Texture2DResource()
            {
                MipLevels = 1,
                MostDetailedMip = 0,
            }
        });
var depthStencilDesc = new DepthStencilStateDescription()
        {
            DepthComparison = Comparison.LessEqual,
            DepthWriteMask = global::SharpDX.Direct3D11.DepthWriteMask.All,
            IsDepthEnabled = true,
        };

And here is how I sample the depth in the .fx file:

int3 posTex = int3(input.p.xy, 0);
float depthPixel = DepthTexture.Load(posTex);
float4 color = float4(depthPixel, depthPixel , depthPixel, 1.0f );
return color;

And here the way I'm now setting the Depth Buffer stencil view as a Render Target in 2 passes. In the first I try to set the depthstencilview as a target. In the second pass I'm trying to set teh depth texture as a shader resource to read from it.

this.device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(this.vertexBuffer, LinesVertex.SizeInBytes, 0));

// PASS 0
this.device.ImmediateContext.OutputMerger.SetTargets(depthBufferStencilView);
this.device.ImmediateContext.ClearDepthStencilView(this.depthBufferStencilView,     DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);
this.technique.GetPassByIndex(0).Apply(this.device.ImmediateContext);
this.device.ImmediateContext.DrawIndexed(this.geometry.Indices.Length, 0, 0);

// PASS 1
this.device.ImmediateContext.OutputMerger.ResetTargets(); // unbinding the depthStencilView

this.device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(this.vertexBuffer, LinesVertex.SizeInBytes, 0));
this.depthStencilShaderResourceVariable = effect.GetVariableByName("DepthTexture").AsShaderResource();
this.depthStencilShaderResourceVariable.SetResource(this.depthBufferShaderResourceView);
this.technique.GetPassByIndex(1).Apply(this.device.ImmediateContext);
this.device.ImmediateContext.DrawIndexed(this.geometry.Indices.Length, 0, 0);

Finally, this is how I set the two passes in the .fx file:

technique11 RenderMyTechnique
{
pass P0
{   

SetDepthStencilState( DSSDepthLessEqual, 0 );
SetVertexShader     ( CompileShader( vs_4_0, VShader() ) );
    SetHullShader       ( NULL );
    SetDomainShader     ( NULL );        
    SetGeometryShader   ( NULL  );
SetPixelShader      ( NULL );
}

pass P1
{
SetDepthStencilState( DSSDepthLessEqual, 0 );
SetVertexShader     ( CompileShader( vs_4_0, VShader() ) );
    SetHullShader       ( NULL );
    SetDomainShader     ( NULL );        
    SetGeometryShader   ( CompileShader( gs_4_0, GShader() ) );
SetPixelShader      ( CompileShader( ps_4_0, PShader() ) );
}
}
\$\endgroup\$
5
  • \$\begingroup\$ Obvious question: Are you actually writing to the depth buffer for sure? \$\endgroup\$ Commented Nov 14, 2013 at 18:13
  • \$\begingroup\$ how can I be sure? I thought it was just always done. \$\endgroup\$
    – c4sh
    Commented Nov 14, 2013 at 18:20
  • \$\begingroup\$ @c4sh You also have to create a DepthStencilView of the buffer (using the D32_FLOAT format) and pass it in your SetRenderTargets call. \$\endgroup\$ Commented Nov 14, 2013 at 18:23
  • \$\begingroup\$ @c4sh: You also have to make sure that DepthWrite is turned on in your DepthStencilState bound to the context when rendering when you render your scene. I don't recall if it's set by default, but it might not be. \$\endgroup\$ Commented Nov 14, 2013 at 18:35
  • \$\begingroup\$ Following the comments I passed the DepthStencilView to my SetRenderTargets call and set a DepthStencilState with IsDepthEnabled as true (added the DepthStencilStateDescription in the question. (see changes in question) So I realized I'm now getting always a 1.0f because I'm clearing the DepthBuffer to 1.0f. So I'm not writing on it, the thing is I don't know why I'm not writing to it..? @NathanReed @SeanMiddleditch \$\endgroup\$
    – c4sh
    Commented Nov 15, 2013 at 15:01

1 Answer 1

1
\$\begingroup\$

My guess would be that you've bound the texture for reading and writing at the same time (i.e. it's the current depth buffer). DX11 won't let you do that (the debug runtime should give you an error message about it).

Also note that it decides what the current depth buffer is at the time you bind the shader resource, and not at draw call time so you want to bind the correct set of render targets before binding any shader resources.

There are three solutions:

  1. Unbind the depth buffer while reading from it in a shader. This assumes you don't need depth testing.
  2. Copy the depth buffer at some point, and read from the copy. This is clearly the slowest option.
  3. Bind the depth buffer as read only. This won't work on 10.0 or 10.1 hardware.
\$\endgroup\$
4
  • \$\begingroup\$ I would take the third approach as I need it to be fast and I really need the depth buffer. The problem is, I don't know how to bind the depth buffer as read only. I'm binding it like this: this.depthStencilShaderResourceVariable = effect.GetVariableByName("DepthTexture").AsShaderResource(); this.depthStencilShaderResourceVariable.SetResource(this.depthBufferShaderResourceView); I don't know if you mean this types of resource usage: sharpdx.org/documentation/api/… But didn't see anything useful in them. \$\endgroup\$
    – c4sh
    Commented Nov 15, 2013 at 16:46
  • \$\begingroup\$ You need to pass D3D11_DSV_READ_ONLY_DEPTH to CreateDepthStencilView() to get a read-only view. For SharpDX I think that's done by calling sharpdx.org/documentation/api/… and setting the Description up appropriately. \$\endgroup\$
    – Adam
    Commented Nov 15, 2013 at 20:09
  • \$\begingroup\$ This leaves it just with 0s. So the depth buffer was cleared to 1.0 but it's as if I was writing zeroes on it! \$\endgroup\$
    – c4sh
    Commented Nov 18, 2013 at 10:37
  • \$\begingroup\$ As no one else is gonna answer this and the problem for me is not solved, I would accept the answer I got as a thanks giving for its usefulness, though it didn't lead me to a solution. \$\endgroup\$
    – c4sh
    Commented Nov 22, 2013 at 10:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .