Remove GrStencilSettings from GrPipeline

Updates the GrPipeline to have user stencil settings instead of actual
settings. This allows us to further defer creating and attaching a
stencil buffer.

This change is a partial step. The ultimate goal is to attach the
stencil buffer and create the stencil settings during render target
flush, but for the sake of keeping this CL smaller, we create the
stencil settings right before use for now.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2468653002

Review-Url: https://codereview.chromium.org/2468653002
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index bee578a..1b9be53 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -19,6 +19,7 @@
 #include "GrResourceProvider.h"
 #include "GrRenderTargetPriv.h"
 #include "GrStencilAttachment.h"
+#include "GrStencilSettings.h"
 #include "GrSurfacePriv.h"
 #include "GrTexturePriv.h"
 #include "SkMathPriv.h"
@@ -442,10 +443,18 @@
     }
 }
 
-const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(GrRenderTarget* rt,
-                                                            const GrStencilSettings& stencil) {
+const GrGpu::MultisampleSpecs& GrGpu::queryMultisampleSpecs(const GrPipeline& pipeline) {
+    GrRenderTarget* rt = pipeline.getRenderTarget();
     SkASSERT(rt->desc().fSampleCnt > 1);
 
+    GrStencilSettings stencil;
+    if (pipeline.isStencilEnabled()) {
+        // TODO: attach stencil and create settings during render target flush.
+        SkASSERT(rt->renderTargetPriv().getStencilAttachment());
+        stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
+                      rt->renderTargetPriv().numStencilBits());
+    }
+
     int effectiveSampleCnt;
     SkSTArray<16, SkPoint, true> pattern;
     this->onQueryMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &pattern);
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 48005ec..475950a 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -355,10 +355,10 @@
         const SkPoint*   fSampleLocations;
     };
 
-    // Finds a render target's multisample specs. The stencil settings are only needed in case we
-    // need to flush the draw state prior to querying multisample info. They are not expected to
+    // Finds a render target's multisample specs. The pipeline is only needed in case we need to
+    // flush the draw state prior to querying multisample info. The pipeline is not expected to
     // affect the multisample information itself.
