Implement various vulkan stencil clears and fix various stenciling bugs.

BUG=skia:4973
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1755753002

Review URL: https://codereview.chromium.org/1755753002
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp
index e43c50f..d26d06d 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -104,7 +104,6 @@
     fActiveRenderPass = renderPass;
     this->addResource(renderPass);
     target.addResources(*this);
-
 }
 
 void GrVkCommandBuffer::endRenderPass(const GrVkGpu* gpu) {
@@ -295,6 +294,22 @@
                                                       subRanges));
 }
 
+void GrVkCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu,
+                                               GrVkImage* image,
+                                               const VkClearDepthStencilValue* color,
+                                               uint32_t subRangeCount,
+                                               const VkImageSubresourceRange* subRanges) {
+    SkASSERT(fIsActive);
+    SkASSERT(!fActiveRenderPass);
+    this->addResource(image->resource());
+    GR_VK_CALL(gpu->vkInterface(), CmdClearDepthStencilImage(fCmdBuffer,
+                                                             image->textureImage(),
+                                                             image->currentLayout(),
+                                                             color,
+                                                             subRangeCount,
+                                                             subRanges));
+}
+
 void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu,
                                          int numAttachments,
                                          const VkClearAttachment* attachments,
diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h
index 33867ab..5cdb2c0 100644
--- a/src/gpu/vk/GrVkCommandBuffer.h
+++ b/src/gpu/vk/GrVkCommandBuffer.h
@@ -114,6 +114,12 @@
                          uint32_t subRangeCount,
                          const VkImageSubresourceRange* subRanges);
 
+    void clearDepthStencilImage(const GrVkGpu* gpu,
+                                GrVkImage* image,
+                                const VkClearDepthStencilValue* color,
+                                uint32_t subRangeCount,
+                                const VkImageSubresourceRange* subRanges);
+
     void copyImage(const GrVkGpu* gpu,
                    GrVkImage* srcImage,
                    VkImageLayout srcLayout,
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index ef2d0be..9528efc 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -520,6 +520,12 @@
     if (renderTarget) {
         tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, desc, lifeCycle,
                                                                     imageDesc);
+#if 0
+        // This clear can be included to fix warning described in htttps://bugs.skia.org/5045
+        // Obviously we do not want to be clearling needlessly every time we create a render target.
+        SkIRect rect = SkIRect::MakeWH(tex->width(), tex->height());
+        this->clear(rect, GrColor_TRANSPARENT_BLACK, tex->asRenderTarget());
+#endif
     } else {
         tex = GrVkTexture::CreateNewTexture(this, desc, lifeCycle, imageDesc);
     }
@@ -882,6 +888,118 @@
     this->submitCommandBuffer(kSkip_SyncQueue);
 }
 
+void GrVkGpu::clearStencil(GrRenderTarget* target) {
+    if (nullptr == target) {
+        return;
+    }
+    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
+    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
+
+
+    VkClearDepthStencilValue vkStencilColor;
+    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
+
+    VkImageLayout origDstLayout = vkStencil->currentLayout();
+
+    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
+    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+
+    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
+    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+
+    vkStencil->setImageLayout(this,
+                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                              srcAccessMask,
+                              dstAccessMask,
+                              srcStageMask,
+                              dstStageMask,
+                              false);
+
+
+    VkImageSubresourceRange subRange;
+    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
+    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+    subRange.baseMipLevel = 0;
+    subRange.levelCount = 1;
+    subRange.baseArrayLayer = 0;
+    subRange.layerCount = 1;
+
+    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
+    // draw. Thus we should look into using the load op functions on the render pass to clear out
+    // the stencil there.
+    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
+}
+
+void GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
+    SkASSERT(target);
+
+    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
+    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
+    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb;
+
+    // this should only be called internally when we know we have a
+    // stencil buffer.
+    SkASSERT(sb);
+    int stencilBitCount = sb->bits();
+
+    // The contract with the callers does not guarantee that we preserve all bits in the stencil
+    // during this clear. Thus we will clear the entire stencil to the desired value.
+
+    VkClearDepthStencilValue vkStencilColor;
+    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
+    if (insideClip) {
+        vkStencilColor.stencil = (1 << (stencilBitCount - 1));
+    } else {
+        vkStencilColor.stencil = 0;
+    }
+
+    VkImageLayout origDstLayout = vkStencil->currentLayout();
+    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
+    VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+    VkPipelineStageFlags srcStageMask =
+        GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
+    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+    vkStencil->setImageLayout(this,
+                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+                              srcAccessMask,
+                              dstAccessMask,
+                              srcStageMask,
+                              dstStageMask,
+                              false);
+
+    VkClearRect clearRect;
+    // Flip rect if necessary
+    SkIRect vkRect = rect;
+
+    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
+        vkRect.fTop = vkRT->height() - rect.fBottom;
+        vkRect.fBottom = vkRT->height() - rect.fTop;
+    }
+
+    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
+    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
+
+    clearRect.baseArrayLayer = 0;
+    clearRect.layerCount = 1;
+
+    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
+    SkASSERT(renderPass);
+    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
+
+    uint32_t stencilIndex;
+    SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex));
+
+    VkClearAttachment attachment;
+    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+    attachment.colorAttachment = 0; // this value shouldn't matter
+    attachment.clearValue.depthStencil = vkStencilColor;
+
+    fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
+    fCurrentCmdBuffer->endRenderPass(this);
+
+    return;
+}
+
 void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
     // parent class should never let us get here with no RT
     SkASSERT(target);
