Sign in to follow this  
mind in a box

[D3D11] Depth buffer does nothing

Recommended Posts

Hey,
with the recode of the core of my engine, most rendering functionality was gone.
That was also the case with the depth buffer, and now I would like to re-implement it finally.
However, I would not post here if that would work out of the box.

When I set my DepthStencilView and DepthStencilState, my scene just looks like no depth buffer would be there at all.
And I have no idea why.

It would be great if you could have a look over my code and maybe tell me what is wrong.

Here is the creation of the texture/view:

RenderToDepthStencilStruct(UINT SizeX,UINT SizeY,DXGI_FORMAT Format, HRESULT* Result=NULL, DXGI_FORMAT DSVFormat=DXGI_FORMAT_UNKNOWN, DXGI_FORMAT SRVFormat=DXGI_FORMAT_UNKNOWN)
{
HRESULT hr=S_OK;

Texture=NULL;
ShaderResView=NULL;
DepthStencilView=NULL;

if(SizeX == 0 || SizeY == 0)
{
LogError() << L"SizeX or SizeY can't be 0";
}

if(Format==0)
{
LogError() << L"DXGI_FORMAT_UNKNOWN (0) isn't a valid texture format";
}

//Create a new render target texture
D3D11_TEXTURE2D_DESC Desc;
ZeroMemory( &Desc, sizeof( D3D10_TEXTURE2D_DESC ) );
Desc.ArraySize = 1;
Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
Desc.Usage = D3D11_USAGE_DEFAULT;
Desc.Format = Format;
Desc.Width = SizeX;
Desc.Height = SizeY;
Desc.MipLevels = 1;
Desc.SampleDesc.Count = 1;

LE(DXUTGetD3D11Device()->CreateTexture2D(&Desc,NULL,&Texture));

//Create a render target view
D3D11_DEPTH_STENCIL_VIEW_DESC DescDSV;
DescDSV.Format = (DSVFormat != DXGI_FORMAT_UNKNOWN ? DSVFormat : Desc.Format);
DescDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
DescDSV.Texture2D.MipSlice = 0;
DescDSV.Flags=0;
LE(DXUTGetD3D11Device()->CreateDepthStencilView((ID3D11Resource *)Texture,&DescDSV,&DepthStencilView));


// Create the resource view
D3D11_SHADER_RESOURCE_VIEW_DESC DescRV;
DescRV.Format = (SRVFormat != DXGI_FORMAT_UNKNOWN ? SRVFormat : Desc.Format);
DescRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
DescRV.Texture2D.MipLevels = 1;
DescRV.Texture2D.MostDetailedMip = 0;
LE(DXUTGetD3D11Device()->CreateShaderResourceView( (ID3D11Resource *)Texture, &DescRV, &ShaderResView ));

if(FAILED(hr))
{
LogError() << L"Coould not create ID3D11Texture2D, ID3D11ShaderResourceView, or ID3D11DepthStencilView. Killing created resources (If any).";
ReleaseAll();
if(Result)*Result=hr;
return;
}

LogInfo() << L"RenderToDepthStencilStruct: Successfully created ID3D11Texture2D, ID3D11ShaderResourceView, and ID3D11DepthStencilView.";
if(Result)*Result=hr;
}





Thats how I call it:


DepthBuffer=new RenderToDepthStencilStruct(SizeX, SizeY, DXGI_FORMAT_R32_TYPELESS, &hr, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT);





And here I set the view and the state:

DXUTGetD3D11DeviceContext()->OMSetRenderTargets(1, &RenderTargetView, DepthBuffer->GetDepthStencilView());
DXUTGetD3D11DeviceContext()->OMSetDepthStencilState(DefaultDepthStencilState, 0);





I had this problem before, and I even made a thread for it: http://www.gamedev.net/community/forums/topic.asp?topic_id=574751

But there I just forgot to set the depth stencil state. Now I do it, and I don't know what's wrong...

Share this post


Link to post
Share on other sites
No, I do clear the depth buffer.

Here is my whole rendering function:

HRESULT SceneRenderer_ToSwapchain::RenderScene(Scene* Scene)
{
HRESULT hr=S_OK;

if(!Scene)
{
LogError() << L"Invalid scene: " << Scene;
return E_FAIL;
}

DXUTGetD3D11DeviceContext()->ClearRenderTargetView(RenderTargetView,(float *)&D3DXVECTOR4(0.0,0.0,0.0,1));
DXUTGetD3D11DeviceContext()->ClearDepthStencilView(DepthBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1, 0);

//Set the RTV
DXUTGetD3D11DeviceContext()->OMSetRenderTargets(1, &RenderTargetView, DepthBuffer->GetDepthStencilView());
DXUTGetD3D11DeviceContext()->OMSetDepthStencilState(DefaultDepthStencilState, 0);

D3D11_VIEWPORT vp;
vp.MinDepth=0;
vp.MaxDepth=0;
vp.TopLeftX=0;
vp.TopLeftY=0;
vp.Width=SwapChainDesc.BufferDesc.Width;
vp.Height=SwapChainDesc.BufferDesc.Height;

DXUTGetD3D11DeviceContext()->RSSetViewports(1,&vp);


//Update projection matrix to ours
GetProjectionMatrix(&Scene->GetBasicObjectInfo()->Projection);

//Prerender
Scene->PreRenderWorld();

//Render scene
Scene->RenderScene(RG_NORMAL);

//Render post processing
Scene->PostRenderWorld();
return S_OK;
}




And the problem does not look like a not-cleared depth buffer...
Here is a picture of a simple test scene:

(That are 5 meshes)

You can see that the ducks are overdrawing each other.
With a working depth buffer everything should render normal.

Share this post


Link to post
Share on other sites
Quote:

Desc.Width = SizeX;
Desc.Height = SizeY;


Does SizeX and SizeY have the same values as the size of the framebuffer?

In my code, I don't call OMSetRenderTargets every frame. I only call it when I create the depth and frame buffer and whenever I resize the window.