-    const MultisampleSpecs& queryMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&);
+    const MultisampleSpecs& queryMultisampleSpecs(const GrPipeline&);
 
     // Finds the multisample specs with a given unique id.
     const MultisampleSpecs& getMultisampleSpecs(uint8_t uniqueID) {
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index 08ffeb5..0ac17e7 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -21,19 +21,15 @@
 GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
                                  GrXPOverridesForBatch* overrides) {
     const GrPipelineBuilder& builder = *args.fPipelineBuilder;
+    const GrUserStencilSettings* userStencil = builder.getUserStencil();
+    GrRenderTarget* rt = args.fRenderTargetContext->accessRenderTarget();
 
     GrPipeline* pipeline = new (memory) GrPipeline;
-    GrRenderTarget* rt = args.fRenderTargetContext->accessRenderTarget();
     pipeline->fRenderTarget.reset(rt);
     SkASSERT(pipeline->fRenderTarget);
     pipeline->fScissorState = *args.fScissor;
     pipeline->fWindowRectsState = *args.fWindowRectsState;
-    if (builder.hasUserStencilSettings() || args.fHasStencilClip) {
-        const GrRenderTargetPriv& rtPriv = rt->renderTargetPriv();
-        pipeline->fStencilSettings.reset(*builder.getUserStencil(), args.fHasStencilClip,
-                                         rtPriv.numStencilBits());
-        SkASSERT(!pipeline->fStencilSettings.usesWrapOp() || args.fCaps->stencilWrapOpsSupport());
-    }
+    pipeline->fUserStencilSettings = userStencil;
     pipeline->fDrawFace = builder.getDrawFace();
 
     pipeline->fFlags = 0;
@@ -55,10 +51,13 @@
     if (args.fHasStencilClip) {
         pipeline->fFlags |= kHasStencilClip_Flag;
     }
+    if (!userStencil->isDisabled(args.fHasStencilClip)) {
+        pipeline->fFlags |= kStencilEnabled_Flag;
+    }
 
     // Create XferProcessor from DS's XPFactory
     bool hasMixedSamples = args.fRenderTargetContext->hasMixedSamples() &&
-                           (builder.isHWAntialias() || !pipeline->fStencilSettings.isDisabled());
+                           (builder.isHWAntialias() || pipeline->isStencilEnabled());
     const GrXPFactory* xpFactory = builder.getXPFactory();
     SkAutoTUnref<GrXferProcessor> xferProcessor;
     if (xpFactory) {
@@ -88,7 +87,7 @@
     const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
                                                        &GrPorterDuffXPFactory::SimpleSrcOverXP();
     optFlags = xpForOpts->getOptimizations(args.fOpts,
-                                           pipeline->fStencilSettings.doesWrite(),
+                                           userStencil->doesWrite(args.fHasStencilClip),
                                            &overrideColor,
                                            *args.fCaps);
 
@@ -226,7 +225,7 @@
         a.fScissorState != b.fScissorState ||
         !a.fWindowRectsState.cheapEqualTo(b.fWindowRectsState) ||
         a.fFlags != b.fFlags ||
-        a.fStencilSettings != b.fStencilSettings ||
+        a.fUserStencilSettings != b.fUserStencilSettings ||
         a.fDrawFace != b.fDrawFace ||
         a.fIgnoresCoverage != b.fIgnoresCoverage) {
         return false;
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 10ccc80..2c7c779 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -16,7 +16,7 @@
 #include "GrProcOptInfo.h"
 #include "GrProgramDesc.h"
 #include "GrScissorState.h"
-#include "GrStencilSettings.h"
+#include "GrUserStencilSettings.h"
 #include "GrWindowRectsState.h"
 #include "SkMatrix.h"
 #include "SkRefCnt.h"
@@ -148,7 +148,7 @@
      */
     GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
 
-    const GrStencilSettings& getStencil() const { return fStencilSettings; }
+    const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
 
     const GrScissorState& getScissorState() const { return fScissorState; }
 
@@ -168,6 +168,9 @@
     bool hasStencilClip() const {
         return SkToBool(fFlags & kHasStencilClip_Flag);
     }
+    bool isStencilEnabled() const {
+        return SkToBool(fFlags & kStencilEnabled_Flag);
+    }
 
     GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
         return this->getXferProcessor().xferBarrierType(fRenderTarget.get(), caps);
@@ -213,6 +216,7 @@
         kAllowSRGBInputs_Flag               = 0x8,
         kUsesDistanceVectorField_Flag       = 0x10,
         kHasStencilClip_Flag                = 0x20,
+        kStencilEnabled_Flag                = 0x40,
     };
 
     typedef GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> RenderTarget;
@@ -222,7 +226,7 @@
     RenderTarget                        fRenderTarget;
     GrScissorState                      fScissorState;
     GrWindowRectsState                  fWindowRectsState;
-    GrStencilSettings                   fStencilSettings;
+    const GrUserStencilSettings*        fUserStencilSettings;
     GrDrawFace                          fDrawFace;
     uint32_t                            fFlags;
     ProgramXferProcessor                fXferProcessor;
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index cfcdbb5..3b0e54b 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -165,7 +165,7 @@
     if (requiredFeatures & GrProcessor::kSampleLocations_RequiredFeature) {
         SkASSERT(pipeline.isHWAntialiasState());
         header->fSamplePatternKey =
-            rt->renderTargetPriv().getMultisampleSpecs(pipeline.getStencil()).fUniqueID;
+            rt->renderTargetPriv().getMultisampleSpecs(pipeline).fUniqueID;
     } else {
         header->fSamplePatternKey = 0;
     }
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 7b526ee..a82048b 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -16,6 +16,7 @@
 #include "GrDrawingManager.h"
 #include "GrFixedClip.h"
 #include "GrPathRenderer.h"
+#include "GrStencilSettings.h"
 #include "GrStyle.h"
 #include "GrUserStencilSettings.h"
 
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index 09d43f9..e7782cc 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -15,6 +15,7 @@
 #include "GrRenderTargetOpList.h"
 #include "GrRenderTargetPriv.h"
 #include "GrStencilAttachment.h"
+#include "GrStencilSettings.h"
 
 GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc, Flags flags,
                                GrStencilAttachment* stencil)
