Add pass-through helper methods from GrOpFlushState to GrOpsRenderPass

Change-Id: Ifa18e909978367a4502dbf6b35a62a437e83b5c2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/276842
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/bench/VertexColorSpaceBench.cpp b/bench/VertexColorSpaceBench.cpp
index 5ef3f2d..3a16a47 100644
--- a/bench/VertexColorSpaceBench.cpp
+++ b/bench/VertexColorSpaceBench.cpp
@@ -261,7 +261,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp
index 32786bc..c75d066 100644
--- a/gm/beziereffects.cpp
+++ b/gm/beziereffects.cpp
@@ -117,7 +117,7 @@
         }
 
         static constexpr int kOneMesh = 1;
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, kOneMesh);
     }
 
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index e8da08c..a429685 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -217,10 +217,9 @@
             fProgramInfo = this->createProgramInfo(flushState);
         }
 
-        GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-        renderPass->bindPipeline(*fProgramInfo, SkRect::MakeXYWH(0, fY, 100, 100));
-        renderPass->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
-        renderPass->draw(4, 0);
+        flushState->bindPipeline(*fProgramInfo, SkRect::MakeXYWH(0, fY, 100, 100));
+        flushState->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
+        flushState->draw(4, 0);
     }
 
     sk_sp<GrBuffer> fVertexBuffer;
diff --git a/gm/fwidth_squircle.cpp b/gm/fwidth_squircle.cpp
index ee34bc8..70bd885 100644
--- a/gm/fwidth_squircle.cpp
+++ b/gm/fwidth_squircle.cpp
@@ -225,10 +225,9 @@
             fProgramInfo = this->createProgramInfo(flushState);
         }
 
-        GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-        renderPass->bindPipeline(*fProgramInfo, SkRect::MakeIWH(kWidth, kHeight));
-        renderPass->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
-        renderPass->draw(4, 0);
+        flushState->bindPipeline(*fProgramInfo, SkRect::MakeIWH(kWidth, kHeight));
+        flushState->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
+        flushState->draw(4, 0);
 
     }
 
diff --git a/gm/samplelocations.cpp b/gm/samplelocations.cpp
index 141b9f2..413ff52 100644
--- a/gm/samplelocations.cpp
+++ b/gm/samplelocations.cpp
@@ -290,11 +290,9 @@
             fProgramInfo = this->createProgramInfo(flushState);
         }
 
-        GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-        renderPass->bindPipeline(*fProgramInfo, SkRect::MakeIWH(200, 200),
-                                 flushState->scissorRectIfEnabled());
-        renderPass->bindBuffers(nullptr, nullptr, nullptr);
-        renderPass->drawInstanced(200*200, 0, 4, 0);
+        flushState->bindPipelineAndScissorClip(*fProgramInfo, SkRect::MakeIWH(200, 200));
+        flushState->bindBuffers(nullptr, nullptr, nullptr);
+        flushState->drawInstanced(200*200, 0, 4, 0);
     }
 
     const GradType fGradType;
diff --git a/gm/tessellation.cpp b/gm/tessellation.cpp
index a2b025a..3ff9c68 100644
--- a/gm/tessellation.cpp
+++ b/gm/tessellation.cpp
@@ -332,10 +332,9 @@
                                   &pipeline, shader.get(), &fixedDynamicState, nullptr, 0,
                                   GrPrimitiveType::kPatches, tessellationPatchVertexCount);
 
-        GrOpsRenderPass* renderPass = state->opsRenderPass();
-        renderPass->bindPipeline(programInfo, SkRect::MakeIWH(kWidth, kHeight));
-        renderPass->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
-        renderPass->draw(tessellationPatchVertexCount, fBaseVertex);
+        state->bindPipeline(programInfo, SkRect::MakeIWH(kWidth, kHeight));
+        state->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
+        state->draw(tessellationPatchVertexCount, fBaseVertex);
     }
 
     const SkMatrix fViewMatrix;
