Fix vulkan clear texture image layout format

Also ensure depth stencil texture is clear in begin render pass.

Bug: dawn:175, dawn:145
Change-Id: I19fc857dedf9f353a4834b8e1c9616d02c5a15ac
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8140
Commit-Queue: Natasha Lee <natlee@microsoft.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp
index e36676f..f200e2b 100644
--- a/src/dawn_native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -169,24 +169,43 @@
                 RenderPassCacheQuery query;
 
                 for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
-                    const auto& attachmentInfo = renderPass->colorAttachments[i];
+                    auto& attachmentInfo = renderPass->colorAttachments[i];
+                    TextureView* view = ToBackend(attachmentInfo.view.Get());
                     bool hasResolveTarget = attachmentInfo.resolveTarget.Get() != nullptr;
 
                     dawn::LoadOp loadOp = attachmentInfo.loadOp;
-                    if (loadOp == dawn::LoadOp::Load && attachmentInfo.view->GetTexture() &&
-                        !attachmentInfo.view->GetTexture()->IsSubresourceContentInitialized(
-                            attachmentInfo.view->GetBaseMipLevel(), 1,
-                            attachmentInfo.view->GetBaseArrayLayer(), 1)) {
+                    ASSERT(view->GetLayerCount() == 1);
+                    ASSERT(view->GetLevelCount() == 1);
+                    if (loadOp == dawn::LoadOp::Load && view->GetTexture() &&
+                        !view->GetTexture()->IsSubresourceContentInitialized(
+                            view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1)) {
                         loadOp = dawn::LoadOp::Clear;
                     }
+                    switch (attachmentInfo.storeOp) {
+                        case dawn::StoreOp::Store: {
+                            view->GetTexture()->SetIsSubresourceContentInitialized(
+                                view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1);
+                        } break;
+
+                        default: { UNREACHABLE(); } break;
+                    }
 
                     query.SetColor(i, attachmentInfo.view->GetFormat(), loadOp, hasResolveTarget);
                 }
 
                 if (renderPass->hasDepthStencilAttachment) {
-                    const auto& attachmentInfo = renderPass->depthStencilAttachment;
+                    auto& attachmentInfo = renderPass->depthStencilAttachment;
                     query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat(),
                                           attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
+                    if (attachmentInfo.depthLoadOp == dawn::LoadOp::Load ||
+                        attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) {
+                        ToBackend(attachmentInfo.view->GetTexture())
+                            ->EnsureSubresourceContentInitialized(
+                                commands, attachmentInfo.view->GetBaseMipLevel(),
+                                attachmentInfo.view->GetLevelCount(),
+                                attachmentInfo.view->GetBaseArrayLayer(),
+                                attachmentInfo.view->GetLayerCount());
+                    }
                 }
 
                 query.SetSampleCount(renderPass->sampleCount);
@@ -553,20 +572,6 @@
                 case Command::EndRenderPass: {
                     mCommands.NextCommand<EndRenderPassCmd>();
                     device->fn.CmdEndRenderPass(commands);
-                    for (uint32_t i : IterateBitSet(renderPassCmd->colorAttachmentsSet)) {
-                        auto& attachmentInfo = renderPassCmd->colorAttachments[i];
-                        TextureView* view = ToBackend(attachmentInfo.view.Get());
-                        switch (attachmentInfo.storeOp) {
-                            case dawn::StoreOp::Store: {
-                                attachmentInfo.view->GetTexture()
-                                    ->SetIsSubresourceContentInitialized(
-                                        view->GetBaseMipLevel(), view->GetLevelCount(),
-                                        view->GetBaseArrayLayer(), view->GetLayerCount());
-                            } break;
-
-                            default: { UNREACHABLE(); } break;
-                        }
-                    }
                     return;
                 } break;
 
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 263cd86..cbd7644 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -331,16 +331,27 @@
             range.levelCount = GetNumMipLevels();
             range.baseArrayLayer = 0;
             range.layerCount = GetArrayLayers();
-
-            // TODO(natlee@microsoft.com): use correct union member depending on the texture format
-            VkClearColorValue clear_color = {{1.0, 1.0, 1.0, 1.0}};
-
             TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(),
                                dawn::TextureUsageBit::TransferDst);