@@ -100,17 +101,19 @@
 }
 
 int GrRenderTargetPriv::numStencilBits() const {
-    return fRenderTarget->fStencilAttachment ? fRenderTarget->fStencilAttachment->bits() : 0;
+    SkASSERT(this->getStencilAttachment());
+    return this->getStencilAttachment()->bits();
 }
 
 const GrGpu::MultisampleSpecs&
-GrRenderTargetPriv::getMultisampleSpecs(const GrStencilSettings& stencil) const {
+GrRenderTargetPriv::getMultisampleSpecs(const GrPipeline& pipeline) const {
+    SkASSERT(fRenderTarget == pipeline.getRenderTarget()); // TODO: remove RT from pipeline.
     GrGpu* gpu = fRenderTarget->getGpu();
     if (auto id = fRenderTarget->fMultisampleSpecsID) {
-        SkASSERT(gpu->queryMultisampleSpecs(fRenderTarget, stencil).fUniqueID == id);
+        SkASSERT(gpu->queryMultisampleSpecs(pipeline).fUniqueID == id);
         return gpu->getMultisampleSpecs(id);
     }
-    const GrGpu::MultisampleSpecs& specs = gpu->queryMultisampleSpecs(fRenderTarget, stencil);
+    const GrGpu::MultisampleSpecs& specs = gpu->queryMultisampleSpecs(pipeline);
     fRenderTarget->fMultisampleSpecsID = specs.fUniqueID;
     return specs;
 }
diff --git a/src/gpu/GrRenderTargetPriv.h b/src/gpu/GrRenderTargetPriv.h
index 922d9b3..19e7263 100644
--- a/src/gpu/GrRenderTargetPriv.h
+++ b/src/gpu/GrRenderTargetPriv.h
@@ -32,10 +32,10 @@
 
     int numStencilBits() const;
 
-    // Finds a render target's multisample specs. The stencil settings are only needed in case the
-    // info isn't cached and we need to flush the draw state in order to query it. They are not
-    // expected to affect the multisample information itself.
-    const GrGpu::MultisampleSpecs& getMultisampleSpecs(const GrStencilSettings& stencil) const;
+    // Finds a render target's multisample specs. The pipeline is only needed in case the info isn't
+    // cached and we need to flush the draw state in order to query it. The pipeline is not expected
+    // to affect the multisample information itself.
+    const GrGpu::MultisampleSpecs& getMultisampleSpecs(const GrPipeline&) const;
 
     typedef GrRenderTarget::Flags Flags;
 
diff --git a/src/gpu/GrStencilSettings.cpp b/src/gpu/GrStencilSettings.cpp
index d3216db..cec8bee 100644
--- a/src/gpu/GrStencilSettings.cpp
+++ b/src/gpu/GrStencilSettings.cpp
@@ -28,6 +28,7 @@
                               int numStencilBits) {
     uint16_t frontFlags = user.fFrontFlags[hasStencilClip];
     if (frontFlags & kSingleSided_StencilFlag) {
+        SkASSERT(frontFlags == user.fBackFlags[hasStencilClip]);
         fFlags = frontFlags;
         if (!this->isDisabled()) {
             fFront.reset(user.fFront, hasStencilClip, numStencilBits);
diff --git a/src/gpu/GrUserStencilSettings.h b/src/gpu/GrUserStencilSettings.h
index 1800259..3cbadfd 100644
--- a/src/gpu/GrUserStencilSettings.h
+++ b/src/gpu/GrUserStencilSettings.h
@@ -182,6 +182,22 @@
     GrUserStencilSettings() = delete;
     GrUserStencilSettings(const GrUserStencilSettings&) = delete;
 
+    uint16_t flags(bool hasStencilClip) const {
+        return fFrontFlags[hasStencilClip] & fBackFlags[hasStencilClip];
+    }
+    bool isDisabled(bool hasStencilClip) const {
+        return this->flags(hasStencilClip) & kDisabled_StencilFlag;
+    }
+    bool doesWrite(bool hasStencilClip) const {
+        return !(this->flags(hasStencilClip) & kNoModifyStencil_StencilFlag);
+    }
+    bool isTwoSided(bool hasStencilClip) const {
+        return !(this->flags(hasStencilClip) & kSingleSided_StencilFlag);
+    }
+    bool usesWrapOp(bool hasStencilClip) const {
+        return !(this->flags(hasStencilClip) & kNoWrapOps_StencilFlag);
+    }
+
     const uint16_t   fFrontFlags[2]; // frontFlagsForDraw = fFrontFlags[hasStencilClip].
     const Face       fFront;
     const uint16_t   fBackFlags[2]; // backFlagsForDraw = fBackFlags[hasStencilClip].
diff --git a/src/gpu/batches/GrDrawPathBatch.h b/src/gpu/batches/GrDrawPathBatch.h
index 6adc943..79b8b57 100644
--- a/src/gpu/batches/GrDrawPathBatch.h
+++ b/src/gpu/batches/GrDrawPathBatch.h
@@ -14,6 +14,7 @@
 #include "GrPath.h"
 #include "GrPathRendering.h"
 #include "GrPathProcessor.h"
+#include "GrStencilSettings.h"
 
 #include "SkTLList.h"
 
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 454753c..6d50ee2 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2052,10 +2052,17 @@
     program->setData(primProc, pipeline);
 
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
-    this->flushStencil(pipeline.getStencil());
+    GrStencilSettings stencil;
+    if (pipeline.isStencilEnabled()) {
+        // TODO: attach stencil and create settings during render target flush.
+        SkASSERT(glRT->renderTargetPriv().getStencilAttachment());
+        stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
+                      glRT->renderTargetPriv().numStencilBits());
+    }
+    this->flushStencil(stencil);
     this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
     this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT);
-    this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled());
+    this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), stencil.isDisabled());
 
     // This must come after textures are flushed because a texture may need
     // to be msaa-resolved (which will modify bound FBO state).
diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h
index 40f72cc..d7a7dbf 100644
--- a/src/gpu/gl/GrGLPathRendering.h
+++ b/src/gpu/gl/GrGLPathRendering.h
@@ -10,12 +10,12 @@
 
 #include "SkRefCnt.h"
 #include "GrPathRendering.h"
+#include "GrStencilSettings.h"
 #include "gl/GrGLTypes.h"
 #include "glsl/GrGLSLUtil.h"
 
 class GrGLNameAllocator;
 class GrGLGpu;
-class GrStencilSettings;
 class GrStyle;
 
 /**
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index db420c8..a9493b8 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -357,7 +357,7 @@
     SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
     const GrPipeline& pipeline = fProgramBuilder->pipeline();
     const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
-    const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline.getStencil());
+    const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
     SkSTArray<16, SkPoint, true> offsets;
     offsets.push_back_n(specs.fEffectiveSampleCnt);
     m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
diff --git a/src/gpu/instanced/InstanceProcessor.cpp b/src/gpu/instanced/InstanceProcessor.cpp
index 55be89e..475b020 100644
--- a/src/gpu/instanced/InstanceProcessor.cpp
+++ b/src/gpu/instanced/InstanceProcessor.cpp
@@ -1701,7 +1701,7 @@
         case AntialiasMode::kMSAA:
         case AntialiasMode::kMixedSamples: {
             const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
-            const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline.getStencil());
+            const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
             return new BackendMultisample(batchInfo, inputs, specs.fEffectiveSampleCnt);
         }
     }
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index 9103981..40a6cf0 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -397,6 +397,7 @@
 }
 
 GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
+                                   const GrStencilSettings& stencil,
                                    const GrPrimitiveProcessor& primProc,
                                    VkPipelineShaderStageCreateInfo* shaderStageInfo,
                                    int shaderStageCount,
@@ -415,7 +416,7 @@
     setup_input_assembly_state(primitiveType, &inputAssemblyInfo);
 
     VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
-    setup_depth_stencil_state(pipeline.getStencil(), &depthStencilInfo);
+    setup_depth_stencil_state(stencil, &depthStencilInfo);
 
     VkPipelineViewportStateCreateInfo viewportInfo;
     setup_viewport_scissor_state(&viewportInfo);
diff --git a/src/gpu/vk/GrVkPipeline.h b/src/gpu/vk/GrVkPipeline.h
index 2565185..b4788de 100644
--- a/src/gpu/vk/GrVkPipeline.h
+++ b/src/gpu/vk/GrVkPipeline.h
@@ -17,6 +17,7 @@
 class GrNonInstancedVertices;
 class GrPipeline;
 class GrPrimitiveProcessor;
+class GrStencilSettings;
 class GrVkCommandBuffer;
 class GrVkGpu;
 class GrVkRenderPass;
@@ -25,6 +26,7 @@
 public:
     static GrVkPipeline* Create(GrVkGpu* gpu,
                                 const GrPipeline& pipeline,
+                                const GrStencilSettings&,
                                 const GrPrimitiveProcessor& primProc,
                                 VkPipelineShaderStageCreateInfo* shaderStageInfo,
                                 int shaderStageCount,
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 71ce831..abb95f6 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -492,6 +492,7 @@
 bool GrVkPipelineState::Desc::Build(Desc* desc,
                                     const GrPrimitiveProcessor& primProc,
                                     const GrPipeline& pipeline,
+                                    const GrStencilSettings& stencil,
                                     GrPrimitiveType primitiveType,
                                     const GrGLSLCaps& caps) {
     if (!INHERITED::Build(desc, primProc, primitiveType == kPoints_GrPrimitiveType, pipeline,
@@ -503,7 +504,7 @@
     GrVkRenderTarget* vkRT = (GrVkRenderTarget*)pipeline.getRenderTarget();
     vkRT->simpleRenderPass()->genKey(&b);
 
-    pipeline.getStencil().genKey(&b);
+    stencil.genKey(&b);
 
     SkASSERT(sizeof(GrDrawFace) <= sizeof(uint32_t));
     b.add32((int32_t)pipeline.getDrawFace());
diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h
index d15fef4..ba8a21f 100644
--- a/src/gpu/vk/GrVkPipelineState.h
+++ b/src/gpu/vk/GrVkPipelineState.h
@@ -74,6 +74,7 @@
         static bool Build(Desc*,
                           const GrPrimitiveProcessor&,
                           const GrPipeline&,
+                          const GrStencilSettings&,
                           GrPrimitiveType primitiveType,
                           const GrGLSLCaps&);
     private:
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index 69ae4a4..c088a8a 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -14,6 +14,7 @@
 GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
                                                                GrVkGpu* gpu,
                                                                const GrPipeline& pipeline,
+                                                               const GrStencilSettings& stencil,
                                                                const GrPrimitiveProcessor& primProc,
                                                                GrPrimitiveType primitiveType,
                                                                const GrVkPipelineState::Desc& desc,
@@ -30,7 +31,7 @@
         return nullptr;
     }
 
-    return builder.finalize(primitiveType, renderPass, desc);
+    return builder.finalize(stencil, primitiveType, renderPass, desc);
 }
 
 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
@@ -73,7 +74,8 @@
     return GrCompileVkShaderModule(gpu, shaderString.c_str(), stage, shaderModule, stageInfo);
 }
 
-GrVkPipelineState* GrVkPipelineStateBuilder::finalize(GrPrimitiveType primitiveType,
+GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
+                                                      GrPrimitiveType primitiveType,
                                                       const GrVkRenderPass& renderPass,
                                                       const GrVkPipelineState::Desc& desc) {
     VkDescriptorSetLayout dsLayout[2];
@@ -129,6 +131,7 @@
                                         &shaderStageInfo[1]));
 
     GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
+                                                             stencil,
                                                              fPrimProc,
                                                              shaderStageInfo,
                                                              2,
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.h b/src/gpu/vk/GrVkPipelineStateBuilder.h
index c887e36..cf9237a 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.h
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.h
@@ -31,6 +31,7 @@
     */
     static GrVkPipelineState* CreatePipelineState(GrVkGpu*,
                                                   const GrPipeline&,
+                                                  const GrStencilSettings&,
                                                   const GrPrimitiveProcessor&,
                                                   GrPrimitiveType,
                                                   const GrVkPipelineState::Desc&,
@@ -50,7 +51,8 @@
                              const GrPrimitiveProcessor&,
                              const GrProgramDesc&);
 