diff --git a/src/gpu/GrAppliedClip.h b/src/gpu/GrAppliedClip.h
index 5983d31..594a627 100644
--- a/src/gpu/GrAppliedClip.h
+++ b/src/gpu/GrAppliedClip.h
@@ -21,14 +21,16 @@
  */
 class GrAppliedHardClip {
 public:
+    static const GrAppliedHardClip& Disabled() {
+        static GrAppliedHardClip kDisabled;
+        return kDisabled;
+    }
+
     GrAppliedHardClip() = default;
     GrAppliedHardClip(GrAppliedHardClip&& that) = default;
     GrAppliedHardClip(const GrAppliedHardClip&) = delete;
 
     const GrScissorState& scissorState() const { return fScissorState; }
-    const SkIRect* scissorRectIfEnabled() const {
-        return fScissorState.enabled() ? &fScissorState.rect() : nullptr;
-    }
     const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; }
     uint32_t stencilStackID() const { return fStencilStackID; }
     bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fStencilStackID; }
@@ -84,7 +86,6 @@
     GrAppliedClip(const GrAppliedClip&) = delete;
 
     const GrScissorState& scissorState() const { return fHardClip.scissorState(); }
-    const SkIRect* scissorRectIfEnabled() const { return fHardClip.scissorRectIfEnabled(); }
     const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); }
     uint32_t stencilStackID() const { return fHardClip.stencilStackID(); }
     bool hasStencilClip() const { return fHardClip.hasStencilClip(); }
@@ -98,6 +99,7 @@
         return std::move(fClipCoverageFPs[i]);
     }
 
+    const GrAppliedHardClip& hardClip() const { return fHardClip; }
     GrAppliedHardClip& hardClip() { return fHardClip; }
 
     void addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp) {
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index a67b379..50d2521 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -54,7 +54,7 @@
                                   fCurrDraw->fMeshCnt,
                                   fCurrDraw->fPrimitiveType);
 
-        this->opsRenderPass()->bindPipeline(programInfo, chainBounds);
+        this->bindPipeline(programInfo, chainBounds);
         this->opsRenderPass()->drawMeshes(programInfo, fCurrDraw->fMeshes, fCurrDraw->fMeshCnt);
         fTokenTracker->flushToken();
         ++fCurrDraw;
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index a59d98e..05a3339 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -14,6 +14,7 @@
 #include "src/gpu/GrAppliedClip.h"
 #include "src/gpu/GrBufferAllocPool.h"
 #include "src/gpu/GrDeferredUpload.h"
+#include "src/gpu/GrProgramInfo.h"
 #include "src/gpu/GrRenderTargetProxy.h"
 #include "src/gpu/GrSurfaceProxyView.h"
 #include "src/gpu/ops/GrMeshDrawOp.h"
@@ -135,8 +136,9 @@
     const GrSurfaceProxyView* outputView() const final { return this->drawOpArgs().outputView(); }
     GrRenderTargetProxy* proxy() const final { return this->drawOpArgs().proxy(); }
     const GrAppliedClip* appliedClip() const final { return this->drawOpArgs().appliedClip(); }