Double check and make sure the smaller ducks have a larger z-coordinate than the larger ones (assuming they're all lining up along the z-axis).

Also, does DepthBuffer->GetDepthStencilView() return a valid pointer?

[Edited by - 16bit_port on October 1, 2010 4:40:24 PM]

Share this post


Link to post
Share on other sites
Quote:

Does SizeX and SizeY have the same values as the size of the framebuffer?


I use the same variables for resizing my swapchain. I also checked this.
If they wouldn't be the same, the debug layer would give me some hints, though.

Quote:

In my code, I don't call OMSetRenderTargets every frame. I only call it when I create the depth and frame buffer and whenever I resize the window.


I have some multiple viewports, each with it's own swapchain and stuff. That's why I need that.

Quote:

Double check and make sure the smaller ducks have a larger z-coordinate than the larger ones (assuming they're all lining up along the z-axis).


Same scene, viewing from the top:


Quote:

Also, does DepthBuffer->GetDepthStencilView() return a valid pointer?

I just triple checked this ... :-/

Share this post


Link to post
Share on other sites
Quote:

I have some multiple viewports, each with it's own swapchain and stuff. That's why I need that.


I would temporarily disable the other viewports and make sure you're not accidentally using the other viewports' resource views and whatnot. Also it'll just make debugging easier.

Share this post


Link to post
Share on other sites
Quote:

I would temporarily disable the other viewports and make sure you're not accidentally using the other viewports' resource views and whatnot. Also it'll just make debugging easier.


There are no other than the main-viewport open at the moment. They only pop up if I want them to do. [smile]

Share this post


Link to post
Share on other sites
Did you try specifying NULL for the second param in CreateDepthStencilView()? (I had JUST edited that into the previous reply so I don't know if you caught it or not.)

If this isn't the solution, then I don't know what is :
Move

DXUTGetD3D11DeviceContext()->ClearDepthStencilView(DepthBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1, 0);

so that it is called AFTER

DXUTGetD3D11DeviceContext()->OMSetRenderTargets(1, &RenderTargetView, DepthBuffer->GetDepthStencilView());
DXUTGetD3D11DeviceContext()->OMSetDepthStencilState(DefaultDepthStencilState, 0);

Share this post


Link to post
Share on other sites
Quote:

Also, try specifying NULL for the second param in CreateDepthStencilView().


Doesn't help. [sad]

Quote:

Move

DXUTGetD3D11DeviceContext()->ClearDepthStencilView(DepthBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1, 0);

so that it is called AFTER

DXUTGetD3D11DeviceContext()->OMSetRenderTargets(1, &RenderTargetView, DepthBuffer->GetDepthStencilView());
DXUTGetD3D11DeviceContext()->OMSetDepthStencilState(DefaultDepthStencilState, 0);


Doesn't help either. [sad]


It's 23:57 here. I think I should sleep over it now, maybe I'm just too tired for debugging right or whatever. Hopefully I will find error tomorrow.

Share this post


Link to post
Share on other sites
Try commenting out :

DXUTGetD3D11DeviceContext()->OMSetDepthStencilState(DefaultDepthStencilState, 0);

and see if it is the state that is screwing things up.

Share this post


Link to post
Share on other sites
I just checked this and tried different shaders. No change of results.
Damn, this is just the zBuffer, why can't I get it to work???

Btw, I forgot the creation of the DepthStencilState:


D3D11_DEPTH_STENCIL_DESC dsDesc;

HRESULT hr=S_OK;

// Depth test parameters
dsDesc.DepthEnable = true;
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D11_COMPARISON_LESS;

// Stencil test parameters
dsDesc.StencilEnable = true;
dsDesc.StencilReadMask = 0xFF;
dsDesc.StencilWriteMask = 0xFF;

// Stencil operations if pixel is front-facing
dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

// Stencil operations if pixel is back-facing
dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

// Create depth stencil state

LE(DXUTGetD3D11Device()->CreateDepthStencilState(&dsDesc, &DefaultDepthStencilState));



Is my mistake here?

Share this post


Link to post
Share on other sites
Quote:
Original post by mind in a box
I just checked this and tried different shaders. No change of results.
Damn, this is just the zBuffer, why can't I get it to work???

Btw, I forgot the creation of the DepthStencilState:

*** Source Snippet Removed ***

Is my mistake here?


Probably not, since as stated here the device maps the NULL state to the default state described here. If, however, the default state doesn't suit your needs this may be the problem.

Share this post


Link to post
Share on other sites
Quote:

Probably not, since as stated here the device maps the NULL state to the default state described here. If, however, the default state doesn't suit your needs this may be the problem.


The default state looks good for me. There should be no problem with it.

Let's sum up what was suggested in this thread:

- "You don't clear the depth buffer": I do, as you can see in my rendering function.

- "Does SizeX and SizeY have the same values as the size of the framebuffer?"

You can see this here:

/** Called when the buffers need to be resized */
HRESULT SceneRenderer_ToSwapchain::ResizeBuffers(UINT SizeX, UINT SizeY)
{
HRESULT hr;

if(SizeX==0 && SizeX==0)
{
RECT r;
GetClientRect(SwapChainDesc.OutputWindow,&r);
SizeX=r.right;
SizeY=r.bottom;
SwapChainDesc.BufferDesc.Width=SizeX;
SwapChainDesc.BufferDesc.Height=SizeY;
}

//Update projection matrix
SetProjectionParameters(SizeX, SizeY);

SAFE_RELEASE(RenderTargetView);

UINT Flags = 0;
//We want to allow the mode switch.
Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

//Resize the swapchain
LE( SwapChain->ResizeBuffers( SwapChainDesc.BufferCount,
SizeX,
SizeY,
SwapChainDesc.BufferDesc.Format,
Flags ) );


//Recreate the rendertargetview:


//Get the back buffer and desc
ID3D11Texture2D* BackBuffer;
LE_R( SwapChain->GetBuffer( 0, __uuidof( *BackBuffer ), ( void** )&BackBuffer ) );

D3D11_TEXTURE2D_DESC backBufferSurfaceDesc;
BackBuffer->GetDesc( &backBufferSurfaceDesc );

// Create the render target view
LE_R(DXUTGetD3D11Device()->CreateRenderTargetView(BackBuffer, NULL, &RenderTargetView ));

SAFE_RELEASE( BackBuffer );

delete DepthBuffer;
DepthBuffer=new RenderToDepthStencilStruct(SizeX, SizeY, DXGI_FORMAT_D24_UNORM_S8_UINT, &hr);//, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT);

return S_OK;
}




(I don't know why the formating of the pasted code is so wired here)

- "Try passing DXGI_FORMAT_D24_UNORM_S8_UINT as format": Check.
- "Try specifying NULL for the second param in CreateDepthStencilView()": Check.
- "Also, does DepthBuffer->GetDepthStencilView() return a valid pointer?": I called GetDesc() on it to check this. Results seem to be valid.
- "Just a shot in the dark, but is it possible one of your shaders is disabling the depth buffer or depth writes?": I tried multiple shaders, which should no do that.

Someone got another idea? :/

Share this post


Link to post
Share on other sites
I just tried PIX, and I noticed that my whole depth buffer seems to get cleared to black, not white as I specified.
After rendering, the geometry shows up in white, even if it is VERY near at the camera.

Where do I check if the correct states are bound?

[edit]: I tried to debug one of the pixels of the rendertarget in PIX.
There were many pixels which said "This pixel was eliminated because: It failed the depth test.". So it could test against the depth in some way... But then in a wrong one!

Share this post


Link to post
Share on other sites
I don't know if you've made the suggested changes and then switched back if it didn't work, but I would keep everything as basic and standard as possible (just until you find the culprit)

1) comment the DepthStencilState desc out
2) d3dDevice->OMSetDepthStencilState( 0, 0 );
3) Not entirely sure what you mean when you say that you have the other viewports disabled (at runtime?) but I would hardcode it so that it only creates one and move

DXUTGetD3D11DeviceContext()->OMSetRenderTargets(1, &RenderTargetView, DepthBuffer->GetDepthStencilView());

to initialization

keep the changes I suggested earlier :
4) pass DXGI_FORMAT_D24_UNORM_S8_UINT as format
5) specify NULL for the second param in CreateDepthStencilView()
6)

