I can't for the life of me figure out why my depth buffer is playing up, and it seems like a simple oversight somewhere.
Basically, I'm drawing a series of objects in my scene and can navigate around. What happens is the objects are drawing as if they are behind each-other, with the farthest away objects being drawn through closer ones.
I can "solve" this by setting the depth buffer D3D12_CLEAR_VALUE to 0.0 and performing a D3D12_COMPARISON_FUNC_GREATER_EQUAL instead of D3D12_COMPARISON_FUNC_LESS_EQUAL Everything then renders correctly. However rather than being happy with that, I want to know what's causing this - as it's unusual and does not reflect the behaviour of the DirectX Samples.
My psuedo render loop:
- Set gbuffer as active render targets.
- Clear gbuffer render textures.
- Clear depth buffer.
- Draw objects.
- Set backbuffer as active render target.
- Draw gbuffer result.
In terms of actual code, I suppose the three useful bits here are my depth buffer creation, depth buffer clearing and PSO setup.
Creating the depth buffer:
// Create a resource description for the depth texture.
D3D12_RESOURCE_DESC depthDesc = {};
depthDesc.MipLevels = 1;
depthDesc.Format = DXGI_FORMAT_R32_TYPELESS;
depthDesc.Alignment = 0;
depthDesc.Width = _screenWidth;
depthDesc.Height = _screenHeight;
depthDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
depthDesc.DepthOrArraySize = 1;
depthDesc.SampleDesc.Count = 1;
depthDesc.SampleDesc.Quality = 0;
depthDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
depthDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
D3D12_CLEAR_VALUE* clearVal = new D3D12_CLEAR_VALUE();
clearVal->Format = DXGI_FORMAT_D32_FLOAT;
clearVal->DepthStencil.Depth = 1.0f;
clearVal->DepthStencil.Stencil = 0;
// Create a depth stencil view description.
D3D12_DEPTH_STENCIL_VIEW_DESC stencilDesc = {};
stencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
stencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
stencilDesc.Texture2D.MipSlice = 0;
// Create a shader resource view description.
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
LOGFAILEDCOM(_device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &depthDesc,
D3D12_RESOURCE_STATE_DEPTH_READ, clearVal, IID_PPV_ARGS(&_pDepthBuffer)));
_device->CreateDepthStencilView(_pDepthBuffer, &stencilDesc, _dsvHeap->GetCPUDescriptorHandleForHeapStart());
DepthBufferIndex = ResourceFactory::GetTextureSlot();
CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(_cbvSrvHeap->GetCPUDescriptorHandleForHeapStart(), DepthBufferIndex, D3DUtils::GetSRVDescriptorSize());
_device->CreateShaderResourceView(_pDepthBuffer, &srvDesc, srvHandle);
Clearing the depth buffer (how difficult can it be?):
_commandList->ClearDepthStencilView(_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
PSO (relevant bits):
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.InputLayout = {&inputLayout[0], UINT(inputLayout.size())};
psoDesc.pRootSignature = _pRootSignature;
psoDesc.VS = {reinterpret_cast<UINT8*>(_pVertexShader->GetBufferPointer()), _pVertexShader->GetBufferSize()};
psoDesc.PS = {reinterpret_cast<UINT8*>(_pPixelShader->GetBufferPointer()), _pPixelShader->GetBufferSize()};
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
psoDesc.BlendState = blendState;
psoDesc.SampleMask = UINT_MAX;
psoDesc.SampleDesc.Count = 1;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState.DepthFunc = _depthCheck;
psoDesc.DepthStencilState.DepthEnable = TRUE;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.DepthStencilState.DepthWriteMask = _depthWrite;
psoDesc.NumRenderTargets = GBuffer::GBUFFER_NUM_TEXTURES;
for (size_t i = 0; i < GBuffer::GBUFFER_NUM_TEXTURES; ++i)
{
psoDesc.RTVFormats[i] = DXGI_FORMAT_R8G8B8A8_UNORM;
}