-    const SkIRect* scissorRectIfEnabled() const {
-        return this->appliedClip() ? this->appliedClip()->scissorRectIfEnabled() : nullptr;
+    const GrAppliedHardClip& appliedHardClip() const {
+        return (fOpArgs->appliedClip()) ?
+                fOpArgs->appliedClip()->hardClip() : GrAppliedHardClip::Disabled();
     }
     GrAppliedClip detachAppliedClip() final;
     const GrXferProcessor::DstProxyView& dstProxyView() const final {
@@ -155,6 +157,66 @@
     /** GrMeshDrawOp::Target override. */
     SkArenaAlloc* allocator() override { return &fArena; }
 
+    // This is a convenience method that binds the given pipeline, and then, if our applied clip has
+    // a scissor, sets the scissor rect from the applied clip.
+    void bindPipelineAndScissorClip(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
+        SkASSERT((programInfo.pipeline().isScissorTestEnabled()) ==
+                 (this->appliedClip() && this->appliedClip()->scissorState().enabled()));
+        this->bindPipeline(programInfo, drawBounds);
+        if (programInfo.pipeline().isScissorTestEnabled()) {
+            this->setScissorRect(this->appliedClip()->scissorState().rect());
+        }
+    }
+
+    // This is a convenience method for when the primitive processor has exactly one texture. It
+    // binds one texture for the primitive processor, and any others for FPs on the pipeline.
+    void bindTextures(const GrPrimitiveProcessor& primProc,
+                      const GrSurfaceProxy& singlePrimProcTexture, const GrPipeline& pipeline) {
+        SkASSERT(primProc.numTextureSamplers() == 1);
+        const GrSurfaceProxy* ptr = &singlePrimProcTexture;
+        this->bindTextures(primProc, &ptr, pipeline);
+    }
+
+    // Pass-through methods to GrOpsRenderPass.
+    void bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
+        fOpsRenderPass->bindPipeline(programInfo, drawBounds);
+    }
+    void setScissorRect(const SkIRect& scissorRect) {
+        fOpsRenderPass->setScissorRect(scissorRect);
+    }
+    void bindTextures(const GrPrimitiveProcessor& primProc,
+                      const GrSurfaceProxy* const primProcTextures[], const GrPipeline& pipeline) {
+        fOpsRenderPass->bindTextures(primProc, primProcTextures, pipeline);
+    }
+    void bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
+                     const GrBuffer* vertexBuffer,
+                     GrPrimitiveRestart primitiveRestart = GrPrimitiveRestart::kNo) {
+        fOpsRenderPass->bindBuffers(indexBuffer, instanceBuffer, vertexBuffer, primitiveRestart);
+    }
+    void draw(int vertexCount, int baseVertex) {
+        fOpsRenderPass->draw(vertexCount, baseVertex);
+    }
+    void drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue,
+                     int baseVertex) {
+        fOpsRenderPass->drawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue,
+                                    baseVertex);
+    }
+    void drawInstanced(int instanceCount, int baseInstance, int vertexCount, int baseVertex) {
+        fOpsRenderPass->drawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
+    }
+    void drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
+                              int baseVertex) {
+        fOpsRenderPass->drawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance,
+                                             baseVertex);
+    }
+    void drawIndexPattern(int patternIndexCount, int patternRepeatCount,
+                          int maxPatternRepetitionsInIndexBuffer, int patternVertexCount,
+                          int baseVertex) {
+        fOpsRenderPass->drawIndexPattern(patternIndexCount, patternRepeatCount,
+                                         maxPatternRepetitionsInIndexBuffer, patternVertexCount,
+                                         baseVertex);
+    }
+
 private:
     struct InlineUpload {
         InlineUpload(GrDeferredTextureUploadFn&& upload, GrDeferredUploadToken token)
diff --git a/src/gpu/GrOpsRenderPass.cpp b/src/gpu/GrOpsRenderPass.cpp
index 2c17828..2429381 100644
--- a/src/gpu/GrOpsRenderPass.cpp
+++ b/src/gpu/GrOpsRenderPass.cpp
@@ -42,8 +42,7 @@
     this->onExecuteDrawable(std::move(drawable));
 }
 
-void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds,
-                                   const SkIRect* optionalScissorRect) {
+void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
 #ifdef SK_DEBUG
     // Both the 'programInfo' and this renderPass have an origin. Since they come from the same
     // place (i.e., the target renderTargetProxy) they had best agree.
@@ -105,11 +104,6 @@
     fDrawPipelineStatus = DrawPipelineStatus::kOk;
     fXferBarrierType = programInfo.pipeline().xferBarrierType(fRenderTarget->asTexture(),
                                                               *this->gpu()->caps());
-
-    if (optionalScissorRect) {
-        SkASSERT(programInfo.pipeline().isScissorTestEnabled());
-        this->setScissorRect(*optionalScissorRect);
-    }
 }
 
 void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
@@ -149,14 +143,6 @@
     SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured);
 }
 
-void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
-                                   const GrSurfaceProxy& singlePrimProcTexture,
-                                   const GrPipeline& pipeline) {
-    SkASSERT(primProc.numTextureSamplers() == 1);
-    const GrSurfaceProxy* ptr = &singlePrimProcTexture;
-    this->bindTextures(primProc, &ptr, pipeline);
-}
-
 void GrOpsRenderPass::drawMeshes(const GrProgramInfo& programInfo, const GrSimpleMesh meshes[],
                                  int meshCount) {
     if (programInfo.hasFixedScissor()) {
diff --git a/src/gpu/GrOpsRenderPass.h b/src/gpu/GrOpsRenderPass.h
index b0dc9d6..dbbbe85 100644
--- a/src/gpu/GrOpsRenderPass.h
+++ b/src/gpu/GrOpsRenderPass.h
@@ -50,11 +50,9 @@
     // Signals the end of recording to the GrOpsRenderPass and that it can now be submitted.
     virtual void end() = 0;
 
-    // Updates the internal pipeline state for drawing with the provided GrProgramInfo. If an
-    // optional scissor rect is provided, then this method calls setScissor for convenience after
-    // binding the pipeline. Enters an internal "bad" state if the pipeline could not be set.
-    void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds,
-                      const SkIRect* optionalScissorRect = nullptr);
+    // Updates the internal pipeline state for drawing with the provided GrProgramInfo. Enters an
+    // internal "bad" state if the pipeline could not be set.
+    void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds);
 
     // The scissor rect is always dynamic state and therefore not stored on GrPipeline. If scissor
     // test is enabled on the current pipeline, then the client must call setScissorRect() before
