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 <natlee@microsoft.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index a56b89a..1dcc05f 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -960,16 +960,11 @@
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<uint8_t>(attachmentInfo.clearStencil);
// Load op - depth/stencil
bool doDepthClear = texture->GetFormat().HasDepth() &&
@@ -984,19 +979,35 @@
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<uint8_t>(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 8351509..51c0624 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -391,12 +391,10 @@
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 9ae41cf..8eaca7e 100644
--- a/src/dawn_native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -197,16 +197,33 @@
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 2d244f9..3d6f3e6 100644
--- a/src/tests/end2end/TextureZeroInitTests.cpp
+++ b/src/tests/end2end/TextureZeroInitTests.cpp
@@ -321,6 +321,8 @@
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 @@
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<RGBA8> expected(kSize * kSize, {255, 0, 0, 255});
@@ -360,6 +362,8 @@
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 @@
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<RGBA8> expected(kSize * kSize, {255, 0, 0, 255});
@@ -398,6 +402,8 @@
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 @@
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<RGBA8> expected(kSize * kSize, {255, 0, 0, 255});