-    GrVkPipelineState* finalize(GrPrimitiveType primitiveType,
+    GrVkPipelineState* finalize(const GrStencilSettings&,
+                                GrPrimitiveType primitiveType,
                                 const GrVkRenderPass& renderPass,
                                 const GrVkPipelineState::Desc&);
 
diff --git a/src/gpu/vk/GrVkPipelineStateCache.cpp b/src/gpu/vk/GrVkPipelineStateCache.cpp
index 2e6a85b..2bc4210 100644
--- a/src/gpu/vk/GrVkPipelineStateCache.cpp
+++ b/src/gpu/vk/GrVkPipelineStateCache.cpp
@@ -9,6 +9,7 @@
 
 #include "GrVkGpu.h"
 #include "GrProcessor.h"
+#include "GrRenderTargetPriv.h" // TODO: remove once refPipelineState gets passed stencil settings.
 #include "GrVkPipelineState.h"
 #include "GrVkPipelineStateBuilder.h"
 #include "SkOpts.h"
@@ -97,10 +98,19 @@
 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     ++fTotalRequests;
 #endif
+    GrStencilSettings stencil;
+    if (pipeline.isStencilEnabled()) {
+        GrRenderTarget* rt = pipeline.getRenderTarget();
+        // TODO: attach stencil and create settings during render target flush.
+        SkASSERT(rt->renderTargetPriv().getStencilAttachment());
+        stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
+                      rt->renderTargetPriv().numStencilBits());
+    }
+
     // Get GrVkProgramDesc
     GrVkPipelineState::Desc desc;