@@ -74,11 +72,6 @@
     void bindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy* const primProcTextures[],
                       const GrPipeline&);
 
-    // This is a convenience overload for when the primitive processor has exactly one texture. It
-    // binds one texture for the primitive processor, and any others for FPs on the pipeline.
-    void bindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy& singlePrimProcTexture,
-                      const GrPipeline&);
-
     void bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
                      const GrBuffer* vertexBuffer, GrPrimitiveRestart = GrPrimitiveRestart::kNo);
 
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index 0db6480..1438ee8 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -197,16 +197,10 @@
 
 void GrCCCoverageProcessor::bindPipeline(GrOpFlushState* flushState, const GrPipeline& pipeline,
                                          const SkRect& drawBounds) const {
-    GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-
-    GrPrimitiveType primitiveType = this->primType();
-
     GrProgramInfo programInfo(flushState->proxy()->numSamples(),
                               flushState->proxy()->numStencilSamples(),
                               flushState->proxy()->backendFormat(),
                               flushState->outputView()->origin(), &pipeline, this, nullptr, nullptr,
-                              0, primitiveType);
-
-
-    renderPass->bindPipeline(programInfo, drawBounds);
+                              0, this->primType());
+    flushState->bindPipeline(programInfo, drawBounds);
 }
diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp
index 7444efe..e313cf1 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -140,12 +140,11 @@
                               rtProxy->backendFormat(), flushState->outputView()->origin(),
                               &pipeline, this, nullptr, nullptr, 0, primitiveType);
 
-    GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-    renderPass->bindPipeline(programInfo, bounds, flushState->scissorRectIfEnabled());
-    renderPass->bindTextures(*this, atlasProxy, pipeline);
-    renderPass->bindBuffers(resources.indexBuffer(), resources.instanceBuffer(),
+    flushState->bindPipelineAndScissorClip(programInfo, bounds);
+    flushState->bindTextures(*this, atlasProxy, pipeline);
+    flushState->bindBuffers(resources.indexBuffer(), resources.instanceBuffer(),
                             resources.vertexBuffer(), enablePrimitiveRestart);
-    renderPass->drawIndexedInstanced(numIndicesPerInstance, 0, endInstance - baseInstance,
+    flushState->drawIndexedInstanced(numIndicesPerInstance, 0, endInstance - baseInstance,
                                      baseInstance, 0);
 }
 
diff --git a/src/gpu/ccpr/GrCCStroker.cpp b/src/gpu/ccpr/GrCCStroker.cpp
index d0541f0..2942e20 100644
--- a/src/gpu/ccpr/GrCCStroker.cpp
+++ b/src/gpu/ccpr/GrCCStroker.cpp
@@ -741,9 +741,8 @@
                               flushState->outputView()->origin(), &pipeline, &processor, nullptr,
                               nullptr, 0, GrPrimitiveType::kTriangleStrip);
 
-    GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-    renderPass->bindPipeline(programInfo, SkRect::Make(drawBounds));
-    renderPass->bindBuffers(nullptr, fInstanceBuffer.get(), nullptr);
+    flushState->bindPipeline(programInfo, SkRect::Make(drawBounds));
+    flushState->bindBuffers(nullptr, fInstanceBuffer.get(), nullptr);
 
     // Linear strokes draw a quad. Cubic strokes emit a strip with normals at "numSegments"
     // evenly-spaced points along the curve, plus one more for the final endpoint, plus two more for
@@ -756,8 +755,8 @@
     int endIdx = batch.fNonScissorEndInstances->fStrokes[numSegmentsLog2];
     SkASSERT(endIdx >= startIdx);
     if (int instanceCount = endIdx - startIdx) {
-        renderPass->setScissorRect(drawBounds);
-        renderPass->drawInstanced(instanceCount, baseInstance + startIdx, numStripVertices, 0);
+        flushState->setScissorRect(drawBounds);
+        flushState->drawInstanced(instanceCount, baseInstance + startIdx, numStripVertices, 0);
     }
 
     // Draw scissored strokes.
