From 36906d9edfc91b4c26dec5f71d96d81820ee5d08 Mon Sep 17 00:00:00 2001 From: Steve Karolewics Date: Wed, 18 Dec 2019 23:02:32 -0800 Subject: [PATCH] Try to clear the depth buffer for the ClearBeforePass/Draw overlays This functionality can be very valuable when debugging shadow map rendering, for example. Because the correct value to clear to might not be known, the depth function is checked to see what to clear to. If the depth function is equal, not equal, or always, depth is not cleared, to avoid producing incorrect (and not useful) results. --- renderdoc/driver/d3d11/d3d11_overlay.cpp | 32 ++++++++++++++++++++++++ renderdoc/driver/d3d12/d3d12_overlay.cpp | 28 +++++++++++++++++++++ renderdoc/driver/gl/gl_overlay.cpp | 18 +++++++++++++ renderdoc/driver/vulkan/vk_overlay.cpp | 26 +++++++++++++++++++ 4 files changed, 104 insertions(+) diff --git a/renderdoc/driver/d3d11/d3d11_overlay.cpp b/renderdoc/driver/d3d11/d3d11_overlay.cpp index 31c235e11..59c36c38d 100644 --- a/renderdoc/driver/d3d11/d3d11_overlay.cpp +++ b/renderdoc/driver/d3d11/d3d11_overlay.cpp @@ -609,6 +609,38 @@ ResourceId D3D11Replay::RenderOverlay(ResourceId texid, CompType typeCast, Float if(state.OM.RenderTargets[i]) m_pImmediateContext->ClearRenderTargetView(state.OM.RenderTargets[i], &clearCol.x); + // Try to clear depth as well, to help debug shadow rendering + if(state.OM.DepthView && IsDepthFormat(details.srvFormat)) + { + if(state.OM.DepthStencilState) + { + D3D11_DEPTH_STENCIL_DESC desc; + state.OM.DepthStencilState->GetDesc(&desc); + + // If the depth func is equal or not equal, don't clear at all since the output would be + // altered in an way that would cause replay to produce mostly incorrect results. + // Similarly, skip if the depth func is always, as we'd have a 50% chance of guessing the + // wrong clear value. + if(desc.DepthFunc != D3D11_COMPARISON_EQUAL && + desc.DepthFunc != D3D11_COMPARISON_NOT_EQUAL && + desc.DepthFunc != D3D11_COMPARISON_ALWAYS) + { + // If the depth func is less or less equal, clear to 1 instead of 0 + bool depthFuncLess = desc.DepthFunc == D3D11_COMPARISON_LESS || + desc.DepthFunc == D3D11_COMPARISON_LESS_EQUAL; + float depthClear = depthFuncLess ? 1.0f : 0.0f; + + m_pImmediateContext->ClearDepthStencilView(state.OM.DepthView, D3D11_CLEAR_DEPTH, + depthClear, 0); + } + } + else + { + // Without a depth stencil state set, the comparison func is D3D11_COMPARISON_LESS + m_pImmediateContext->ClearDepthStencilView(state.OM.DepthView, D3D11_CLEAR_DEPTH, 1.0f, 0); + } + } + for(size_t i = 0; i < events.size(); i++) { m_pDevice->ReplayLog(events[i], events[i], eReplay_OnlyDraw); diff --git a/renderdoc/driver/d3d12/d3d12_overlay.cpp b/renderdoc/driver/d3d12/d3d12_overlay.cpp index 55fb8831d..b3b4c3ab1 100644 --- a/renderdoc/driver/d3d12/d3d12_overlay.cpp +++ b/renderdoc/driver/d3d12/d3d12_overlay.cpp @@ -675,6 +675,34 @@ ResourceId D3D12Replay::RenderOverlay(ResourceId texid, CompType typeCast, Float &clearCol.x, 0, NULL); } + // Try to clear depth as well, to help debug shadow rendering + if(rs.dsv.GetResResourceId() != ResourceId() && IsDepthFormat(resourceDesc.Format)) + { + WrappedID3D12PipelineState *origPSO = + m_pDevice->GetResourceManager()->GetCurrentAs(rs.pipe); + if(origPSO && origPSO->IsGraphics()) + { + D3D12_COMPARISON_FUNC depthFunc = origPSO->graphics->DepthStencilState.DepthFunc; + + // If the depth func is equal or not equal, don't clear at all since the output would be + // altered in an way that would cause replay to produce mostly incorrect results. + // Similarly, skip if the depth func is always, as we'd have a 50% chance of guessing the + // wrong clear value. + if(depthFunc != D3D12_COMPARISON_FUNC_EQUAL && + depthFunc != D3D12_COMPARISON_FUNC_NOT_EQUAL && + depthFunc != D3D12_COMPARISON_FUNC_ALWAYS) + { + // If the depth func is less or less equal, clear to 1 instead of 0 + bool depthFuncLess = depthFunc == D3D12_COMPARISON_FUNC_LESS || + depthFunc == D3D12_COMPARISON_FUNC_LESS_EQUAL; + float depthClear = depthFuncLess ? 1.0f : 0.0f; + + Unwrap(list)->ClearDepthStencilView(Unwrap(GetDebugManager()->GetTempDescriptor(rs.dsv)), + D3D12_CLEAR_FLAG_DEPTH, depthClear, 0, 0, NULL); + } + } + } + list->Close(); list = NULL; diff --git a/renderdoc/driver/gl/gl_overlay.cpp b/renderdoc/driver/gl/gl_overlay.cpp index 28b4f3c9e..46c3f2ee3 100644 --- a/renderdoc/driver/gl/gl_overlay.cpp +++ b/renderdoc/driver/gl/gl_overlay.cpp @@ -935,6 +935,24 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeCast, FloatVec for(int i = 0; i < 8; i++) drv.glClearBufferfv(eGL_COLOR, i, &clearCol.x); + // Try to clear depth as well, to help debug shadow rendering + if(IsDepthStencilFormat(texDetails.internalFormat)) + { + // If the depth func is equal or not equal, don't clear at all since the output would be + // altered in an way that would cause replay to produce mostly incorrect results. + // Similarly, skip if the depth func is always, as we'd have a 50% chance of guessing the + // wrong clear value. + if(rs.DepthFunc != eGL_EQUAL && rs.DepthFunc != eGL_NOTEQUAL && rs.DepthFunc != eGL_ALWAYS) + { + // Don't use the render state's depth clear value, as this overlay should show as much + // information as possible. Instead, clear to the value that would cause the most depth + // writes to happen. + bool depthFuncLess = rs.DepthFunc == eGL_LESS || rs.DepthFunc == eGL_LEQUAL; + float depthClear = depthFuncLess ? 1.0f : 0.0f; + drv.glClearBufferfv(eGL_DEPTH, 0, &depthClear); + } + } + for(size_t i = 0; i < events.size(); i++) { m_pDriver->ReplayLog(events[i], events[i], eReplay_OnlyDraw); diff --git a/renderdoc/driver/vulkan/vk_overlay.cpp b/renderdoc/driver/vulkan/vk_overlay.cpp index 2585bf10f..16b8864c3 100644 --- a/renderdoc/driver/vulkan/vk_overlay.cpp +++ b/renderdoc/driver/vulkan/vk_overlay.cpp @@ -1635,6 +1635,32 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, CompType typeCast, Floa atts.push_back(clearatt); } + // Try to clear depth as well, to help debug shadow rendering + if(m_pDriver->m_RenderState.graphics.pipeline != ResourceId() && + IsDepthOrStencilFormat(iminfo.format)) + { + const VulkanCreationInfo::Pipeline &p = + m_pDriver->m_CreationInfo.m_Pipeline[m_pDriver->m_RenderState.graphics.pipeline]; + + // If the depth func is equal or not equal, don't clear at all since the output would be + // altered in an way that would cause replay to produce mostly incorrect results. + // Similarly, skip if the depth func is always, as we'd have a 50% chance of guessing the + // wrong clear value. + if(p.depthCompareOp != VK_COMPARE_OP_EQUAL && p.depthCompareOp != VK_COMPARE_OP_NOT_EQUAL && + p.depthCompareOp != VK_COMPARE_OP_ALWAYS) + { + // If the depth func is less or less equal, clear to 1 instead of 0 + bool depthFuncLess = p.depthCompareOp == VK_COMPARE_OP_LESS || + p.depthCompareOp == VK_COMPARE_OP_LESS_OR_EQUAL; + float depthClear = depthFuncLess ? 1.0f : 0.0f; + + VkClearAttachment clearDepthAtt = {VK_IMAGE_ASPECT_DEPTH_BIT, 0, {}}; + clearDepthAtt.clearValue.depthStencil.depth = depthClear; + + atts.push_back(clearDepthAtt); + } + } + VkClearRect rect = { {{0, 0}, {fb.width, fb.height}}, 0, 1, };