-    if (!GrVkPipelineState::Desc::Build(&desc, primProc, pipeline, primitiveType,
-                                        *fGpu->vkCaps().glslCaps())) {
+    if (!GrVkPipelineState::Desc::Build(&desc, primProc, pipeline, stencil,
+                                        primitiveType, *fGpu->vkCaps().glslCaps())) {
         GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
         return nullptr;
     }
@@ -118,6 +128,7 @@
         sk_sp<GrVkPipelineState> pipelineState(
             GrVkPipelineStateBuilder::CreatePipelineState(fGpu,
                                                           pipeline,
+                                                          stencil,
                                                           primProc,
                                                           primitiveType,
                                                           desc,
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index 3027c2d..ca4d52e9 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -57,6 +57,7 @@
 }
 
 GrVkPipeline* GrVkResourceProvider::createPipeline(const GrPipeline& pipeline,
+                                                   const GrStencilSettings& stencil,
                                                    const GrPrimitiveProcessor& primProc,
                                                    VkPipelineShaderStageCreateInfo* shaderStageInfo,
                                                    int shaderStageCount,
@@ -64,8 +65,9 @@
                                                    const GrVkRenderPass& renderPass,
                                                    VkPipelineLayout layout) {
 
-    return GrVkPipeline::Create(fGpu, pipeline, primProc, shaderStageInfo, shaderStageCount,
-                                primitiveType, renderPass, layout, fPipelineCache);
+    return GrVkPipeline::Create(fGpu, pipeline, stencil, primProc, shaderStageInfo,
+                                shaderStageCount, primitiveType, renderPass, layout,
+                                fPipelineCache);
 }
 
 GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h
index 8200123..0c9397e 100644
--- a/src/gpu/vk/GrVkResourceProvider.h
+++ b/src/gpu/vk/GrVkResourceProvider.h
@@ -44,6 +44,7 @@
     void init();
 
     GrVkPipeline* createPipeline(const GrPipeline& pipeline,
+                                 const GrStencilSettings& stencil,
                                  const GrPrimitiveProcessor& primProc,
                                  VkPipelineShaderStageCreateInfo* shaderStageInfo,
                                  int shaderStageCount,