Move

DXUTGetD3D11DeviceContext()->ClearDepthStencilView(DepthBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1, 0);

so that it is called AFTER

DXUTGetD3D11DeviceContext()->OMSetRenderTargets(1, &RenderTargetView, DepthBuffer->GetDepthStencilView());
DXUTGetD3D11DeviceContext()->OMSetDepthStencilState(DefaultDepthStencilState, 0);

Share this post


Link to post
Share on other sites
Psst-- did you make sure your depth culling operation (i.e. LESS_EQUAL, GREATER_EQUAL, etc.) is set the right way? If your depth values are reversed, you should just be able to flop the culling direction and it should work normally :)

I ask as the ordering appears pretty consistent-- it's always the farthest object drawn.

EDIT: And, if you're working with a floating-point depth buffer, reversing the depth range/comparison tests can improve overall depth precision anyways, canceling out some aspects of floating-point error due to nonlinear number line whatchamacallit. There's a formal term, but sadly it escapes me at the moment.

Share this post


Link to post
Share on other sites
Back on this. It still isn't working. I'm completely annoyed of depth buffers right now. I almost stopped developing my engine because of this and other problems which stand in my way of doing something else.

16bit_port, I've done everything like you suggested, no change of things.
I even recoded this from scratch, no change.

InvalidPointer: I swap it, the screen gets black. I also swapped the value I clear the buffer with, still black.
If I decrease the clear-value by some specific amount, the screen gets black.

PIX shows everything in pure white color in the depth buffer, no black/gray for near objects.

The debug runtime does say nothing.



This is just the zbuffer. Why can't I get it to work?
Please, someone must have another idea ...

Share this post


Link to post
Share on other sites
try setting your max depth to one


D3D11_VIEWPORT vp;
vp.MinDepth=0;
vp.MaxDepth=0; <---------
vp.TopLeftX=0;
vp.TopLeftY=0;
vp.Width=SwapChainDesc.BufferDesc.Width;
vp.Height=SwapChainDesc.BufferDesc.Height;

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