@@ -768,8 +767,8 @@
         endIdx = subBatch.fEndInstances->fStrokes[numSegmentsLog2];
         SkASSERT(endIdx >= startIdx);
         if (int instanceCount = endIdx - startIdx) {
-            renderPass->setScissorRect(subBatch.fScissor);
-            renderPass->drawInstanced(instanceCount, baseInstance + startIdx, numStripVertices, 0);
+            flushState->setScissorRect(subBatch.fScissor);
+            flushState->drawInstanced(instanceCount, baseInstance + startIdx, numStripVertices, 0);
             startIdx = endIdx;
         }
     }
@@ -781,9 +780,8 @@
                                          const Batch& batch, const InstanceTallies* startIndices[2],
                                          int startScissorSubBatch,
                                          const SkIRect& drawBounds) const {
-    GrOpsRenderPass* renderPass = flushState->opsRenderPass();
     processor.bindPipeline(flushState, pipeline, SkRect::Make(drawBounds));
-    processor.bindBuffers(renderPass, fInstanceBuffer.get());
+    processor.bindBuffers(flushState->opsRenderPass(), fInstanceBuffer.get());
 
     // Append non-scissored meshes.
     int baseInstance = fBaseInstances[(int)GrScissorTest::kDisabled].*InstanceType;
@@ -791,8 +789,9 @@
     int endIdx = batch.fNonScissorEndInstances->*InstanceType;
     SkASSERT(endIdx >= startIdx);
     if (int instanceCount = endIdx - startIdx) {
-        renderPass->setScissorRect(drawBounds);
-        processor.drawInstances(renderPass, instanceCount, baseInstance + startIdx);
+        flushState->setScissorRect(drawBounds);
+        processor.drawInstances(flushState->opsRenderPass(), instanceCount,
+                                baseInstance + startIdx);
     }
 
     // Append scissored meshes.
@@ -803,8 +802,9 @@
         endIdx = subBatch.fEndInstances->*InstanceType;
         SkASSERT(endIdx >= startIdx);
         if (int instanceCount = endIdx - startIdx) {
-            renderPass->setScissorRect(subBatch.fScissor);
-            processor.drawInstances(renderPass, instanceCount, baseInstance + startIdx);
+            flushState->setScissorRect(subBatch.fScissor);
+            processor.drawInstances(flushState->opsRenderPass(), instanceCount,
+                                    baseInstance + startIdx);
             startIdx = endIdx;
         }
     }
diff --git a/src/gpu/ccpr/GrStencilAtlasOp.cpp b/src/gpu/ccpr/GrStencilAtlasOp.cpp
index 21f882b..281be57 100644
--- a/src/gpu/ccpr/GrStencilAtlasOp.cpp
+++ b/src/gpu/ccpr/GrStencilAtlasOp.cpp
@@ -154,10 +154,9 @@
                               flushState->outputView()->origin(), &resolvePipeline, &primProc,
                               nullptr, nullptr, 0, GrPrimitiveType::kTriangleStrip);
 
-    flushState->opsRenderPass()->bindPipeline(programInfo, SkRect::Make(drawBoundsRect));
-    flushState->opsRenderPass()->setScissorRect(drawBoundsRect);
-    flushState->opsRenderPass()->bindBuffers(nullptr, fResources->stencilResolveBuffer(), nullptr);
-    flushState->opsRenderPass()->drawInstanced(
-            fEndStencilResolveInstance - fBaseStencilResolveInstance, fBaseStencilResolveInstance,
-            4, 0);
+    flushState->bindPipeline(programInfo, SkRect::Make(drawBoundsRect));
+    flushState->setScissorRect(drawBoundsRect);
+    flushState->bindBuffers(nullptr, fResources->stencilResolveBuffer(), nullptr);
+    flushState->drawInstanced(fEndStencilResolveInstance - fBaseStencilResolveInstance,
+                              fBaseStencilResolveInstance, 4, 0);
 }
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index d1feaca..00f02ab 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -852,7 +852,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         for (int i = 0; i < fDraws.count(); ++i) {
             flushState->opsRenderPass()->drawMeshes(*fProgramInfo,
                                                     fDraws[i].fMeshes, fDraws[i].fMeshCount);
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index adeefce..efb5872 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -327,7 +327,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         for (int i = 0; i < fMeshes.count(); ++i) {
             flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMeshes[i], 1);
         }
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index f43af78..022cdc6 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -666,7 +666,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 60606eb..2080e47 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -474,7 +474,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         for (int i = 0; i < fMeshes.count(); ++i) {
             flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMeshes[i], 1);
         }
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index 5ceabe0..a8dd3b9 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -246,7 +246,7 @@
         return;
     }
 
