From 01600dfb3d01cf3aced89f3cd172732bbb8c2878 Mon Sep 17 00:00:00 2001 From: Natasha Lee Date: Wed, 11 Sep 2019 22:04:42 +0000 Subject: [PATCH] Use clear loadop to lazy clear depth stencil attachments Bug: dawn:210, dawn:145 Change-Id: I1eb990266ccd7b51b4a336b0d4d37e0195c6fe69 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11020 Commit-Queue: Natasha Lee Reviewed-by: Kai Ninomiya --- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 49 ++++++++++++-------- src/dawn_native/opengl/CommandBufferGL.cpp | 8 ++-- src/dawn_native/vulkan/CommandBufferVk.cpp | 35 ++++++++++---- src/tests/end2end/TextureZeroInitTests.cpp | 18 ++++--- 4 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index a56b89ac71..1dcc05f9fc 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -960,16 +960,11 @@ namespace dawn_native { namespace d3d12 { if (renderPass->attachmentState->HasDepthStencilAttachment()) { auto& attachmentInfo = renderPass->depthStencilAttachment; Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture()); - if ((texture->GetFormat().HasDepth() && - attachmentInfo.depthLoadOp == dawn::LoadOp::Load) || - (texture->GetFormat().HasStencil() && - attachmentInfo.stencilLoadOp == dawn::LoadOp::Load)) { - texture->EnsureSubresourceContentInitialized( - commandList, attachmentInfo.view->GetBaseMipLevel(), - attachmentInfo.view->GetLevelCount(), - attachmentInfo.view->GetBaseArrayLayer(), - attachmentInfo.view->GetLayerCount()); - } + TextureView* view = ToBackend(attachmentInfo.view.Get()); + float clearDepth = attachmentInfo.clearDepth; + // TODO(kainino@chromium.org): investigate: should the Dawn clear + // stencil type be uint8_t? + uint8_t clearStencil = static_cast(attachmentInfo.clearStencil); // Load op - depth/stencil bool doDepthClear = texture->GetFormat().HasDepth() && @@ -984,19 +979,35 @@ namespace dawn_native { namespace d3d12 { if (doStencilClear) { clearFlags |= D3D12_CLEAR_FLAG_STENCIL; } + // If the depth stencil texture has not been initialized, we want to use loadop + // clear to init the contents to 0's + if (!texture->IsSubresourceContentInitialized( + view->GetBaseMipLevel(), view->GetLevelCount(), view->GetBaseArrayLayer(), + view->GetLayerCount())) { + if (texture->GetFormat().HasDepth() && + attachmentInfo.depthLoadOp == dawn::LoadOp::Load) { + clearDepth = 0.0f; + clearFlags |= D3D12_CLEAR_FLAG_DEPTH; + } + if (texture->GetFormat().HasStencil() && + attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) { + clearStencil = 0u; + clearFlags |= D3D12_CLEAR_FLAG_STENCIL; + } + } if (clearFlags) { D3D12_CPU_DESCRIPTOR_HANDLE handle = args.dsv; - // TODO(kainino@chromium.org): investigate: should the Dawn clear - // stencil type be uint8_t? - uint8_t clearStencil = static_cast(attachmentInfo.clearStencil); - commandList->ClearDepthStencilView( - handle, clearFlags, attachmentInfo.clearDepth, clearStencil, 0, nullptr); + commandList->ClearDepthStencilView(handle, clearFlags, clearDepth, clearStencil, + 0, nullptr); + } + + // TODO(natlee@microsoft.com): Need to fix when storeop discard is added + if (attachmentInfo.depthStoreOp == dawn::StoreOp::Store && + attachmentInfo.stencilStoreOp == dawn::StoreOp::Store) { texture->SetIsSubresourceContentInitialized( - attachmentInfo.view->GetBaseMipLevel(), - attachmentInfo.view->GetLevelCount(), - attachmentInfo.view->GetBaseArrayLayer(), - attachmentInfo.view->GetLayerCount()); + view->GetBaseMipLevel(), view->GetLevelCount(), view->GetBaseArrayLayer(), + view->GetLayerCount()); } } } diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index 8351509d0f..51c0624068 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -391,12 +391,10 @@ namespace dawn_native { namespace opengl { auto TransitionForPass = [](const PassResourceUsage& usages) { for (size_t i = 0; i < usages.textures.size(); i++) { Texture* texture = ToBackend(usages.textures[i]); - // We count the lazy clears for non output attachment textures and depth stencil - // textures in order to match the backdoor lazy clear counts in Vulkan and D3D12. + // We count the lazy clears for non output attachment textures in order to match the + // backdoor lazy clear counts in Vulkan and D3D12. bool isLazyClear = - ((!(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment) && - texture->GetFormat().IsColor()) || - texture->GetFormat().HasDepthOrStencil()); + !(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment); texture->EnsureSubresourceContentInitialized( 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers(), isLazyClear); } diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index 9ae41cf3c5..8eaca7ea10 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -197,16 +197,33 @@ namespace dawn_native { namespace vulkan { if (renderPass->attachmentState->HasDepthStencilAttachment()) { auto& attachmentInfo = renderPass->depthStencilAttachment; - query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format, + TextureView* view = ToBackend(attachmentInfo.view.Get()); + + // If the depth stencil texture has not been initialized, we want to use loadop + // clear to init the contents to 0's + if (!view->GetTexture()->IsSubresourceContentInitialized( + view->GetBaseMipLevel(), view->GetLevelCount(), + view->GetBaseArrayLayer(), view->GetLayerCount())) { + if (view->GetTexture()->GetFormat().HasDepth() && + attachmentInfo.depthLoadOp == dawn::LoadOp::Load) { + attachmentInfo.clearDepth = 0.0f; + attachmentInfo.depthLoadOp = dawn::LoadOp::Clear; + } + if (view->GetTexture()->GetFormat().HasStencil() && + attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) { + attachmentInfo.clearStencil = 0u; + attachmentInfo.stencilLoadOp = dawn::LoadOp::Clear; + } + } + query.SetDepthStencil(view->GetTexture()->GetFormat().format, attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp); - if (attachmentInfo.depthLoadOp == dawn::LoadOp::Load || - attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) { - ToBackend(attachmentInfo.view->GetTexture()) - ->EnsureSubresourceContentInitialized( - recordingContext, attachmentInfo.view->GetBaseMipLevel(), - attachmentInfo.view->GetLevelCount(), - attachmentInfo.view->GetBaseArrayLayer(), - attachmentInfo.view->GetLayerCount()); + + // TODO(natlee@microsoft.com): Need to fix when storeop discard is added + if (attachmentInfo.depthStoreOp == dawn::StoreOp::Store && + attachmentInfo.stencilStoreOp == dawn::StoreOp::Store) { + view->GetTexture()->SetIsSubresourceContentInitialized( + view->GetBaseMipLevel(), view->GetLevelCount(), + view->GetBaseArrayLayer(), view->GetLayerCount()); } } diff --git a/src/tests/end2end/TextureZeroInitTests.cpp b/src/tests/end2end/TextureZeroInitTests.cpp index 2d244f924e..3d6f3e6142 100644 --- a/src/tests/end2end/TextureZeroInitTests.cpp +++ b/src/tests/end2end/TextureZeroInitTests.cpp @@ -321,6 +321,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingDepth) { renderPassDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Load; renderPassDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Clear; renderPassDescriptor.cDepthStencilAttachmentInfo.clearStencil = 0; + renderPassDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = dawn::StoreOp::Store; + renderPassDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = dawn::StoreOp::Store; dawn::CommandEncoder encoder = device.CreateCommandEncoder(); auto pass = encoder.BeginRenderPass(&renderPassDescriptor); @@ -328,8 +330,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingDepth) { pass.Draw(6, 1, 0, 0); pass.EndPass(); dawn::CommandBuffer commandBuffer = encoder.Finish(); - // Expect 1 lazy clear for the depthStencilTexture - EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commandBuffer)); + // Expect 0 lazy clears, depth stencil texture will clear using loadop + EXPECT_LAZY_CLEAR(0u, queue.Submit(1, &commandBuffer)); // Expect the texture to be red because depth test passed. std::vector expected(kSize * kSize, {255, 0, 0, 255}); @@ -360,6 +362,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingStencil) { renderPassDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Clear; renderPassDescriptor.cDepthStencilAttachmentInfo.clearDepth = 0.0f; renderPassDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Load; + renderPassDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = dawn::StoreOp::Store; + renderPassDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = dawn::StoreOp::Store; dawn::CommandEncoder encoder = device.CreateCommandEncoder(); auto pass = encoder.BeginRenderPass(&renderPassDescriptor); @@ -367,8 +371,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingStencil) { pass.Draw(6, 1, 0, 0); pass.EndPass(); dawn::CommandBuffer commandBuffer = encoder.Finish(); - // Expect 1 lazy clear for depthStencilTexture. - EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commandBuffer)); + // Expect 0 lazy clears, depth stencil texture will clear using loadop + EXPECT_LAZY_CLEAR(0u, queue.Submit(1, &commandBuffer)); // Expect the texture to be red because stencil test passed. std::vector expected(kSize * kSize, {255, 0, 0, 255}); @@ -398,6 +402,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingDepthStencil) { depthStencilTexture.CreateView()); renderPassDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Load; renderPassDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Load; + renderPassDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = dawn::StoreOp::Store; + renderPassDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = dawn::StoreOp::Store; dawn::CommandEncoder encoder = device.CreateCommandEncoder(); auto pass = encoder.BeginRenderPass(&renderPassDescriptor); @@ -405,8 +411,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingDepthStencil) { pass.Draw(6, 1, 0, 0); pass.EndPass(); dawn::CommandBuffer commandBuffer = encoder.Finish(); - // Expect 1 lazy clear for depthStencilTexture. - EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commandBuffer)); + // Expect 0 lazy clears, depth stencil texture will clear using loadop + EXPECT_LAZY_CLEAR(0u, queue.Submit(1, &commandBuffer)); // Expect the texture to be red because both depth and stencil tests passed. std::vector expected(kSize * kSize, {255, 0, 0, 255});