@@ -896,7 +1014,7 @@
         VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
         VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
         VkPipelineStageFlags srcStageMask =
-            GrVkMemory::LayoutToPipelineStageFlags(vkRT->currentLayout());
+            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
         VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
         vkRT->setImageLayout(this,
                              VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@@ -907,12 +1025,14 @@
                              false);
 
         VkClearRect clearRect;
-        clearRect.rect.offset = { rect.fLeft, rect.fTop };
-        clearRect.rect.extent = { (uint32_t)rect.width(), (uint32_t)rect.height() };
-        clearRect.baseArrayLayer = 0;
-        clearRect.layerCount = 1;
-
-
+        // Flip rect if necessary
+        SkIRect vkRect = rect;
+        if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
+            vkRect.fTop = vkRT->height() - rect.fBottom;
+            vkRect.fBottom = vkRT->height() - rect.fTop;
+        }
+        clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
+        clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
 
         const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
         SkASSERT(renderPass);
@@ -1201,7 +1321,6 @@
     const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
     SkASSERT(renderPass);
 
-
     GrVkProgram* program = GrVkProgramBuilder::CreateProgram(this, args,
                                                              vertices.primitiveType(),
                                                              *renderPass);
@@ -1234,6 +1353,26 @@
                          dstStageMask,
                          false);
 
+    // If we are using a stencil attachment we also need to update its layout
+    if (!args.fPipeline->getStencil().isDisabled()) {
+        GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment();
+        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
+        VkImageLayout origDstLayout = vkStencil->currentLayout();
+        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
+        VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+        VkPipelineStageFlags srcStageMask =
+            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
+        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+        vkStencil->setImageLayout(this,
+                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+                                  srcAccessMask,
+                                  dstAccessMask,
+                                  srcStageMask,
+                                  dstStageMask,
+                                  false);
+    }
+
     if (vertices.isIndexed()) {
         fCurrentCmdBuffer->drawIndexed(this,
                                        vertices.indexCount(),
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index e04095e..701eeb7 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -92,9 +92,7 @@
                                                                 int width,
                                                                 int height) override;
 
-    void clearStencil(GrRenderTarget* target) override {
-        SkDebugf("clearStencil not yet implemented for Vulkan\n");
-    }
+    void clearStencil(GrRenderTarget* target) override;
 
     void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {
         SkDebugf("drawDebugWireRect not yet implemented for Vulkan\n");
@@ -149,9 +147,7 @@
 
     void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override;
 
-    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override {
-        SkDebugf("onClearStencilClip not yet implemented for Vulkan\n");
-    }
+    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
 
     void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override;
 
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index f009eaf..8c05de5 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -168,8 +168,8 @@
         stencilInfo->front.depthFailOp = stencilInfo->front.failOp;
         stencilInfo->front.compareOp = stencil_func_to_vk_compare_op(stencilSettings.func(face));
         stencilInfo->front.compareMask = stencilSettings.funcMask(face);
-        stencilInfo->front.writeMask = 0;
-        stencilInfo->front.reference = 0;
+        stencilInfo->front.writeMask = stencilSettings.writeMask(face);
+        stencilInfo->front.reference = stencilSettings.funcRef(face);
 
         // Set back face
         face = GrStencilSettings::kBack_Face;
@@ -178,8 +178,8 @@
         stencilInfo->back.depthFailOp = stencilInfo->front.failOp;
         stencilInfo->back.compareOp = stencil_func_to_vk_compare_op(stencilSettings.func(face));
         stencilInfo->back.compareMask = stencilSettings.funcMask(face);
-        stencilInfo->back.writeMask = 0;
-        stencilInfo->back.reference = 0;
+        stencilInfo->back.writeMask = stencilSettings.writeMask(face);
+        stencilInfo->back.reference = stencilSettings.funcRef(face);
     }
     stencilInfo->minDepthBounds = 0.0f;
     stencilInfo->maxDepthBounds = 1.0f;
@@ -366,8 +366,13 @@
         attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
         attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation);
     }
-    attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
-                                      VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+
+    if (!blendInfo.fWriteColor) {
+        attachmentState->colorWriteMask = 0;
+    } else {
+        attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
+                                          VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+    }
 
     memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo));
     colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
diff --git a/src/gpu/vk/GrVkRenderPass.cpp b/src/gpu/vk/GrVkRenderPass.cpp
index 9c4787b..958d604 100644
--- a/src/gpu/vk/GrVkRenderPass.cpp
+++ b/src/gpu/vk/GrVkRenderPass.cpp
@@ -22,7 +22,7 @@
     attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
     attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
     attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-    attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+    attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
     attachment->initialLayout = layout;
     attachment->finalLayout = layout;
 }
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 87f1f77..ee45aa3 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -196,7 +196,6 @@
     GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
     // Create() will increment the refCount of the image resource if it succeeds
     imageResource->unref(gpu);
-
     return rt;
 }