-    flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+    flushState->bindPipeline(*fProgramInfo, chainBounds);
     flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
 }
 
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 5bad9f8..ce038e4 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -357,7 +357,7 @@
         return;
     }
 
-    flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+    flushState->bindPipeline(*fProgramInfo, chainBounds);
     flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
 }
 
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index 573aa59..0ca0358 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -900,11 +900,10 @@
         fProgramInfo = this->createProgramInfo(flushState);
     }
 
-    GrOpsRenderPass* renderPass = flushState->opsRenderPass();
-    renderPass->bindPipeline(*fProgramInfo, this->bounds(), flushState->scissorRectIfEnabled());
-    renderPass->bindTextures(fProgramInfo->primProc(), nullptr, fProgramInfo->pipeline());
-    renderPass->bindBuffers(fIndexBuffer.get(), fInstanceBuffer.get(), fVertexBuffer.get());
-    renderPass->drawIndexedInstanced(fIndexCount, 0, fInstanceCount, fBaseInstance, 0);
+    flushState->bindPipelineAndScissorClip(*fProgramInfo, this->bounds());
+    flushState->bindTextures(fProgramInfo->primProc(), nullptr, fProgramInfo->pipeline());
+    flushState->bindBuffers(fIndexBuffer.get(), fInstanceBuffer.get(), fVertexBuffer.get());
+    flushState->drawIndexedInstanced(fIndexCount, 0, fInstanceCount, fBaseInstance, 0);
 }
 
 // Will the given corner look good if we use HW derivatives?
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 255bd0d..f6b95a8 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -337,7 +337,7 @@
             this->createProgramInfo(flushState);
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 0e2972a..45db504 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -325,7 +325,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index a43d222..7f8c28d 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1428,7 +1428,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
@@ -1750,7 +1750,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
@@ -2037,7 +2037,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
@@ -2302,7 +2302,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
@@ -2761,7 +2761,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
@@ -3074,7 +3074,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 7af7579..e5e7241 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -160,7 +160,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index e099e8e..49174a0 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -628,7 +628,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/ops/GrStrokeRectOp.cpp b/src/gpu/ops/GrStrokeRectOp.cpp
index c9757bb..c221baa 100644
--- a/src/gpu/ops/GrStrokeRectOp.cpp
+++ b/src/gpu/ops/GrStrokeRectOp.cpp
@@ -250,7 +250,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
@@ -592,7 +592,7 @@
         return;
     }
 
-    flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+    flushState->bindPipeline(*fProgramInfo, chainBounds);
     flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
 }
 
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index c84910e..43d9381 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -394,7 +394,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
index e08da15..efc9ec4 100644
--- a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
+++ b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
@@ -156,9 +156,6 @@
 void GrDrawAtlasPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
     SkASSERT(fAtlasProxy->isInstantiated());
 
-    GrAppliedClip clip = state->detachAppliedClip();
-    const SkIRect* scissorRectIfEnabled = clip.scissorRectIfEnabled();
-
     GrPipeline::InitArgs initArgs;
     if (fEnableHWAA) {
         initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
@@ -166,7 +163,7 @@
     initArgs.fCaps = &state->caps();
     initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
     initArgs.fOutputSwizzle = state->drawOpArgs().outputSwizzle();
-    GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip));
+    GrPipeline pipeline(initArgs, std::move(fProcessors), state->detachAppliedClip());
 
     GrSwizzle swizzle = state->caps().getReadSwizzle(fAtlasProxy->backendFormat(),
                                                      GrColorType::kAlpha_8);
@@ -179,9 +176,8 @@
                               &pipeline, &shader, nullptr, nullptr, 0,
                               GrPrimitiveType::kTriangleStrip);
 