-            ToBackend(GetDevice())
-                ->fn.CmdClearColorImage(ToBackend(GetDevice())->GetPendingCommandBuffer(),
-                                        GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                        &clear_color, 1, &range);
+
+            if (TextureFormatHasDepthOrStencil(GetFormat())) {
+                VkClearDepthStencilValue clear_color[1];
+                clear_color[0].depth = 1.0f;
+                clear_color[0].stencil = 1u;
+                ToBackend(GetDevice())
+                    ->fn.CmdClearDepthStencilImage(
+                        ToBackend(GetDevice())->GetPendingCommandBuffer(), GetHandle(),
+                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1, &range);
+            } else {
+                // TODO(natlee@microsoft.com): use correct union member depending on the texture
+                // format
+                VkClearColorValue clear_color = {{1.0, 1.0, 1.0, 1.0}};
+
+                ToBackend(GetDevice())
+                    ->fn.CmdClearColorImage(ToBackend(GetDevice())->GetPendingCommandBuffer(),
+                                            GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                            &clear_color, 1, &range);
+            }
         }
     }
 
@@ -420,37 +431,33 @@
                                uint32_t levelCount,
                                uint32_t baseArrayLayer,
                                uint32_t layerCount) {
-        if (GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
-            VkImageSubresourceRange range = {};
-            range.aspectMask = GetVkAspectMask();
-            range.baseMipLevel = baseMipLevel;
-            range.levelCount = levelCount;
-            range.baseArrayLayer = baseArrayLayer;
-            range.layerCount = layerCount;
+        VkImageSubresourceRange range = {};
+        range.aspectMask = GetVkAspectMask();
+        range.baseMipLevel = baseMipLevel;
+        range.levelCount = levelCount;
+        range.baseArrayLayer = baseArrayLayer;
+        range.layerCount = layerCount;
 
-            TransitionUsageNow(commands, dawn::TextureUsageBit::TransferDst);
-            if (TextureFormatHasDepthOrStencil(GetFormat())) {
-                VkClearDepthStencilValue clear_color[1];
-                clear_color[0].depth = 0.0f;
-                clear_color[0].stencil = 0u;
-                ToBackend(GetDevice())
-                    ->fn.CmdClearDepthStencilImage(commands, GetHandle(),
-                                                   VulkanImageLayout(GetUsage(), GetFormat()),
-                                                   clear_color, 1, &range);
-            } else {
-                VkClearColorValue clear_color[1];
-                clear_color[0].float32[0] = 0.0f;
-                clear_color[0].float32[1] = 0.0f;
-                clear_color[0].float32[2] = 0.0f;
-                clear_color[0].float32[3] = 0.0f;
-                ToBackend(GetDevice())
-                    ->fn.CmdClearColorImage(commands, GetHandle(),
-                                            VulkanImageLayout(GetUsage(), GetFormat()), clear_color,
-                                            1, &range);
-            }
-            SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
-                                               layerCount);
+        TransitionUsageNow(commands, dawn::TextureUsageBit::TransferDst);
+        if (TextureFormatHasDepthOrStencil(GetFormat())) {
+            VkClearDepthStencilValue clear_color[1];
+            clear_color[0].depth = 0.0f;
+            clear_color[0].stencil = 0u;
+            ToBackend(GetDevice())
+                ->fn.CmdClearDepthStencilImage(commands, GetHandle(),
+                                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1,
+                                               &range);
+        } else {
+            VkClearColorValue clear_color[1];
+            clear_color[0].float32[0] = 0.0f;
+            clear_color[0].float32[1] = 0.0f;
+            clear_color[0].float32[2] = 0.0f;
+            clear_color[0].float32[3] = 0.0f;
+            ToBackend(GetDevice())
+                ->fn.CmdClearColorImage(commands, GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                        clear_color, 1, &range);
         }
+        SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount);
     }
 
     void Texture::EnsureSubresourceContentInitialized(VkCommandBuffer commands,
@@ -458,6 +465,9 @@
                                                       uint32_t levelCount,
                                                       uint32_t baseArrayLayer,
                                                       uint32_t layerCount) {
+        if (!GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
+            return;
+        }
         if (!IsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
                                              layerCount)) {
             // If subresource has not been initialized, clear it to black as it could contain dirty
diff --git a/src/tests/end2end/TextureZeroInitTests.cpp b/src/tests/end2end/TextureZeroInitTests.cpp
index df72ba7..7b530f4 100644
--- a/src/tests/end2end/TextureZeroInitTests.cpp
+++ b/src/tests/end2end/TextureZeroInitTests.cpp
@@ -24,7 +24,8 @@
     }

     dawn::TextureDescriptor CreateTextureDescriptor(uint32_t mipLevelCount,

                                                     uint32_t arrayLayerCount,

-                                                    dawn::TextureUsageBit usage) {

+                                                    dawn::TextureUsageBit usage,

+                                                    dawn::TextureFormat format) {

         dawn::TextureDescriptor descriptor;

         descriptor.dimension = dawn::TextureDimension::e2D;

         descriptor.size.width = kSize;

@@ -32,7 +33,7 @@
         descriptor.size.depth = 1;

         descriptor.arrayLayerCount = arrayLayerCount;

         descriptor.sampleCount = 1;

-        descriptor.format = dawn::TextureFormat::RGBA8Unorm;

+        descriptor.format = format;

         descriptor.mipLevelCount = mipLevelCount;

         descriptor.usage = usage;

         return descriptor;

@@ -40,7 +41,7 @@
     dawn::TextureViewDescriptor CreateTextureViewDescriptor(uint32_t baseMipLevel,

                                                             uint32_t baseArrayLayer) {

         dawn::TextureViewDescriptor descriptor;

-        descriptor.format = dawn::TextureFormat::RGBA8Unorm;

+        descriptor.format = kColorFormat;

         descriptor.baseArrayLayer = baseArrayLayer;

         descriptor.arrayLayerCount = 1;

         descriptor.baseMipLevel = baseMipLevel;

@@ -48,13 +49,50 @@
         descriptor.dimension = dawn::TextureViewDimension::e2D;

         return descriptor;

     }

+    dawn::RenderPipeline CreatePipelineForTest() {

+        utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);

+        const char* vs =

+            R"(#version 450

+        const vec3 pos[6] = vec3[6](vec3(-1.0f, -1.0f, 0.0f),

+                                    vec3(-1.0f,  1.0f, 0.0f),

+                                    vec3( 1.0f, -1.0f, 0.0f),

+                                    vec3( 1.0f,  1.0f, 0.0f),

+                                    vec3(-1.0f,  1.0f, 0.0f),

+                                    vec3( 1.0f, -1.0f, 0.0f)

+                                    );

+

+        void main() {

+           gl_Position = vec4(pos[gl_VertexIndex], 1.0);

+        })";

