# [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 on other sites
You forgot to clear the depth buffer every frame. That's probably what's causing the problem.

It's : ID3D11DeviceContext::ClearDepthStencilView.

Click here for ClearDepthStencilView documentation at MSDN

##### 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 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 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 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 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 on other sites
For the "Format", I would pass in DXGI_FORMAT_D24_UNORM_S8_UINT. Also, try specifying NULL for the second param in CreateDepthStencilView().

##### Share on other sites
Still the same ...
Damn, I'm sitting like 4 hours now on this stupid problem! And I bet at the end it was just a tiny little mistake by me. It's always like that.

##### 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 on other sites
Quote:
 And I bet at the end it was just a tiny little mistake by me. It's always like that.

All of my bugs are like that -__-

##### Share on other sites
Quote:
Original post by 16bit_port
Quote:
 And I bet at the end it was just a tiny little mistake by me. It's always like that.

All of my bugs are like that -__-

o/

##### Share on other sites
Quote:
 Also, try specifying NULL for the second param in CreateDepthStencilView().

Quote:
 MoveDXUTGetD3D11DeviceContext()->ClearDepthStencilView(DepthBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1, 0);so that it is called AFTERDXUTGetD3D11DeviceContext()->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 on other sites
Try commenting out :

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

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

##### Share on other sites
I hate to say "No" so often ... But this doesn't change something as well.

Bed time now. Thanks for your help so far!

##### Share on other sites
Just a shot in the dark, but is it possible one of your shaders is disabling the depth buffer or depth writes?

--
Kory

##### 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 on other sites
Quote:
 Original post by mind in a boxI 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 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 on other sites
Did you try PIX to see that the correct buffers and states are bound?

##### 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?

: 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 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 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 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 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;

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