-    GrOpsRenderPass* renderPass = state->opsRenderPass();
-    renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
-    renderPass->bindTextures(shader, *fAtlasProxy, pipeline);
-    renderPass->bindBuffers(nullptr, fInstanceBuffer.get(), nullptr);
-    renderPass->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
+    state->bindPipelineAndScissorClip(programInfo, this->bounds());
+    state->bindTextures(shader, *fAtlasProxy, pipeline);
+    state->bindBuffers(nullptr, fInstanceBuffer.get(), nullptr);
+    state->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
 }
diff --git a/src/gpu/tessellate/GrTessellatePathOp.cpp b/src/gpu/tessellate/GrTessellatePathOp.cpp
index 43fa303..7e48408 100644
--- a/src/gpu/tessellate/GrTessellatePathOp.cpp
+++ b/src/gpu/tessellate/GrTessellatePathOp.cpp
@@ -90,14 +90,13 @@
 }
 
 void GrTessellatePathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
-    GrAppliedClip clip = state->detachAppliedClip();
-    this->drawStencilPass(state, clip.hardClip());
+    this->drawStencilPass(state);
     if (!(Flags::kStencilOnly & fFlags)) {
-        this->drawCoverPass(state, std::move(clip));
+        this->drawCoverPass(state);
     }
 }
 
-void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state, const GrAppliedHardClip& hardClip) {
+void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state) {
     // Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill.
     constexpr static GrUserStencilSettings kIncrDecrStencil(
         GrUserStencilSettings::StaticInitSeparate<
@@ -130,27 +129,25 @@
     initArgs.fUserStencil = (SkPathFillType::kWinding == fPath.getFillType()) ?
             &kIncrDecrStencil : &kInvertStencil;
     initArgs.fCaps = &state->caps();
-
-    GrPipeline pipeline(initArgs, GrDisableColorXPFactory::MakeXferProcessor(), hardClip);
-
-    GrOpsRenderPass* renderPass = state->opsRenderPass();
+    GrPipeline pipeline(initArgs, GrDisableColorXPFactory::MakeXferProcessor(),
+                        state->appliedHardClip());
 
     if (fStencilPathShader) {
         SkASSERT(fPathVertexBuffer);
         GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, fStencilPathShader);
-        renderPass->bindPipeline(programInfo, this->bounds(), hardClip.scissorRectIfEnabled());
-        renderPass->bindBuffers(nullptr, nullptr, fPathVertexBuffer.get());
-        renderPass->draw(fPathVertexCount, fBasePathVertex);
+        state->bindPipelineAndScissorClip(programInfo, this->bounds());
+        state->bindBuffers(nullptr, nullptr, fPathVertexBuffer.get());
+        state->draw(fPathVertexCount, fBasePathVertex);
     }
 
     if (fCubicInstanceBuffer) {
         // Here we treat the cubic instance buffer as tessellation patches to stencil the curves.
         GrStencilCubicShader shader(fViewMatrix);
         GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, &shader);
-        renderPass->bindPipeline(programInfo, this->bounds(), hardClip.scissorRectIfEnabled());
+        state->bindPipelineAndScissorClip(programInfo, this->bounds());
         // Bind instancedBuff as vertex.
-        renderPass->bindBuffers(nullptr, nullptr, fCubicInstanceBuffer.get());
-        renderPass->draw(fCubicInstanceCount * 4, fBaseCubicInstance * 4);
+        state->bindBuffers(nullptr, nullptr, fCubicInstanceBuffer.get());
+        state->draw(fCubicInstanceCount * 4, fBaseCubicInstance * 4);
     }
 
     // http://skbug.com/9739
@@ -159,10 +156,7 @@
     }
 }
 
-void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state, GrAppliedClip&& clip) {
-    GrOpsRenderPass* renderPass = state->opsRenderPass();
-    const SkIRect* scissorRectIfEnabled = clip.scissorRectIfEnabled();
-
+void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) {
     // Allows non-zero stencil values to pass and write a color, and resets the stencil value back
     // to zero; discards immediately on stencil values of zero.
     // NOTE: It's ok to not check the clip here because the previous stencil pass only wrote to
@@ -191,7 +185,7 @@
     initArgs.fCaps = &state->caps();
     initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
     initArgs.fOutputSwizzle = state->drawOpArgs().outputSwizzle();
-    GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip));
+    GrPipeline pipeline(initArgs, std::move(fProcessors), state->detachAppliedClip());
 
     if (fFillPathShader) {
         SkASSERT(fPathVertexBuffer);
@@ -237,10 +231,10 @@
             pipeline.setUserStencil(&kFillOrInvertStencil);
         }
         GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, fFillPathShader);