+        pipelineDescriptor.cVertexStage.module =

+            utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vs);

+

+        const char* fs =

+            "#version 450\n"

+            "layout(location = 0) out vec4 fragColor;"

+            "void main() {\n"

+            "   fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"

+            "}\n";

+        pipelineDescriptor.cFragmentStage.module =

+            utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, fs);

+

+        pipelineDescriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Equal;

+        pipelineDescriptor.cDepthStencilState.stencilFront.compare = dawn::CompareFunction::Equal;

+        pipelineDescriptor.depthStencilState = &pipelineDescriptor.cDepthStencilState;

+

+        return device.CreateRenderPipeline(&pipelineDescriptor);

+    }

     constexpr static uint32_t kSize = 128;

+    constexpr static dawn::TextureFormat kColorFormat = dawn::TextureFormat::RGBA8Unorm;

+    constexpr static dawn::TextureFormat kDepthStencilFormat =

+        dawn::TextureFormat::Depth24PlusStencil8;

 };

 

 // This tests that the code path of CopyTextureToBuffer clears correctly to Zero after first usage

 TEST_P(TextureZeroInitTest, RecycleTextureMemoryClear) {

     dawn::TextureDescriptor descriptor = CreateTextureDescriptor(

-        1, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc);

+        1, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture texture = device.CreateTexture(&descriptor);

 

     // Texture's first usage is in EXPECT_PIXEL_RGBA8_EQ's call to CopyTextureToBuffer

@@ -66,14 +104,14 @@
 // This goes through the BeginRenderPass's code path

 TEST_P(TextureZeroInitTest, MipMapClearsToZero) {

     dawn::TextureDescriptor descriptor = CreateTextureDescriptor(

-        4, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc);

+        4, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture texture = device.CreateTexture(&descriptor);

 

     dawn::TextureViewDescriptor viewDescriptor = CreateTextureViewDescriptor(2, 0);

     dawn::TextureView view = texture.CreateView(&viewDescriptor);

 

-    utils::BasicRenderPass renderPass =

-        utils::BasicRenderPass(kSize, kSize, texture, dawn::TextureFormat::RGBA8Unorm);

+    utils::BasicRenderPass renderPass = utils::BasicRenderPass(kSize, kSize, texture, kColorFormat);

 

     renderPass.renderPassInfo.cColorAttachmentsInfoPtr[0]->attachment = view;

     dawn::CommandEncoder encoder = device.CreateCommandEncoder();

@@ -95,14 +133,14 @@
 // This goes through the BeginRenderPass's code path

 TEST_P(TextureZeroInitTest, ArrayLayerClearsToZero) {

     dawn::TextureDescriptor descriptor = CreateTextureDescriptor(

-        1, 4, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc);

+        1, 4, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture texture = device.CreateTexture(&descriptor);

 

     dawn::TextureViewDescriptor viewDescriptor = CreateTextureViewDescriptor(0, 2);

     dawn::TextureView view = texture.CreateView(&viewDescriptor);

 

-    utils::BasicRenderPass renderPass =

-        utils::BasicRenderPass(kSize, kSize, texture, dawn::TextureFormat::RGBA8Unorm);

+    utils::BasicRenderPass renderPass = utils::BasicRenderPass(kSize, kSize, texture, kColorFormat);

 

     renderPass.renderPassInfo.cColorAttachmentsInfoPtr[0]->attachment = view;

     dawn::CommandEncoder encoder = device.CreateCommandEncoder();

@@ -125,7 +163,8 @@
     dawn::TextureDescriptor descriptor = CreateTextureDescriptor(

         4, 1,

         dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled |

-            dawn::TextureUsageBit::TransferSrc);

+            dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture texture = device.CreateTexture(&descriptor);

 

     std::vector<uint8_t> data(4 * kSize * kSize, 100);

@@ -150,7 +189,8 @@
     dawn::TextureDescriptor descriptor = CreateTextureDescriptor(

         4, 1,

         dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled |

-            dawn::TextureUsageBit::TransferSrc);

+            dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture texture = device.CreateTexture(&descriptor);

 

     std::vector<uint8_t> data(4 * kSize * kSize, 100);

@@ -175,7 +215,7 @@
 // This tests CopyTextureToTexture fully overwrites copy so lazy init is not needed.

 TEST_P(TextureZeroInitTest, CopyTextureToTexture) {

     dawn::TextureDescriptor srcDescriptor = CreateTextureDescriptor(

-        1, 1, dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::TransferSrc);

+        1, 1, dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::TransferSrc, kColorFormat);

     dawn::Texture srcTexture = device.CreateTexture(&srcDescriptor);

 

     dawn::TextureCopyView srcTextureCopyView =

@@ -184,7 +224,8 @@
     dawn::TextureDescriptor dstDescriptor = CreateTextureDescriptor(

         1, 1,

         dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferDst |

-            dawn::TextureUsageBit::TransferSrc);

+            dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture dstTexture = device.CreateTexture(&dstDescriptor);

 

     dawn::TextureCopyView dstTextureCopyView =

@@ -209,7 +250,8 @@
     dawn::TextureDescriptor srcDescriptor = CreateTextureDescriptor(

         1, 1,

         dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::TransferSrc |

-            dawn::TextureUsageBit::TransferDst);

+            dawn::TextureUsageBit::TransferDst,

+        kColorFormat);

     dawn::Texture srcTexture = device.CreateTexture(&srcDescriptor);

 

     // fill srcTexture with 100

@@ -234,7 +276,8 @@
     dawn::TextureDescriptor dstDescriptor = CreateTextureDescriptor(

         1, 1,

         dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferDst |

-            dawn::TextureUsageBit::TransferSrc);

+            dawn::TextureUsageBit::TransferSrc,

+        kColorFormat);

     dawn::Texture dstTexture = device.CreateTexture(&dstDescriptor);

 

     dawn::TextureCopyView dstTextureCopyView =

@@ -255,6 +298,107 @@
                             0);

 }

 

