Vulkan: Implement masked depth & stencil clear

This commit also adds tests for clearing depth and stencil with
mask/scissor.

Bug: angleproject:2540
Change-Id: I30dd840afd6cdd4e3a38c50fcba4c8623513ceb0
Reviewed-on: https://chromium-review.googlesource.com/c/1307585
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 8e91a53..39abce1 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -178,6 +178,9 @@
     bool clearDepth = (depthAttachment && (mask & GL_DEPTH_BUFFER_BIT) != 0);
     ASSERT(!clearDepth || depthAttachment->isAttached());
 
+    // If depth write is disabled, pretend that GL_DEPTH_BUFFER_BIT is not specified altogether.
+    clearDepth = clearDepth && contextVk->getGLState().getDepthStencilState().depthMask;
+
     const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment();
     bool clearStencil = (stencilAttachment && (mask & GL_STENCIL_BUFFER_BIT) != 0);
     ASSERT(!clearStencil || stencilAttachment->isAttached());
@@ -203,8 +206,6 @@
 
         if (clearDepth || clearStencil)
         {
-            // Masked stencil clears are currently not implemented.
-            // TODO(jmadill): Masked stencil clear. http://anglebug.com/2540
             ANGLE_TRY(clearWithClearAttachments(contextVk, false, clearDepth, clearStencil));
         }
         return angle::Result::Continue();
@@ -222,9 +223,6 @@
         // With scissor test enabled, we clear very differently and we don't need to access
         // the image inside each attachment we can just use clearCmdAttachments with our
         // scissor region instead.
-
-        // Masked stencil clears are currently not implemented.
-        // TODO(jmadill): Masked stencil clear. http://anglebug.com/2540
         ANGLE_TRY(clearWithClearAttachments(contextVk, clearColor, clearDepth, clearStencil));
         return angle::Result::Continue();
     }
@@ -234,9 +232,13 @@
     {
         ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
 
-        const VkClearDepthStencilValue &clearDepthStencilValue =
+        VkClearDepthStencilValue clearDepthStencilValue =
             contextVk->getClearDepthStencilValue().depthStencil;
 
+        // Apply the stencil mask to the clear value.
+        clearDepthStencilValue.stencil &=
+            contextVk->getGLState().getDepthStencilState().stencilWritemask;
+
         RenderTargetVk *renderTarget         = mRenderTargetCache.getDepthStencil();
         const angle::Format &format          = renderTarget->getImageFormat().textureFormat();
         const VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
@@ -936,6 +938,16 @@
         }
     }
 
+    VkClearValue depthStencilClearValue = contextVk->getClearDepthStencilValue();
+
+    // Apply the stencil mask to the clear value.  Stencil mask is generally respected through the
+    // respective pipeline state, but clear uses its own special function.
+    if (clearStencil)
+    {
+        depthStencilClearValue.depthStencil.stencil &=
+            contextVk->getGLState().getDepthStencilState().stencilWritemask;
+    }
+
     if (clearDepth && clearStencil && mState.getDepthStencilAttachment() != nullptr)
     {
         // When we have a packed depth/stencil attachment we can do 1 clear for both when it
@@ -943,7 +955,7 @@
         VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
         clearAttachment.aspectMask      = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
         clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
-        clearAttachment.clearValue      = contextVk->getClearDepthStencilValue();
+        clearAttachment.clearValue         = depthStencilClearValue;
         ++clearAttachmentIndex;
     }
     else
@@ -953,7 +965,7 @@
             VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
             clearAttachment.aspectMask         = VK_IMAGE_ASPECT_DEPTH_BIT;
             clearAttachment.colorAttachment    = VK_ATTACHMENT_UNUSED;
-            clearAttachment.clearValue         = contextVk->getClearDepthStencilValue();
+            clearAttachment.clearValue         = depthStencilClearValue;
             ++clearAttachmentIndex;
         }
 
@@ -962,7 +974,7 @@
             VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
             clearAttachment.aspectMask         = VK_IMAGE_ASPECT_STENCIL_BIT;
             clearAttachment.colorAttachment    = VK_ATTACHMENT_UNUSED;
-            clearAttachment.clearValue         = contextVk->getClearDepthStencilValue();
+            clearAttachment.clearValue         = depthStencilClearValue;
             ++clearAttachmentIndex;
         }
     }