-        renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
-        renderPass->bindTextures(*fFillPathShader, nullptr, pipeline);
-        renderPass->bindBuffers(nullptr, nullptr, fPathVertexBuffer.get());
-        renderPass->draw(fPathVertexCount, fBasePathVertex);
+        state->bindPipelineAndScissorClip(programInfo, this->bounds());
+        state->bindTextures(*fFillPathShader, nullptr, pipeline);
+        state->bindBuffers(nullptr, nullptr, fPathVertexBuffer.get());
+        state->draw(fPathVertexCount, fBasePathVertex);
 
         if (fCubicInstanceBuffer) {
             // At this point, every pixel is filled in except the ones touched by curves. Issue a
@@ -249,19 +243,19 @@
             pipeline.setUserStencil(&kTestAndResetStencil);
             GrFillCubicHullShader shader(fViewMatrix, fColor);
             GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, &shader);
-            renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
-            renderPass->bindTextures(shader, nullptr, pipeline);
-            renderPass->bindBuffers(nullptr, fCubicInstanceBuffer.get(), nullptr);
-            renderPass->drawInstanced(fCubicInstanceCount, fBaseCubicInstance, 4, 0);
+            state->bindPipelineAndScissorClip(programInfo, this->bounds());
+            state->bindTextures(shader, nullptr, pipeline);
+            state->bindBuffers(nullptr, fCubicInstanceBuffer.get(), nullptr);
+            state->drawInstanced(fCubicInstanceCount, fBaseCubicInstance, 4, 0);
         }
     } else {
         // There is not a fill shader for the path. Just draw a bounding box.
         pipeline.setUserStencil(&kTestAndResetStencil);
         GrFillBoundingBoxShader shader(fViewMatrix, fColor, fPath.getBounds());
         GrPathShader::ProgramInfo programInfo(state->outputView(), &pipeline, &shader);
-        renderPass->bindPipeline(programInfo, this->bounds(), scissorRectIfEnabled);
-        renderPass->bindTextures(shader, nullptr, pipeline);
-        renderPass->bindBuffers(nullptr, nullptr, nullptr);
-        renderPass->draw(4, 0);
+        state->bindPipelineAndScissorClip(programInfo, this->bounds());
+        state->bindTextures(shader, nullptr, pipeline);
+        state->bindBuffers(nullptr, nullptr, nullptr);
+        state->draw(4, 0);
     }
 }
diff --git a/src/gpu/tessellate/GrTessellatePathOp.h b/src/gpu/tessellate/GrTessellatePathOp.h
index f2f678c..5f767fa 100644
--- a/src/gpu/tessellate/GrTessellatePathOp.h
+++ b/src/gpu/tessellate/GrTessellatePathOp.h
@@ -56,8 +56,8 @@
     void onPrepare(GrOpFlushState* state) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
-    void drawStencilPass(GrOpFlushState*, const GrAppliedHardClip&);
-    void drawCoverPass(GrOpFlushState*, GrAppliedClip&&);
+    void drawStencilPass(GrOpFlushState*);
+    void drawCoverPass(GrOpFlushState*);
 
     const Flags fFlags;
     const SkMatrix fViewMatrix;
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index 4c7ffd6..6783b64 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -168,8 +168,7 @@
                                   nullptr,
                                   &dynamicState, 0, GrPrimitiveType::kTriangleStrip);
 
-        flushState->opsRenderPass()->bindPipeline(programInfo,
-                                                  SkRect::MakeIWH(kScreenSize, kScreenSize));
+        flushState->bindPipeline(programInfo, SkRect::MakeIWH(kScreenSize, kScreenSize));
         flushState->opsRenderPass()->drawMeshes(programInfo, meshes.begin(), 4);
     }
 
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index 9a3ef71..0465177 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -191,7 +191,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }
 
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp
index 476d19a..cbfc961 100644
--- a/tests/PrimitiveProcessorTest.cpp
+++ b/tests/PrimitiveProcessorTest.cpp
@@ -153,7 +153,7 @@
             return;
         }
 
-        flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
+        flushState->bindPipeline(*fProgramInfo, chainBounds);
         flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, 1);
     }