+// This tests the texture with depth attachment and load op load will init depth stencil texture to

+// 0s.

+TEST_P(TextureZeroInitTest, DepthClear) {

+    dawn::TextureDescriptor srcDescriptor = CreateTextureDescriptor(

+        1, 1,

+        dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::TransferDst |

+            dawn::TextureUsageBit::OutputAttachment,

+        kColorFormat);

+    dawn::Texture srcTexture = device.CreateTexture(&srcDescriptor);

+

+    dawn::TextureDescriptor depthStencilDescriptor = CreateTextureDescriptor(

+        1, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc,

+        kDepthStencilFormat);

+    dawn::Texture depthStencilTexture = device.CreateTexture(&depthStencilDescriptor);

+

+    utils::ComboRenderPassDescriptor renderPassDescriptor({srcTexture.CreateDefaultView()},

+                                                          depthStencilTexture.CreateDefaultView());

+    renderPassDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Load;

+    renderPassDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Clear;

+    renderPassDescriptor.cDepthStencilAttachmentInfo.clearStencil = 0;

+

+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();

+    auto pass = encoder.BeginRenderPass(&renderPassDescriptor);

+    pass.SetPipeline(CreatePipelineForTest());

+    pass.Draw(6, 1, 0, 0);

+    pass.EndPass();

+    dawn::CommandBuffer commandBuffer = encoder.Finish();

+    queue.Submit(1, &commandBuffer);

+

+    // Expect the texture to be red because depth test passed.

+    std::vector<RGBA8> expected(kSize * kSize, {255, 0, 0, 255});

+    EXPECT_TEXTURE_RGBA8_EQ(expected.data(), srcTexture, 0, 0, kSize, kSize, 0, 0);

+}

+

+// This tests the texture with stencil attachment and load op load will init depth stencil texture

+// to 0s.

+TEST_P(TextureZeroInitTest, StencilClear) {

+    dawn::TextureDescriptor srcDescriptor = CreateTextureDescriptor(

+        1, 1,

+        dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::TransferDst |

+            dawn::TextureUsageBit::OutputAttachment,

+        kColorFormat);

+    dawn::Texture srcTexture = device.CreateTexture(&srcDescriptor);

+

+    dawn::TextureDescriptor depthStencilDescriptor = CreateTextureDescriptor(

+        1, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc,

+        kDepthStencilFormat);

+    dawn::Texture depthStencilTexture = device.CreateTexture(&depthStencilDescriptor);

+

+    utils::ComboRenderPassDescriptor renderPassDescriptor({srcTexture.CreateDefaultView()},

+                                                          depthStencilTexture.CreateDefaultView());

+    renderPassDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Clear;

+    renderPassDescriptor.cDepthStencilAttachmentInfo.clearDepth = 0.0f;

+    renderPassDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Load;

+

+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();

+    auto pass = encoder.BeginRenderPass(&renderPassDescriptor);

+    pass.SetPipeline(CreatePipelineForTest());

+    pass.Draw(6, 1, 0, 0);

+    pass.EndPass();

+    dawn::CommandBuffer commandBuffer = encoder.Finish();

+    queue.Submit(1, &commandBuffer);

+

+    // Expect the texture to be red because stencil test passed.

+    std::vector<RGBA8> expected(kSize * kSize, {255, 0, 0, 255});

+    EXPECT_TEXTURE_RGBA8_EQ(expected.data(), srcTexture, 0, 0, kSize, kSize, 0, 0);

+}

+

+// This tests the texture with depth stencil attachment and load op load will init depth stencil

+// texture to 0s.

+TEST_P(TextureZeroInitTest, DepthStencilClear) {

+    dawn::TextureDescriptor srcDescriptor = CreateTextureDescriptor(

+        1, 1,

+        dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::TransferDst |

+            dawn::TextureUsageBit::OutputAttachment,

+        kColorFormat);

+    dawn::Texture srcTexture = device.CreateTexture(&srcDescriptor);

+

+    dawn::TextureDescriptor depthStencilDescriptor = CreateTextureDescriptor(

+        1, 1, dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc,

+        kDepthStencilFormat);

+    dawn::Texture depthStencilTexture = device.CreateTexture(&depthStencilDescriptor);

+

+    utils::ComboRenderPassDescriptor renderPassDescriptor({srcTexture.CreateDefaultView()},

+                                                          depthStencilTexture.CreateDefaultView());

+    renderPassDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Load;

+    renderPassDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Load;

+

+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();

+    auto pass = encoder.BeginRenderPass(&renderPassDescriptor);

+    pass.SetPipeline(CreatePipelineForTest());

+    pass.Draw(6, 1, 0, 0);

+    pass.EndPass();

+    dawn::CommandBuffer commandBuffer = encoder.Finish();

+    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});

+    EXPECT_TEXTURE_RGBA8_EQ(expected.data(), srcTexture, 0, 0, kSize, kSize, 0, 0);

+}

+

 DAWN_INSTANTIATE_TEST(TextureZeroInitTest,

                       ForceWorkarounds(VulkanBackend,

                                        {"nonzero_clear_resources_on_creation_for_testing"}));