Add support for plumbing GrDstSampleType through Ops and Pipeline creation.

This CL adds a new type GrDstSampleType to say how we will sample the dst.

We add tracking of the GrDstSampleType in the recording of GrOps and
then during execution passing the information along to the GrPipeline.

In general the tracking of GrDstSampleType is a global state of a GrOpsTask
so it is kept separate fro the DstProxyView which is more specific to a
single Op on the GrOpsTask.

Bug: skia:10409
Change-Id: Ie843c31f2e48a887daf96cee99ed159b196cb545
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315645
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/bench/TessellateBench.cpp b/bench/TessellateBench.cpp
index b42a50b..b5a6b00 100644
--- a/bench/TessellateBench.cpp
+++ b/bench/TessellateBench.cpp
@@ -92,6 +92,7 @@
     UNIMPL(const GrAppliedClip* appliedClip() const)
     UNIMPL(GrAppliedClip detachAppliedClip())
     UNIMPL(const GrXferProcessor::DstProxyView& dstProxyView() const)
+    UNIMPL(GrXferBarrierFlags renderPassBarriers() const)
     UNIMPL(GrStrikeCache* strikeCache() const)
     UNIMPL(GrAtlasManager* atlasManager() const)
     UNIMPL(SkTArray<GrSurfaceProxy*, true>* sampledProxyArray())
diff --git a/bench/VertexColorSpaceBench.cpp b/bench/VertexColorSpaceBench.cpp
index 024aae0..8ae0719 100644
--- a/bench/VertexColorSpaceBench.cpp
+++ b/bench/VertexColorSpaceBench.cpp
@@ -174,7 +174,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp = GP::Make(arena, fMode, fColorSpaceXform);
 
         fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps,
@@ -185,6 +186,7 @@
                                                                    gp,
                                                                    GrProcessorSet::MakeEmptySet(),
                                                                    GrPrimitiveType::kTriangleStrip,
+                                                                   renderPassXferBarriers,
                                                                    GrPipeline::InputFlags::kNone);
     }
 
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp
index 4f1baa0..55d5ca0 100644
--- a/gm/beziereffects.cpp
+++ b/gm/beziereffects.cpp
@@ -93,7 +93,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         auto gp = this->makeGP(*caps, arena);
         if (!gp) {
             return;
@@ -106,6 +107,7 @@
                                                                    dstProxyView, gp,
                                                                    std::move(fProcessorSet),
                                                                    GrPrimitiveType::kTriangles,
+                                                                   renderPassXferBarriers,
                                                                    flags);
     }
 
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index 0b1892d..e7a3629 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -162,13 +162,15 @@
                                      SkArenaAlloc* arena,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip&& appliedClip,
-                                     const GrXferProcessor::DstProxyView& dstProxyView) const {
+                                     const GrXferProcessor::DstProxyView& dstProxyView,
+                                     GrXferBarrierFlags renderPassXferBarriers) const {
         GrGeometryProcessor* geomProc = ClockwiseTestProcessor::Make(arena, fReadSkFragCoord);
 
         return sk_gpu_test::CreateProgramInfo(caps, arena, writeView,
                                               std::move(appliedClip), dstProxyView,
                                               geomProc, SkBlendMode::kPlus,
-                                              GrPrimitiveType::kTriangleStrip);
+                                              GrPrimitiveType::kTriangleStrip,
+                                              renderPassXferBarriers);
     }
 
     GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
@@ -176,20 +178,23 @@
                                        flushState->allocator(),
                                        flushState->writeView(),
                                        flushState->detachAppliedClip(),
-                                       flushState->dstProxyView());
+                                       flushState->dstProxyView(),
+                                       flushState->renderPassBarriers());
     }
 
     void onPrePrepare(GrRecordingContext* context,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip* clip,
-                      const GrXferProcessor::DstProxyView& dstProxyView) final {
+                      const GrXferProcessor::DstProxyView& dstProxyView,
+                      GrXferBarrierFlags renderPassXferBarriers) final {
         SkArenaAlloc* arena = context->priv().recordTimeAllocator();
 
         // This is equivalent to a GrOpFlushState::detachAppliedClip
         GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
 
         fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
-                                               std::move(appliedClip), dstProxyView);
+                                               std::move(appliedClip), dstProxyView,
+                                               renderPassXferBarriers);
 
         context->priv().recordProgramInfo(fProgramInfo);
     }
diff --git a/gm/fwidth_squircle.cpp b/gm/fwidth_squircle.cpp
index 32b699e..bd2be0f 100644
--- a/gm/fwidth_squircle.cpp
+++ b/gm/fwidth_squircle.cpp
@@ -172,13 +172,15 @@
                                      SkArenaAlloc* arena,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip&& appliedClip,
-                                     const GrXferProcessor::DstProxyView& dstProxyView) const {
+                                     const GrXferProcessor::DstProxyView& dstProxyView,
+                                     GrXferBarrierFlags renderPassXferBarriers) const {
         GrGeometryProcessor* geomProc = FwidthSquircleTestProcessor::Make(arena, fViewMatrix);
 
         return sk_gpu_test::CreateProgramInfo(caps, arena, writeView,
                                               std::move(appliedClip), dstProxyView,
                                               geomProc, SkBlendMode::kSrcOver,
-                                              GrPrimitiveType::kTriangleStrip);
+                                              GrPrimitiveType::kTriangleStrip,
+                                              renderPassXferBarriers);
     }
 
     GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
@@ -186,20 +188,23 @@
                                        flushState->allocator(),
                                        flushState->writeView(),
                                        flushState->detachAppliedClip(),
-                                       flushState->dstProxyView());
+                                       flushState->dstProxyView(),
+                                       flushState->renderPassBarriers());
     }
 
     void onPrePrepare(GrRecordingContext* context,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip* clip,
-                      const GrXferProcessor::DstProxyView& dstProxyView) final {
+                      const GrXferProcessor::DstProxyView& dstProxyView,
+                      GrXferBarrierFlags renderPassXferBarriers) final {
         SkArenaAlloc* arena = context->priv().recordTimeAllocator();
 
         // This is equivalent to a GrOpFlushState::detachAppliedClip
         GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
 
         fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
-                                               std::move(appliedClip), dstProxyView);
+                                               std::move(appliedClip), dstProxyView,
+                                               renderPassXferBarriers);
 
         context->priv().recordProgramInfo(fProgramInfo);
     }
diff --git a/gm/samplelocations.cpp b/gm/samplelocations.cpp
index 0ceda73..5c81980 100644
--- a/gm/samplelocations.cpp
+++ b/gm/samplelocations.cpp
@@ -244,7 +244,8 @@
                                      SkArenaAlloc* arena,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip&& appliedClip,
-                                     const GrXferProcessor::DstProxyView& dstProxyView) const {
+                                     const GrXferProcessor::DstProxyView& dstProxyView,
+                                     GrXferBarrierFlags renderPassXferBarriers) const {
         GrGeometryProcessor* geomProc = SampleLocationsTestProcessor::Make(arena, fGradType);
 
         GrPipeline::InputFlags flags = GrPipeline::InputFlags::kHWAntialias;
@@ -253,6 +254,7 @@
                                               std::move(appliedClip), dstProxyView,
                                               geomProc, SkBlendMode::kSrcOver,
                                               GrPrimitiveType::kTriangleStrip,
+                                              renderPassXferBarriers,
                                               flags, &gStencilWrite);
     }
 
@@ -261,13 +263,15 @@
                                        flushState->allocator(),
                                        flushState->writeView(),
                                        flushState->detachAppliedClip(),
-                                       flushState->dstProxyView());
+                                       flushState->dstProxyView(),
+                                       flushState->renderPassBarriers());
     }
 
     void onPrePrepare(GrRecordingContext* context,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip* clip,
-                      const GrXferProcessor::DstProxyView& dstProxyView) final {
+                      const GrXferProcessor::DstProxyView& dstProxyView,
+                      GrXferBarrierFlags renderPassXferBarriers) final {
         // We're going to create the GrProgramInfo (and the GrPipeline and geometry processor
         // it relies on) in the DDL-record-time arena.
         SkArenaAlloc* arena = context->priv().recordTimeAllocator();
@@ -276,7 +280,8 @@
         GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
 
         fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
-                                               std::move(appliedClip), dstProxyView);
+                                               std::move(appliedClip), dstProxyView,
+                                               renderPassXferBarriers);
 
         context->priv().recordProgramInfo(fProgramInfo);
     }
diff --git a/gm/tessellation.cpp b/gm/tessellation.cpp
index 40709ec..34c58cc 100644
--- a/gm/tessellation.cpp
+++ b/gm/tessellation.cpp
@@ -313,7 +313,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
 
     void onPrepare(GrOpFlushState* flushState) override {
         if (fTriPositions) {
@@ -345,7 +346,7 @@
         GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
                                   state->proxy()->backendFormat(), state->writeView()->origin(),
                                   &pipeline, shader.get(), GrPrimitiveType::kPatches,
-                                  tessellationPatchVertexCount);
+                                  tessellationPatchVertexCount, state->renderPassBarriers());
 
         state->bindPipeline(programInfo, SkRect::MakeIWH(kWidth, kHeight));
         state->bindBuffers(nullptr, nullptr, std::move(fVertexBuffer));
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 88156a1..47f5dbe 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -1218,6 +1218,41 @@
     Context fReleaseCtx;
 };
 
+
+enum class GrDstSampleType {
+    kNone, // The dst value will not be sampled in the shader
+    kAsTextureCopy, // The dst value will be sampled from a copy of the dst
+    // The types below require a texture barrier
+    kAsSelfTexture, // The dst value is sampled directly from the dst itself as a texture.
+    kAsInputAttachment, // The dst value is sampled directly from the dst as an input attachment.
+};
+
+// Returns true if the sampling of the dst color in the shader is done by reading the dst directly.
+// Anything that directly reads the dst will need a barrier between draws.
+static constexpr bool GrDstSampleTypeDirectlySamplesDst(GrDstSampleType type) {
+    switch (type) {
+        case GrDstSampleType::kAsSelfTexture:  // fall through
+        case GrDstSampleType::kAsInputAttachment:
+            return true;
+        case GrDstSampleType::kNone:  // fall through
+        case GrDstSampleType::kAsTextureCopy:
+            return false;
+    }
+    SkUNREACHABLE;
+}
+
+static constexpr bool GrDstSampleTypeUsesTexture(GrDstSampleType type) {
+    switch (type) {
+        case GrDstSampleType::kAsSelfTexture:  // fall through
+        case GrDstSampleType::kAsTextureCopy:
+            return true;
+        case GrDstSampleType::kNone:  // fall through
+        case GrDstSampleType::kAsInputAttachment:
+            return false;
+    }
+    SkUNREACHABLE;
+}
+
 #if defined(SK_DEBUG) || GR_TEST_UTILS || defined(SK_ENABLE_DUMP_GPU)
 static constexpr const char* GrBackendApiToStr(GrBackendApi api) {
     switch (api) {
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index b9885ef..c4f17ae 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -105,7 +105,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrepare(GrOpFlushState*) override {}
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 10d34ff..c6fb6cb 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -5,11 +5,13 @@
  * found in the LICENSE file.
  */
 
+#include "src/gpu/GrCaps.h"
+
 #include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/GrContextOptions.h"
 #include "include/private/GrTypesPriv.h"
 #include "src/gpu/GrBackendUtils.h"
-#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrRenderTargetProxy.h"
 #include "src/gpu/GrSurface.h"
 #include "src/gpu/GrSurfaceProxy.h"
 #include "src/gpu/GrWindowRectangles.h"
@@ -433,3 +435,11 @@
     return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone;
 }
 
+GrDstSampleType GrCaps::getDstSampleTypeForProxy(const GrRenderTargetProxy* rt) const {
+    SkASSERT(rt);
+    if (this->textureBarrierSupport() && !rt->requiresManualMSAAResolve()) {
+        return this->onGetDstSampleTypeForProxy(rt);
+    }
+    return GrDstSampleType::kAsTextureCopy;
+}
+
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index a4801f3..2a8d2b4 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -383,6 +383,9 @@
     bool driverDisableCCPR() const { return fDriverDisableCCPR; }
     bool driverDisableMSAACCPR() const { return fDriverDisableMSAACCPR; }
 
+    // Returns how to sample the dst values for the passed in GrRenderTargetProxy.
+    GrDstSampleType getDstSampleTypeForProxy(const GrRenderTargetProxy*) const;
+
     /**
      * This is used to try to ensure a successful copy a dst in order to perform shader-based
      * blending.
@@ -570,6 +573,9 @@
 
     virtual GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const = 0;
 
+    virtual GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const {
+        return GrDstSampleType::kAsTextureCopy;
+    }
 
     bool fSuppressPrints : 1;
     bool fWireframeMode  : 1;
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index ce4ce4b..89434d4 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -52,7 +52,9 @@
                                   this->writeView()->origin(),
                                   pipeline,
                                   fCurrDraw->fGeometryProcessor,
-                                  fCurrDraw->fPrimitiveType);
+                                  fCurrDraw->fPrimitiveType,
+                                  0,
+                                  this->renderPassBarriers());
 
         this->bindPipelineAndScissorClip(programInfo, chainBounds);
         this->bindTextures(programInfo.primProc(), fCurrDraw->fPrimProcProxies,
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 2dc4fb1..f833ef2 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -59,12 +59,14 @@
     struct OpArgs {
         // TODO: why does OpArgs have the op we're going to pass it to as a member? Remove it.
         explicit OpArgs(GrOp* op, GrSurfaceProxyView* surfaceView, GrAppliedClip* appliedClip,
-                        const GrXferProcessor::DstProxyView& dstProxyView)
+                        const GrXferProcessor::DstProxyView& dstProxyView,
+                        GrXferBarrierFlags renderPassXferBarriers)
                 : fOp(op)
                 , fSurfaceView(surfaceView)
                 , fRenderTargetProxy(surfaceView->asRenderTargetProxy())
                 , fAppliedClip(appliedClip)
-                , fDstProxyView(dstProxyView) {
+                , fDstProxyView(dstProxyView)
+                , fRenderPassXferBarriers(renderPassXferBarriers) {
             SkASSERT(surfaceView->asRenderTargetProxy());
         }
 
@@ -77,6 +79,7 @@
         GrAppliedClip* appliedClip() { return fAppliedClip; }
         const GrAppliedClip* appliedClip() const { return fAppliedClip; }
         const GrXferProcessor::DstProxyView& dstProxyView() const { return fDstProxyView; }
+        GrXferBarrierFlags renderPassBarriers() const { return fRenderPassXferBarriers; }
 
 #ifdef SK_DEBUG
         void validate() const {
@@ -91,6 +94,7 @@
         GrRenderTargetProxy*          fRenderTargetProxy;
         GrAppliedClip*                fAppliedClip;
         GrXferProcessor::DstProxyView fDstProxyView;   // TODO: do we still need the dst proxy here?
+        GrXferBarrierFlags            fRenderPassXferBarriers;
     };
 
     void setOpArgs(OpArgs* opArgs) { fOpArgs = opArgs; }
@@ -151,6 +155,11 @@
     const GrXferProcessor::DstProxyView& dstProxyView() const final {
         return this->drawOpArgs().dstProxyView();
     }
+
+    GrXferBarrierFlags renderPassBarriers() const final {
+        return this->drawOpArgs().renderPassBarriers();
+    }
+
     GrDeferredUploadTarget* deferredUploadTarget() final { return this; }
     const GrCaps& caps() const final;
     GrResourceProvider* resourceProvider() const final { return fResourceProvider; }
diff --git a/src/gpu/GrOpsRenderPass.cpp b/src/gpu/GrOpsRenderPass.cpp
index 68ea089..cd329de 100644
--- a/src/gpu/GrOpsRenderPass.cpp
+++ b/src/gpu/GrOpsRenderPass.cpp
@@ -129,8 +129,7 @@
 #endif
 
     fDrawPipelineStatus = DrawPipelineStatus::kOk;
-    fXferBarrierType = programInfo.pipeline().xferBarrierType(fRenderTarget->asTexture(),
-                                                              *this->gpu()->caps());
+    fXferBarrierType = programInfo.pipeline().xferBarrierType(*this->gpu()->caps());
 }
 
 void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 0d70a5da..ac42304 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -416,7 +416,8 @@
             chain.head()->prePrepare(context,
                                      &fTargets[0],
                                      chain.appliedClip(),
-                                     chain.dstProxyView());
+                                     chain.dstProxyView(),
+                                     fRenderPassXferBarriers);
         }
     }
 }
@@ -445,7 +446,8 @@
             GrOpFlushState::OpArgs opArgs(chain.head(),
                                           &fTargets[0],
                                           chain.appliedClip(),
-                                          chain.dstProxyView());
+                                          chain.dstProxyView(),
+                                          fRenderPassXferBarriers);
 
             flushState->setOpArgs(&opArgs);
 
@@ -571,7 +573,7 @@
     GrOpsRenderPass* renderPass = create_render_pass(
             flushState->gpu(), proxy->peekRenderTarget(), stencil, this->target(0).origin(),
             fClippedContentBounds, fColorLoadOp, fLoadClearColor, stencilLoadOp, stencilStoreOp,
-            fSampledProxies, fUsesXferBarriers);
+            fSampledProxies, fRenderPassXferBarriers != GrXferBarrierFlags::kNone);
     if (!renderPass) {
         return false;
     }
@@ -590,7 +592,8 @@
         GrOpFlushState::OpArgs opArgs(chain.head(),
                                       &fTargets[0],
                                       chain.appliedClip(),
-                                      chain.dstProxyView());
+                                      chain.dstProxyView(),
+                                      fRenderPassXferBarriers);
 
         flushState->setOpArgs(&opArgs);
         chain.head()->execute(flushState, chain.bounds());
diff --git a/src/gpu/GrOpsTask.h b/src/gpu/GrOpsTask.h
index 3ad87e5..f01236c 100644
--- a/src/gpu/GrOpsTask.h
+++ b/src/gpu/GrOpsTask.h
@@ -113,16 +113,23 @@
         op->visitProxies(addDependency);
         clip.visitProxies(addDependency);
         if (dstProxyView.proxy()) {
-            this->addSampledTexture(dstProxyView.proxy());
+            if (GrDstSampleTypeUsesTexture(dstProxyView.dstSampleType())) {
+                this->addSampledTexture(dstProxyView.proxy());
+            }
             addDependency(dstProxyView.proxy(), GrMipmapped::kNo);
-            if (this->target(0).asTextureProxy() == dstProxyView.proxy()) {
+            if (this->target(0).proxy() == dstProxyView.proxy()) {
                 // Since we are sampling and drawing to the same surface we will need to use
                 // texture barriers.
-                fUsesXferBarriers |= true;
+                SkASSERT(GrDstSampleTypeDirectlySamplesDst(dstProxyView.dstSampleType()));
+                fRenderPassXferBarriers |= GrXferBarrierFlags::kTexture;
             }
+            SkASSERT(dstProxyView.dstSampleType() != GrDstSampleType::kAsInputAttachment ||
+                     dstProxyView.offset().isZero());
         }
 
-        fUsesXferBarriers |= processorAnalysis.usesNonCoherentHWBlending();
+        if (processorAnalysis.usesNonCoherentHWBlending()) {
+            fRenderPassXferBarriers |= GrXferBarrierFlags::kBlend;
+        }
 
         this->recordOp(std::move(op), processorAnalysis, clip.doesClip() ? &clip : nullptr,
                        &dstProxyView, caps);
@@ -320,7 +327,7 @@
     SkIRect fLastDevClipBounds;
     int fLastClipNumAnalyticElements;
 
-    bool fUsesXferBarriers = false;
+    GrXferBarrierFlags fRenderPassXferBarriers = GrXferBarrierFlags::kNone;
 
     // For ops/opsTask we have mean: 5 stdDev: 28
     SkSTArray<25, OpChain> fOpChains;
diff --git a/src/gpu/GrPathRendering.cpp b/src/gpu/GrPathRendering.cpp
index 49608d4..d726b4b 100644
--- a/src/gpu/GrPathRendering.cpp
+++ b/src/gpu/GrPathRendering.cpp
@@ -57,8 +57,7 @@
                                const GrStencilSettings& stencilPassSettings,
                                const GrPath* path) {
     fGpu->handleDirtyContext();
-    if (auto barrierType = programInfo.pipeline().xferBarrierType(renderTarget->asTexture(),
-                                                                  *fGpu->caps())) {
+    if (auto barrierType = programInfo.pipeline().xferBarrierType(*fGpu->caps())) {
         fGpu->xferBarrier(renderTarget, barrierType);
     }
     this->onDrawPath(stencilPassSettings, path);
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index cfc7479..a16ee31 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -32,10 +32,13 @@
 
     fXferProcessor = std::move(xferProcessor);
 
+    SkASSERT((args.fDstProxyView.dstSampleType() != GrDstSampleType::kNone) ==
+             SkToBool(args.fDstProxyView.proxy()));
     if (args.fDstProxyView.proxy()) {
         fDstProxyView = args.fDstProxyView.proxyView();
         fDstTextureOffset = args.fDstProxyView.offset();
     }
+    fDstSampleType = args.fDstProxyView.dstSampleType();
 }
 
 GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
@@ -61,9 +64,8 @@
     }
 }
 
-GrXferBarrierType GrPipeline::xferBarrierType(GrTexture* texture, const GrCaps& caps) const {
-    auto proxy = fDstProxyView.proxy();
-    if (proxy && proxy->peekTexture() == texture) {
+GrXferBarrierType GrPipeline::xferBarrierType(const GrCaps& caps) const {
+    if (fDstProxyView.proxy() && GrDstSampleTypeDirectlySamplesDst(fDstSampleType)) {
         return kTexture_GrXferBarrierType;
     }
     return this->getXferProcessor().xferBarrierType(caps);
@@ -97,13 +99,22 @@
 
     static constexpr uint32_t kBlendWriteShift = 1;
     static constexpr uint32_t kBlendCoeffShift = 5;
+    static constexpr uint32_t kBlendEquationShift = 5;
+    static constexpr uint32_t kDstSampleTypeInputShift = 1;
     static_assert(kLast_GrBlendCoeff < (1 << kBlendCoeffShift));
-    static_assert(kFirstAdvancedGrBlendEquation - 1 < 4);
+    static_assert(kLast_GrBlendEquation < (1 << kBlendEquationShift));
+    static_assert(kBlendWriteShift +
+                  2 * kBlendCoeffShift +
+                  kBlendEquationShift +
+                  kDstSampleTypeInputShift <= 32);
 
     uint32_t blendKey = blendInfo.fWriteColor;
     blendKey |= (blendInfo.fSrcBlend << kBlendWriteShift);
     blendKey |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
     blendKey |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
+    // Note that we use the general fDstSampleType here and not localDstSampleType()
+    blendKey |= ((fDstSampleType == GrDstSampleType::kAsInputAttachment)
+                 << (kBlendWriteShift + 2 * kBlendCoeffShift + kBlendEquationShift));
 
     b->add32(blendKey);
 }
@@ -120,7 +131,7 @@
     for (auto& fp : fFragmentProcessors) {
         fp->visitProxies(func);
     }
-    if (fDstProxyView.asTextureProxy()) {
-        func(fDstProxyView.asTextureProxy(), GrMipmapped::kNo);
+    if (this->usesDstTexture()) {
+        func(fDstProxyView.proxy(), GrMipmapped::kNo);
     }
 }
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index d30fd30..830e23a 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -123,20 +123,34 @@
         }
     }
 
+    GrDstSampleType dstSampleType() const {
+        return fDstSampleType;
+    }
+
+    // Helper functions to quickly know if this GrPipeline will access the dst as a texture or an
+    // input attachment.
+    bool usesDstTexture() const {
+        return GrDstSampleTypeUsesTexture(fDstSampleType);
+    }
+    bool usesInputAttachment() const {
+        return fDstSampleType == GrDstSampleType::kAsInputAttachment;
+    }
+
     /**
      * This returns the GrSurfaceProxyView for the texture used to access the dst color. If the
      * GrXferProcessor does not use the dst color then the proxy on the GrSurfaceProxyView will be
      * nullptr.
      */
-    const GrSurfaceProxyView& dstProxyView() const {
-        return fDstProxyView;
-    }
+    const GrSurfaceProxyView& dstProxyView() const { return fDstProxyView; }
 
     /**
      * If the GrXferProcessor uses a texture to access the dst color, then this returns that
      * texture and the offset to the dst contents within that texture.
      */
     GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
+        if (!this->usesDstTexture()) {
+            return nullptr;
+        }
         if (offset) {
             *offset = fDstTextureOffset;
         }
@@ -195,7 +209,7 @@
     }
 #endif
 
-    GrXferBarrierType xferBarrierType(GrTexture*, const GrCaps&) const;
+    GrXferBarrierType xferBarrierType(const GrCaps&) const;
 
     // Used by Vulkan and Metal to cache their respective pipeline objects
     void genKey(GrProcessorKeyBuilder*, const GrCaps&) const;
@@ -223,6 +237,10 @@
 
     GrSurfaceProxyView fDstProxyView;
     SkIPoint fDstTextureOffset;
+    // This is the GrDstSampleType that is used for the render pass that this GrPipeline will be
+    // used in (i.e. if this GrPipeline does read the dst, it will do so using this
+    // GrDstSampleType).
+    GrDstSampleType fDstSampleType = GrDstSampleType::kNone;
     GrWindowRectsState fWindowRectsState;
     const GrUserStencilSettings* fUserStencilSettings;
     Flags fFlags;
diff --git a/src/gpu/GrProgramInfo.h b/src/gpu/GrProgramInfo.h
index f8ce3fc..cbcce48 100644
--- a/src/gpu/GrProgramInfo.h
+++ b/src/gpu/GrProgramInfo.h
@@ -23,7 +23,8 @@
                   const GrPipeline* pipeline,
                   const GrPrimitiveProcessor* primProc,
                   GrPrimitiveType primitiveType,
-                  uint8_t tessellationPatchVertexCount = 0)
+                  uint8_t tessellationPatchVertexCount,
+                  GrXferBarrierFlags renderPassXferBarriers)
             : fNumSamples(numSamples)
             , fNumStencilSamples(numStencilSamples)
             , fIsMixedSampled(pipeline->isStencilEnabled() && numStencilSamples > numSamples)
@@ -32,7 +33,8 @@
             , fPipeline(pipeline)
             , fPrimProc(primProc)
             , fPrimitiveType(primitiveType)
-            , fTessellationPatchVertexCount(tessellationPatchVertexCount) {
+            , fTessellationPatchVertexCount(tessellationPatchVertexCount)
+            , fRenderPassXferBarriers(renderPassXferBarriers) {
         SkASSERT(this->numRasterSamples() > 0);
         SkASSERT((GrPrimitiveType::kPatches == fPrimitiveType) ==
                  (fTessellationPatchVertexCount > 0));
@@ -67,6 +69,8 @@
         return fTessellationPatchVertexCount;
     }
 
+    GrXferBarrierFlags renderPassBarriers() const { return fRenderPassXferBarriers; }
+
     uint16_t primitiveTypeKey() const {
         return ((uint16_t)fPrimitiveType << 8) | fTessellationPatchVertexCount;
     }
@@ -101,6 +105,7 @@
     GrProcessor::CustomFeatures           fRequestedFeatures;
     GrPrimitiveType                       fPrimitiveType;
     uint8_t                               fTessellationPatchVertexCount;  // GrPrimType::kPatches.
+    GrXferBarrierFlags                    fRenderPassXferBarriers;
 };
 
 #endif
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 904256c..7e3292c 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -2066,7 +2066,8 @@
         willAddFn(op.get(), opsTask->uniqueID());
     }
     opsTask->addDrawOp(this->drawingManager(), std::move(op), analysis, std::move(appliedClip),
-                       dstProxyView,GrTextureResolveManager(this->drawingManager()), *this->caps());
+                       dstProxyView, GrTextureResolveManager(this->drawingManager()),
+                       *this->caps());
 }
 
 bool GrRenderTargetContext::setupDstProxyView(const GrOp& op,
@@ -2078,16 +2079,21 @@
         return false;
     }
 
-    if (this->caps()->textureBarrierSupport() &&
-        !this->asSurfaceProxy()->requiresManualMSAAResolve()) {
-        if (this->asTextureProxy()) {
-            // The render target is a texture, so we can read from it directly in the shader. The XP
-            // will be responsible to detect this situation and request a texture barrier.
-            dstProxyView->setProxyView(this->readSurfaceView());
-            dstProxyView->setOffset(0, 0);
-            return true;
-        }
+    if (fDstSampleType == GrDstSampleType::kNone) {
+        fDstSampleType = this->caps()->getDstSampleTypeForProxy(this->asRenderTargetProxy());
     }
+    SkASSERT(fDstSampleType != GrDstSampleType::kNone);
+
+    if (GrDstSampleTypeDirectlySamplesDst(fDstSampleType)) {
+        // The render target is a texture or input attachment, so we can read from it directly in
+        // the shader. The XP will be responsible to detect this situation and request a texture
+        // barrier.
+        dstProxyView->setProxyView(this->readSurfaceView());
+        dstProxyView->setOffset(0, 0);
+        dstProxyView->setDstSampleType(fDstSampleType);
+        return true;
+    }
+    SkASSERT(fDstSampleType == GrDstSampleType::kAsTextureCopy);
 
     GrColorType colorType = this->colorInfo().colorType();
     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
@@ -2121,6 +2127,7 @@
 
     dstProxyView->setProxyView({std::move(copy), this->origin(), this->readSwizzle()});
     dstProxyView->setOffset(dstOffset);
+    dstProxyView->setDstSampleType(fDstSampleType);
     return true;
 }
 
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index be69830..0567ab4 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -717,6 +717,9 @@
     bool fManagedOpsTask;
 
     int fNumStencilSamples = 0;
+
+    GrDstSampleType fDstSampleType = GrDstSampleType::kNone;
+
 #if GR_TEST_UTILS
     bool fPreserveOpsOnFullClear_TestingOnly = false;
 #endif
diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h
index 3edd51a..74e2137 100644
--- a/src/gpu/GrXferProcessor.h
+++ b/src/gpu/GrXferProcessor.h
@@ -31,6 +31,15 @@
 /** Should be able to treat kNone as false in boolean expressions */
 static_assert(SkToBool(kNone_GrXferBarrierType) == false);
 
+// Flag version of the above enum.
+enum class GrXferBarrierFlags {
+    kNone    = 0,
+    kTexture = 1 << 0,
+    kBlend   = 1 << 1,
+};
+
+GR_MAKE_BITFIELD_CLASS_OPS(GrXferBarrierFlags)
+
 /**
  * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
  * color, and for applying any coverage. It does this by emitting fragment shader code and
@@ -62,23 +71,17 @@
             *this = other;
         }
 
-        DstProxyView(GrSurfaceProxyView view, const SkIPoint& offset)
-            : fProxyView(std::move(view)) {
-            if (fProxyView.proxy()) {
-                fOffset = offset;
-            } else {
-                fOffset.set(0, 0);
-            }
-        }
-
         DstProxyView& operator=(const DstProxyView& other) {
             fProxyView = other.fProxyView;
             fOffset = other.fOffset;
+            fDstSampleType = other.fDstSampleType;
             return *this;
         }
 
         bool operator==(const DstProxyView& that) const {
-            return fProxyView == that.fProxyView && fOffset == that.fOffset;
+            return fProxyView == that.fProxyView &&
+                   fOffset == that.fOffset &&
+                   fDstSampleType == that.fDstSampleType;
         }
         bool operator!=(const DstProxyView& that) const { return !(*this == that); }
 
@@ -87,7 +90,7 @@
         void setOffset(const SkIPoint& offset) { fOffset = offset; }
         void setOffset(int ox, int oy) { fOffset.set(ox, oy); }
 
-        GrTextureProxy* proxy() const { return fProxyView.asTextureProxy(); }
+        GrSurfaceProxy* proxy() const { return fProxyView.proxy(); }
         const GrSurfaceProxyView& proxyView() const { return fProxyView; }
 
         void setProxyView(GrSurfaceProxyView view) {
@@ -97,9 +100,14 @@
             }
         }
 
+        GrDstSampleType dstSampleType() const { return fDstSampleType; }
+
+        void setDstSampleType(GrDstSampleType dstSampleType) { fDstSampleType = dstSampleType; }
+
     private:
-        GrSurfaceProxyView fProxyView;
-        SkIPoint           fOffset;
+        GrSurfaceProxyView       fProxyView;
+        SkIPoint                 fOffset;
+        GrDstSampleType          fDstSampleType = GrDstSampleType::kNone;
     };
 
     /**
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index 0426210..782cc23 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -201,6 +201,6 @@
                               flushState->proxy()->numStencilSamples(),
                               flushState->proxy()->backendFormat(),
                               flushState->writeView()->origin(), &pipeline, this,
-                              this->primType());
+                              this->primType(), 0, flushState->renderPassBarriers());
     flushState->bindPipeline(programInfo, drawBounds);
 }
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index f4b389e..6753ae3 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -74,7 +74,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
 
     friend class GrOpMemoryPool;
 
diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp
index 921c56a..d381274 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -147,7 +147,8 @@
     GrRenderTargetProxy* rtProxy = flushState->proxy();
     GrProgramInfo programInfo(rtProxy->numSamples(), rtProxy->numStencilSamples(),
                               rtProxy->backendFormat(), flushState->writeView()->origin(),
-                              &pipeline, this, primitiveType);
+                              &pipeline, this, primitiveType, 0,
+                              flushState->renderPassBarriers());
 
     flushState->bindPipelineAndScissorClip(programInfo, bounds);
     flushState->bindTextures(*this, atlasProxy, pipeline);
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index 2ca2a20..a549f48 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -60,7 +60,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) final {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) final {}
     void onPrepare(GrOpFlushState*) final {}
 };
 
diff --git a/src/gpu/ccpr/GrCCStroker.cpp b/src/gpu/ccpr/GrCCStroker.cpp
index 3f9d4f5..a6b00f8 100644
--- a/src/gpu/ccpr/GrCCStroker.cpp
+++ b/src/gpu/ccpr/GrCCStroker.cpp
@@ -730,7 +730,8 @@
                               flushState->proxy()->numStencilSamples(),
                               flushState->proxy()->backendFormat(),
                               flushState->writeView()->origin(), &pipeline, &processor,
-                              GrPrimitiveType::kTriangleStrip);
+                              GrPrimitiveType::kTriangleStrip, 0,
+                              flushState->renderPassBarriers());
 
     flushState->bindPipeline(programInfo, SkRect::Make(drawBounds));
     flushState->bindBuffers(nullptr, fInstanceBuffer, nullptr);
diff --git a/src/gpu/ccpr/GrStencilAtlasOp.cpp b/src/gpu/ccpr/GrStencilAtlasOp.cpp
index 0b0721d..bee43b0 100644
--- a/src/gpu/ccpr/GrStencilAtlasOp.cpp
+++ b/src/gpu/ccpr/GrStencilAtlasOp.cpp
@@ -188,7 +188,8 @@
                               flushState->proxy()->numStencilSamples(),
                               flushState->proxy()->backendFormat(),
                               flushState->writeView()->origin(), &resolvePipeline, &primProc,
-                              GrPrimitiveType::kTriangleStrip);
+                              GrPrimitiveType::kTriangleStrip, 0,
+                              flushState->renderPassBarriers());
     flushState->bindPipeline(programInfo, SkRect::Make(drawBounds));
     flushState->setScissorRect(drawBounds);
     flushState->bindBuffers(nullptr, fResources->stencilResolveBuffer(), nullptr);
diff --git a/src/gpu/ccpr/GrStencilAtlasOp.h b/src/gpu/ccpr/GrStencilAtlasOp.h
index 7cce205..d749dc4 100644
--- a/src/gpu/ccpr/GrStencilAtlasOp.h
+++ b/src/gpu/ccpr/GrStencilAtlasOp.h
@@ -56,7 +56,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrepare(GrOpFlushState*) override {}
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
     void drawResolve(GrOpFlushState*, const GrPipeline&, const GrPrimitiveProcessor&,
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 052ad4e..cf40bf5 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -4456,6 +4456,13 @@
     return {};
 }
 
+GrDstSampleType GrGLCaps::onGetDstSampleTypeForProxy(const GrRenderTargetProxy* rt) const {
+    if (rt->asTextureProxy()) {
+        return GrDstSampleType::kAsSelfTexture;
+    }
+    return GrDstSampleType::kAsTextureCopy;
+}
+
 uint64_t GrGLCaps::computeFormatKey(const GrBackendFormat& format) const {
     auto glFormat = format.asGLFormat();
     return (uint64_t)(glFormat);
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 77b2ecd..1c5302a 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -518,6 +518,8 @@
 
     GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
 
+    GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const override;
+
     GrGLStandard fStandard = kNone_GrGLStandard;
 
     SkTArray<StencilFormat, true> fStencilFormats;
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index b28ada6..2a5c4de 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -742,7 +742,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         SkMatrix invert;
         if (fHelper.usesLocalCoords() && !fPaths.back().fViewMatrix.invert(&invert)) {
             return;
@@ -755,7 +756,8 @@
         fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
                                                             std::move(appliedClip),
                                                             dstProxyView, quadProcessor,
-                                                            GrPrimitiveType::kTriangles);
+                                                            GrPrimitiveType::kTriangles,
+                                                            renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index bd77ece..bc40662 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -878,15 +878,18 @@
     void makeLineProgramInfo(const GrCaps&, SkArenaAlloc*, const GrPipeline*,
                              const GrSurfaceProxyView* writeView,
                              const SkMatrix* geometryProcessorViewM,
-                             const SkMatrix* geometryProcessorLocalM);
+                             const SkMatrix* geometryProcessorLocalM,
+                             GrXferBarrierFlags renderPassXferBarriers);
     void makeQuadProgramInfo(const GrCaps&, SkArenaAlloc*, const GrPipeline*,
                              const GrSurfaceProxyView* writeView,
                              const SkMatrix* geometryProcessorViewM,
-                             const SkMatrix* geometryProcessorLocalM);
+                             const SkMatrix* geometryProcessorLocalM,
+                             GrXferBarrierFlags renderPassXferBarriers);
     void makeConicProgramInfo(const GrCaps&, SkArenaAlloc*, const GrPipeline*,
                               const GrSurfaceProxyView* writeView,
                               const SkMatrix* geometryProcessorViewM,
-                              const SkMatrix* geometryProcessorLocalM);
+                              const SkMatrix* geometryProcessorLocalM,
+                              GrXferBarrierFlags renderPassXferBarriers);
 
     GrProgramInfo* programInfo() override {
         // This Op has 3 programInfos and implements its own onPrePrepareDraws so this entry point
@@ -901,12 +904,14 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override;
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override;
 
     void onPrePrepareDraws(GrRecordingContext*,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override;
+                           const GrXferProcessor::DstProxyView&,
+                           GrXferBarrierFlags renderPassXferBarriers) override;
 
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
@@ -990,7 +995,8 @@
                                        const GrPipeline* pipeline,
                                        const GrSurfaceProxyView* writeView,
                                        const SkMatrix* geometryProcessorViewM,
-                                       const SkMatrix* geometryProcessorLocalM) {
+                                       const SkMatrix* geometryProcessorLocalM,
+                                       GrXferBarrierFlags renderPassXferBarriers) {
     if (fProgramInfos[0]) {
         return;
     }
@@ -1012,15 +1018,17 @@
         SkASSERT(sizeof(LineVertex) == lineGP->vertexStride());
     }
 
-    fProgramInfos[0] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(arena, pipeline, writeView, lineGP,
-                                                                   GrPrimitiveType::kTriangles);
+    fProgramInfos[0] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
+            arena, pipeline, writeView, lineGP, GrPrimitiveType::kTriangles,
+            renderPassXferBarriers);
 }
 
 void AAHairlineOp::makeQuadProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
                                        const GrPipeline* pipeline,
                                        const GrSurfaceProxyView* writeView,
                                        const SkMatrix* geometryProcessorViewM,
-                                       const SkMatrix* geometryProcessorLocalM) {
+                                       const SkMatrix* geometryProcessorLocalM,
+                                       GrXferBarrierFlags renderPassXferBarriers) {
     if (fProgramInfos[1]) {
         return;
     }
@@ -1034,15 +1042,17 @@
                                                      this->coverage());
     SkASSERT(sizeof(BezierVertex) == quadGP->vertexStride());
 
-    fProgramInfos[1] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(arena, pipeline, writeView, quadGP,
-                                                                   GrPrimitiveType::kTriangles);
+    fProgramInfos[1] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
+            arena, pipeline, writeView, quadGP, GrPrimitiveType::kTriangles,
+            renderPassXferBarriers);
 }
 
 void AAHairlineOp::makeConicProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
                                         const GrPipeline* pipeline,
                                         const GrSurfaceProxyView* writeView,
                                         const SkMatrix* geometryProcessorViewM,
-                                        const SkMatrix* geometryProcessorLocalM) {
+                                        const SkMatrix* geometryProcessorLocalM,
+                                        GrXferBarrierFlags renderPassXferBarriers) {
     if (fProgramInfos[2]) {
         return;
     }
@@ -1056,8 +1066,9 @@
                                                        this->coverage());
     SkASSERT(sizeof(BezierVertex) == conicGP->vertexStride());
 
-    fProgramInfos[2] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(arena, pipeline, writeView, conicGP,
-                                                                   GrPrimitiveType::kTriangles);
+    fProgramInfos[2] = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
+            arena, pipeline, writeView, conicGP, GrPrimitiveType::kTriangles,
+            renderPassXferBarriers);
 }
 
 AAHairlineOp::Program AAHairlineOp::predictPrograms(const GrCaps* caps) const {
@@ -1090,7 +1101,8 @@
                                        SkArenaAlloc* arena,
                                        const GrSurfaceProxyView* writeView,
                                        GrAppliedClip&& appliedClip,
-                                       const GrXferProcessor::DstProxyView& dstProxyView) {
+                                       const GrXferProcessor::DstProxyView& dstProxyView,
+                                       GrXferBarrierFlags renderPassXferBarriers) {
     // Setup the viewmatrix and localmatrix for the GrGeometryProcessor.
     SkMatrix invert;
     if (!this->viewMatrix().invert(&invert)) {
@@ -1111,15 +1123,18 @@
 
     if (fCharacterization & kLine_Program) {
         this->makeLineProgramInfo(*caps, arena, pipeline, writeView,
-                                  geometryProcessorViewM, geometryProcessorLocalM);
+                                  geometryProcessorViewM, geometryProcessorLocalM,
+                                  renderPassXferBarriers);
     }
     if (fCharacterization & kQuad_Program) {
         this->makeQuadProgramInfo(*caps, arena, pipeline, writeView,
-                                  geometryProcessorViewM, geometryProcessorLocalM);
+                                  geometryProcessorViewM, geometryProcessorLocalM,
+                                  renderPassXferBarriers);
     }
     if (fCharacterization & kConic_Program) {
         this->makeConicProgramInfo(*caps, arena, pipeline, writeView,
-                                   geometryProcessorViewM, geometryProcessorLocalM);
+                                   geometryProcessorViewM, geometryProcessorLocalM,
+                                   renderPassXferBarriers);
 
     }
 }
@@ -1127,7 +1142,8 @@
 void AAHairlineOp::onPrePrepareDraws(GrRecordingContext* context,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip* clip,
-                                     const GrXferProcessor::DstProxyView& dstProxyView) {
+                                     const GrXferProcessor::DstProxyView& dstProxyView,
+                                     GrXferBarrierFlags renderPassXferBarriers) {
     SkArenaAlloc* arena = context->priv().recordTimeAllocator();
     const GrCaps* caps = context->priv().caps();
 
@@ -1137,7 +1153,8 @@
     // Conservatively predict which programs will be required
     fCharacterization = this->predictPrograms(caps);
 
-    this->createProgramInfo(caps, arena, writeView, std::move(appliedClip), dstProxyView);
+    this->createProgramInfo(caps, arena, writeView, std::move(appliedClip), dstProxyView,
+                            renderPassXferBarriers);
 
     context->priv().recordProgramInfo(fProgramInfos[0]);
     context->priv().recordProgramInfo(fProgramInfos[1]);
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index 53643c3..9f8bc51 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -203,7 +203,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp = create_lines_only_gp(arena,
                                                        fHelper.compatibleWithCoverageAsAlpha(),
                                                        fHelper.usesLocalCoords(),
@@ -215,7 +216,8 @@
 
         fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
                                                             std::move(appliedClip), dstProxyView,
-                                                            gp, GrPrimitiveType::kTriangles);
+                                                            gp, GrPrimitiveType::kTriangles,
+                                                            renderPassXferBarriers);
     }
 
     void recordDraw(Target* target,
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 3b07e17..4bcecae 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -112,14 +112,16 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override {
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         // TODO [PI]: implement
     }
 
     void onPrePrepareDraws(GrRecordingContext*,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override {
+                           const GrXferProcessor::DstProxyView&,
+                           GrXferBarrierFlags renderPassXferBarriers) override {
         // TODO [PI]: implement
     }
 
diff --git a/src/gpu/ops/GrClearOp.h b/src/gpu/ops/GrClearOp.h
index f3491bd..6e4846b 100644
--- a/src/gpu/ops/GrClearOp.h
+++ b/src/gpu/ops/GrClearOp.h
@@ -47,7 +47,8 @@
                                       const GrCaps& caps) override;
 
     void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView* writeView, GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
 
     void onPrepare(GrOpFlushState*) override {}
 
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index c09b54f..08846f0 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -321,7 +321,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
 
         DashCap capType = (this->cap() == SkPaint::kRound_Cap) ? kRound_DashCap : kNonRound_DashCap;
 
@@ -360,6 +361,7 @@
                                                                    gp,
                                                                    std::move(fProcessorSet),
                                                                    GrPrimitiveType::kTriangles,
+                                                                   renderPassXferBarriers,
                                                                    pipelineFlags,
                                                                    fStencilSettings);
     }
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 68a2329..95802c8 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -420,7 +420,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp;
         {
             using namespace GrDefaultGeoProcFactory;
@@ -439,7 +440,8 @@
 
         fProgramInfo =  fHelper.createProgramInfoWithStencil(caps, arena, writeView,
                                                              std::move(appliedClip),
-                                                             dstProxyView, gp, this->primType());
+                                                             dstProxyView, gp, this->primType(),
+                                                             renderPassXferBarriers);
 
     }
 
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index 1078ea5..bc19a1a 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -56,7 +56,8 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override;
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override;
 
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
@@ -201,7 +202,8 @@
                                       SkArenaAlloc* arena,
                                       const GrSurfaceProxyView* writeView,
                                       GrAppliedClip&& appliedClip,
-                                      const GrXferProcessor::DstProxyView& dstProxyView) {
+                                      const GrXferProcessor::DstProxyView& dstProxyView,
+                                      GrXferBarrierFlags renderPassXferBarriers) {
     // Setup geometry processor
     GrGeometryProcessor* gp = make_gp(arena,
                                       this->hasColors(),
@@ -209,7 +211,8 @@
                                       this->viewMatrix());
 
     fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                             dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                             dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                             renderPassXferBarriers);
 }
 
 void DrawAtlasOp::onPrepareDraws(Target* target) {
diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp
index ca1b37b..d49bc52 100644
--- a/src/gpu/ops/GrDrawPathOp.cpp
+++ b/src/gpu/ops/GrDrawPathOp.cpp
@@ -95,7 +95,9 @@
                               flushState->writeView()->origin(),
                               pipeline,
                               pathProc.get(),
-                              GrPrimitiveType::kPath);
+                              GrPrimitiveType::kPath,
+                              0,
+                              flushState->renderPassBarriers());
 
     flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
     flushState->bindTextures(programInfo.primProc(), nullptr, programInfo.pipeline());
diff --git a/src/gpu/ops/GrDrawPathOp.h b/src/gpu/ops/GrDrawPathOp.h
index 4c493cd..178969f 100644
--- a/src/gpu/ops/GrDrawPathOp.h
+++ b/src/gpu/ops/GrDrawPathOp.h
@@ -57,7 +57,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) final {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) final {}
 
     void onPrepare(GrOpFlushState*) final {}
 
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 4df9803..0a80e67 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -467,7 +467,8 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override;
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override;
 
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
@@ -634,10 +635,12 @@
                                          SkArenaAlloc* arena,
                                          const GrSurfaceProxyView* writeView,
                                          GrAppliedClip&& appliedClip,
-                                         const GrXferProcessor::DstProxyView& dstProxyView) {
+                                         const GrXferProcessor::DstProxyView& dstProxyView,
+                                         GrXferBarrierFlags renderPassXferBarriers) {
     GrGeometryProcessor* gp = this->makeGP(arena);
     fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                             dstProxyView, gp, this->primitiveType());
+                                             dstProxyView, gp, this->primitiveType(),
+                                             renderPassXferBarriers);
 }
 
 void DrawVerticesOp::onPrepareDraws(Target* target) {
diff --git a/src/gpu/ops/GrDrawableOp.h b/src/gpu/ops/GrDrawableOp.h
index 18fee75..7be5648 100644
--- a/src/gpu/ops/GrDrawableOp.h
+++ b/src/gpu/ops/GrDrawableOp.h
@@ -39,7 +39,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
 
     void onPrepare(GrOpFlushState*) override {}
 
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index d4d8faf..a8c4aca 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -104,7 +104,8 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) final;
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) final;
 
     Helper         fHelper;
     SkPMColor4f    fColor;
@@ -855,12 +856,14 @@
                                       SkArenaAlloc* arena,
                                       const GrSurfaceProxyView* writeView,
                                       GrAppliedClip&& appliedClip,
-                                      const GrXferProcessor::DstProxyView& dstProxyView) {
+                                      const GrXferProcessor::DstProxyView& dstProxyView,
+                                      GrXferBarrierFlags renderPassXferBarriers) {
     GrGeometryProcessor* gp = Processor::Make(arena, fHelper.aaType(), fProcessorFlags);
     SkASSERT(gp->instanceStride() == (size_t)fInstanceStride);
 
     fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                             dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                             dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                             renderPassXferBarriers);
 }
 
 void FillRRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 1d4b30c..a874ea6 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -207,7 +207,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         const VertexSpec vertexSpec = this->vertexSpec();
 
         GrGeometryProcessor* gp = GrQuadPerEdgeAA::MakeProcessor(arena, vertexSpec);
@@ -216,13 +217,15 @@
         fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
                                                             std::move(appliedClip),
                                                             dstProxyView, gp,
-                                                            vertexSpec.primitiveType());
+                                                            vertexSpec.primitiveType(),
+                                                            renderPassXferBarriers);
     }
 
     void onPrePrepareDraws(GrRecordingContext* context,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
+                           const GrXferProcessor::DstProxyView& dstProxyView,
+                           GrXferBarrierFlags renderPassXferBarriers) override {
         TRACE_EVENT0("skia.gpu", TRACE_FUNC);
 
         SkASSERT(!fPrePreparedVertices);
@@ -233,7 +236,7 @@
         GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
 
         this->createProgramInfo(context->priv().caps(), arena, writeView,
-                                std::move(appliedClip), dstProxyView);
+                                std::move(appliedClip), dstProxyView, renderPassXferBarriers);
 
         context->priv().recordProgramInfo(fProgramInfo);
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 03ac020..773e8d9 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -197,7 +197,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
 
         auto gp = LatticeGP::Make(arena, fView, fColorSpaceXform, fFilter, fWideColor);
         if (!gp) {
@@ -209,6 +210,7 @@
                                                                    dstProxyView, gp,
                                                                    fHelper.detachProcessorSet(),
                                                                    GrPrimitiveType::kTriangles,
+                                                                   renderPassXferBarriers,
                                                                    fHelper.pipelineFlags(),
                                                                    &GrUserStencilSettings::kUnused);
     }
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index 809620b..d09fa6a 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -21,7 +21,8 @@
                             target->allocator(),
                             target->writeView(),
                             target->detachAppliedClip(),
-                            target->dstProxyView());
+                            target->dstProxyView(),
+                            target->renderPassBarriers());
 }
 
 // This onPrepareDraws implementation assumes the derived Op only has a single programInfo -
@@ -29,14 +30,15 @@
 void GrMeshDrawOp::onPrePrepareDraws(GrRecordingContext* context,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip* clip,
-                                     const GrXferProcessor::DstProxyView& dstProxyView) {
+                                     const GrXferProcessor::DstProxyView& dstProxyView,
+                                     GrXferBarrierFlags renderPassXferBarriers) {
     SkArenaAlloc* arena = context->priv().recordTimeAllocator();
 
     // This is equivalent to a GrOpFlushState::detachAppliedClip
     GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
 
     this->createProgramInfo(context->priv().caps(), arena, writeView,
-                            std::move(appliedClip), dstProxyView);
+                            std::move(appliedClip), dstProxyView, renderPassXferBarriers);
 
     // TODO: at this point we've created both the program info and desc in the recording context's
     // arena. In the DDL case, it would be cool if 'recordProgramInfo' could return the
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index baf81f5..09f864f 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -41,8 +41,10 @@
                            SkArenaAlloc* arena,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip&& appliedClip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) {
-        this->onCreateProgramInfo(caps, arena, writeView, std::move(appliedClip), dstProxyView);
+                           const GrXferProcessor::DstProxyView& dstProxyView,
+                           GrXferBarrierFlags renderPassXferBarriers) {
+        this->onCreateProgramInfo(caps, arena, writeView, std::move(appliedClip), dstProxyView,
+                                  renderPassXferBarriers);
     }
 
     void createProgramInfo(Target* target);
@@ -103,7 +105,8 @@
     virtual void onPrePrepareDraws(GrRecordingContext*,
                                    const GrSurfaceProxyView* writeView,
                                    GrAppliedClip*,
-                                   const GrXferProcessor::DstProxyView&);
+                                   const GrXferProcessor::DstProxyView&,
+                                   GrXferBarrierFlags renderPassXferBarriers);
 
 private:
     virtual GrProgramInfo* programInfo() = 0;
@@ -113,13 +116,15 @@
                                      SkArenaAlloc*,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip&&,
-                                     const GrXferProcessor::DstProxyView&) = 0;
+                                     const GrXferProcessor::DstProxyView&,
+                                     GrXferBarrierFlags renderPassXferBarriers) = 0;
 
     void onPrePrepare(GrRecordingContext* context,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip* clip,
-                      const GrXferProcessor::DstProxyView& dstProxyView) final {
-        this->onPrePrepareDraws(context, writeView, clip, dstProxyView);
+                      const GrXferProcessor::DstProxyView& dstProxyView,
+                      GrXferBarrierFlags renderPassXferBarriers) final {
+        this->onPrePrepareDraws(context, writeView, clip, dstProxyView, renderPassXferBarriers);
     }
     void onPrepare(GrOpFlushState* state) final;
 
@@ -218,6 +223,8 @@
 
     virtual const GrXferProcessor::DstProxyView& dstProxyView() const = 0;
 
+    virtual GrXferBarrierFlags renderPassBarriers() const = 0;
+
     virtual GrResourceProvider* resourceProvider() const = 0;
     uint32_t contextUniqueID() const { return this->resourceProvider()->contextUniqueID(); }
 
diff --git a/src/gpu/ops/GrOp.h b/src/gpu/ops/GrOp.h
index 66ff71f..b9f6e4a 100644
--- a/src/gpu/ops/GrOp.h
+++ b/src/gpu/ops/GrOp.h
@@ -163,8 +163,9 @@
      * ahead of time and when it has not been called).
      */
     void prePrepare(GrRecordingContext* context, GrSurfaceProxyView* dstView, GrAppliedClip* clip,
-                    const GrXferProcessor::DstProxyView& dstProxyView) {
-        this->onPrePrepare(context, dstView, clip, dstProxyView);
+                    const GrXferProcessor::DstProxyView& dstProxyView,
+                    GrXferBarrierFlags renderPassXferBarriers) {
+        this->onPrePrepare(context, dstView, clip, dstProxyView, renderPassXferBarriers);
     }
 
     /**
@@ -296,7 +297,8 @@
     virtual void onPrePrepare(GrRecordingContext*,
                               const GrSurfaceProxyView* writeView,
                               GrAppliedClip*,
-                              const GrXferProcessor::DstProxyView&) = 0;
+                              const GrXferProcessor::DstProxyView&,
+                              GrXferBarrierFlags renderPassXferBarriers) = 0;
     virtual void onPrepare(GrOpFlushState*) = 0;
     // If this op is chained then chainBounds is the union of the bounds of all ops in the chain.
     // Otherwise, this op's bounds.
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index ab3299b..051906e 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1244,7 +1244,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         SkMatrix localMatrix;
         if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
             return;
@@ -1256,7 +1257,8 @@
                                                                 localMatrix);
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -1605,7 +1607,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         SkMatrix localMatrix;
         if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
             return;
@@ -1617,7 +1620,8 @@
                                                                              localMatrix);
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -1937,7 +1941,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         SkMatrix localMatrix;
         if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
             return;
@@ -1947,7 +1952,8 @@
                                                                  fUseScale, localMatrix);
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -2212,13 +2218,15 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp = DIEllipseGeometryProcessor::Make(arena, fWideColor, fUseScale,
                                                                    this->viewMatrix(),
                                                                    this->style());
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -2609,7 +2617,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         // Invert the view matrix as a local matrix (if any other processors require coords).
         SkMatrix localMatrix;
         if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
@@ -2621,7 +2630,8 @@
                                                                 fWideColor, localMatrix);
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -2931,7 +2941,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         SkMatrix localMatrix;
         if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
             return;
@@ -2941,7 +2952,8 @@
                                                                  fUseScale, localMatrix);
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 1c58183..91983ea 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -89,7 +89,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp = make_gp(arena, fViewMatrix, fWideColor);
         if (!gp) {
             SkDebugf("Couldn't create GrGeometryProcessor\n");
@@ -98,7 +99,8 @@
 
         fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
                                                             std::move(appliedClip), dstProxyView,
-                                                            gp, GrPrimitiveType::kTriangles);
+                                                            gp, GrPrimitiveType::kTriangles,
+                                                            renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index 8e7f7d6..9d1d740 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -529,7 +529,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp = GrRRectShadowGeoProc::Make(arena, fFalloffView);
         SkASSERT(sizeof(CircleVertex) == gp->vertexStride());
 
@@ -538,6 +539,7 @@
                                                                    dstProxyView, gp,
                                                                    GrProcessorSet::MakeEmptySet(),
                                                                    GrPrimitiveType::kTriangles,
+                                                                   renderPassXferBarriers,
                                                                    GrPipeline::InputFlags::kNone,
                                                                    &GrUserStencilSettings::kUnused);
     }
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
index ae689e5..4a876ec 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp
@@ -164,6 +164,7 @@
             GrGeometryProcessor* geometryProcessor,
             GrProcessorSet&& processorSet,
             GrPrimitiveType primitiveType,
+            GrXferBarrierFlags renderPassXferBarriers,
             GrPipeline::InputFlags pipelineFlags,
             const GrUserStencilSettings* stencilSettings) {
     auto pipeline = CreatePipeline(caps,
@@ -175,14 +176,16 @@
                                    pipelineFlags,
                                    stencilSettings);
 
-    return CreateProgramInfo(arena, pipeline, writeView, geometryProcessor, primitiveType);
+    return CreateProgramInfo(arena, pipeline, writeView, geometryProcessor, primitiveType,
+                             renderPassXferBarriers);
 }
 
 GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(SkArenaAlloc* arena,
                                                            const GrPipeline* pipeline,
                                                            const GrSurfaceProxyView* writeView,
                                                            GrGeometryProcessor* geometryProcessor,
-                                                           GrPrimitiveType primitiveType) {
+                                                           GrPrimitiveType primitiveType,
+                                                           GrXferBarrierFlags renderPassXferBarriers) {
     GrRenderTargetProxy* outputProxy = writeView->asRenderTargetProxy();
 
     auto tmp = arena->make<GrProgramInfo>(outputProxy->numSamples(),
@@ -191,7 +194,9 @@
                                           writeView->origin(),
                                           pipeline,
                                           geometryProcessor,
-                                          primitiveType);
+                                          primitiveType,
+                                          0,
+                                          renderPassXferBarriers);
     return tmp;
 }
 
@@ -202,7 +207,8 @@
                                             GrAppliedClip&& appliedClip,
                                             const GrXferProcessor::DstProxyView& dstProxyView,
                                             GrGeometryProcessor* gp,
-                                            GrPrimitiveType primType) {
+                                            GrPrimitiveType primType,
+                                            GrXferBarrierFlags renderPassXferBarriers) {
     return CreateProgramInfo(caps,
                              arena,
                              writeView,
@@ -211,6 +217,7 @@
                              gp,
                              this->detachProcessorSet(),
                              primType,
+                             renderPassXferBarriers,
                              this->pipelineFlags());
 }
 
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
index 231e078..3ef6d8e 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -144,7 +144,8 @@
                                             const GrPipeline*,
                                             const GrSurfaceProxyView* writeView,
                                             GrGeometryProcessor*,
-                                            GrPrimitiveType);
+                                            GrPrimitiveType,
+                                            GrXferBarrierFlags renderPassXferBarriers);
 
     // Create a programInfo with the following properties:
     //     its primitive processor uses no textures
@@ -157,6 +158,7 @@
                                             GrGeometryProcessor*,
                                             GrProcessorSet&&,
                                             GrPrimitiveType,
+                                            GrXferBarrierFlags renderPassXferBarriers,
                                             GrPipeline::InputFlags pipelineFlags
                                                                 = GrPipeline::InputFlags::kNone,
                                             const GrUserStencilSettings*
@@ -168,7 +170,8 @@
                                      GrAppliedClip&&,
                                      const GrXferProcessor::DstProxyView&,
                                      GrGeometryProcessor*,
-                                     GrPrimitiveType);
+                                     GrPrimitiveType,
+                                     GrXferBarrierFlags renderPassXferBarriers);
 
     GrProcessorSet detachProcessorSet() {
         return fProcessors ? std::move(*fProcessors) : GrProcessorSet::MakeEmptySet();
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp
index 202f2e5..000b699 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.cpp
@@ -76,7 +76,8 @@
                                             GrAppliedClip&& appliedClip,
                                             const GrXferProcessor::DstProxyView& dstProxyView,
                                             GrGeometryProcessor* gp,
-                                            GrPrimitiveType primType) {
+                                            GrPrimitiveType primType,
+                                            GrXferBarrierFlags renderPassXferBarriers) {
     return CreateProgramInfo(caps,
                              arena,
                              writeViewSwizzle,
@@ -85,6 +86,7 @@
                              gp,
                              this->detachProcessorSet(),
                              primType,
+                             renderPassXferBarriers,
                              this->pipelineFlags(),
                              this->stencilSettings());
 }
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h
index 95628e5..b1339ad 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h
@@ -36,7 +36,8 @@
                                                 GrAppliedClip&&,
                                                 const GrXferProcessor::DstProxyView&,
                                                 GrGeometryProcessor*,
-                                                GrPrimitiveType);
+                                                GrPrimitiveType,
+                                                GrXferBarrierFlags renderPassXferBarriers);
 
 
     // using declarations can't be templated, so this is a pass through function instead.
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index c46ca51..8d44fb8 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -165,14 +165,16 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override {
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         // TODO [PI]: implement
     }
 
     void onPrePrepareDraws(GrRecordingContext*,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override {
+                           const GrXferProcessor::DstProxyView&,
+                           GrXferBarrierFlags renderPassXferBarriers) override {
         // TODO [PI]: implement
     }
 
diff --git a/src/gpu/ops/GrStencilPathOp.h b/src/gpu/ops/GrStencilPathOp.h
index edaf5b5..dca6866 100644
--- a/src/gpu/ops/GrStencilPathOp.h
+++ b/src/gpu/ops/GrStencilPathOp.h
@@ -50,7 +50,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
 
     void onPrepare(GrOpFlushState*) override {}
 
diff --git a/src/gpu/ops/GrStrokeRectOp.cpp b/src/gpu/ops/GrStrokeRectOp.cpp
index fbdcb7a..e7a5ba8 100644
--- a/src/gpu/ops/GrStrokeRectOp.cpp
+++ b/src/gpu/ops/GrStrokeRectOp.cpp
@@ -174,7 +174,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& clip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp;
         {
             using namespace GrDefaultGeoProcFactory;
@@ -190,7 +191,8 @@
                                                       : GrPrimitiveType::kLineStrip;
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(clip),
-                                                 dstProxyView, gp, primType);
+                                                 dstProxyView, gp, primType,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -440,7 +442,8 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override;
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override;
 
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
@@ -515,7 +518,8 @@
                                          SkArenaAlloc* arena,
                                          const GrSurfaceProxyView* writeView,
                                          GrAppliedClip&& appliedClip,
-                                         const GrXferProcessor::DstProxyView& dstProxyView) {
+                                         const GrXferProcessor::DstProxyView& dstProxyView,
+                                         GrXferBarrierFlags renderPassXferBarriers) {
 
     GrGeometryProcessor* gp = create_aa_stroke_rect_gp(arena,
                                                        fHelper.compatibleWithCoverageAsAlpha(),
@@ -533,7 +537,8 @@
                                              std::move(appliedClip),
                                              dstProxyView,
                                              gp,
-                                             GrPrimitiveType::kTriangles);
+                                             GrPrimitiveType::kTriangles,
+                                             renderPassXferBarriers);
 }
 
 void AAStrokeRectOp::onPrepareDraws(Target* target) {
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 10e49cc..bc6c399 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -651,7 +651,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         SkASSERT(fDesc);
 
         GrGeometryProcessor* gp;
@@ -676,13 +677,14 @@
         fDesc->fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
                 caps, arena, writeView, std::move(appliedClip), dstProxyView, gp,
                 GrProcessorSet::MakeEmptySet(), fDesc->fVertexSpec.primitiveType(),
-                pipelineFlags);
+                renderPassXferBarriers, pipelineFlags);
     }
 
     void onPrePrepareDraws(GrRecordingContext* context,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip* clip,
-                           const GrXferProcessor::DstProxyView& dstProxyView) override {
+                           const GrXferProcessor::DstProxyView& dstProxyView,
+                           GrXferBarrierFlags renderPassXferBarriers) override {
         TRACE_EVENT0("skia.gpu", TRACE_FUNC);
 
         SkDEBUGCODE(this->validate();)
@@ -696,7 +698,8 @@
         FillInVertices(*context->priv().caps(), this, fDesc, fDesc->fPrePreparedVertices);
 
         // This will call onCreateProgramInfo and register the created program with the DDL.
-        this->INHERITED::onPrePrepareDraws(context, writeView, clip, dstProxyView);
+        this->INHERITED::onPrePrepareDraws(context, writeView, clip, dstProxyView,
+                                           renderPassXferBarriers);
     }
 
     static void FillInVertices(const GrCaps& caps, TextureOp* texOp, Desc* desc, char* vertexData) {
diff --git a/src/gpu/ops/GrTriangulatingPathRenderer.cpp b/src/gpu/ops/GrTriangulatingPathRenderer.cpp
index 49310db..fd5341c 100644
--- a/src/gpu/ops/GrTriangulatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTriangulatingPathRenderer.cpp
@@ -319,7 +319,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         GrGeometryProcessor* gp;
         {
             using namespace GrDefaultGeoProcFactory;
@@ -361,7 +362,8 @@
 
         fProgramInfo =  fHelper.createProgramInfoWithStencil(caps, arena, writeView,
                                                              std::move(appliedClip), dstProxyView,
-                                                             gp, primitiveType);
+                                                             gp, primitiveType,
+                                                             renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
diff --git a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
index f7ad26e..1631cfa 100644
--- a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
+++ b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
@@ -144,8 +144,8 @@
 void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext*,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip*,
-                                     const GrXferProcessor::DstProxyView&) {
-}
+                                     const GrXferProcessor::DstProxyView&,
+                                     GrXferBarrierFlags renderPassXferBarriers) {}
 
 void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* state) {
     size_t instanceStride = Instance::Stride(fUsesLocalCoords);
@@ -180,7 +180,8 @@
 
     GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
                               state->proxy()->backendFormat(), state->writeView()->origin(),
-                              &pipeline, &shader, GrPrimitiveType::kTriangleStrip);
+                              &pipeline, &shader, GrPrimitiveType::kTriangleStrip, 0,
+                              state->renderPassBarriers());
 
     state->bindPipelineAndScissorClip(programInfo, this->bounds());
     state->bindTextures(shader, *fAtlasProxy, pipeline);
diff --git a/src/gpu/tessellate/GrDrawAtlasPathOp.h b/src/gpu/tessellate/GrDrawAtlasPathOp.h
index c7299a7..066dd83 100644
--- a/src/gpu/tessellate/GrDrawAtlasPathOp.h
+++ b/src/gpu/tessellate/GrDrawAtlasPathOp.h
@@ -45,7 +45,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override;
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override;
 
     struct Instance {
         constexpr static size_t Stride(bool usesLocalCoords) {
diff --git a/src/gpu/tessellate/GrPathShader.h b/src/gpu/tessellate/GrPathShader.h
index e244f1e..3e371c4 100644
--- a/src/gpu/tessellate/GrPathShader.h
+++ b/src/gpu/tessellate/GrPathShader.h
@@ -33,15 +33,22 @@
     // GrPathShader.
     class ProgramInfo : public GrProgramInfo {
     public:
-        ProgramInfo(const GrSurfaceProxyView* view, const GrPipeline* pipeline,
-                    const GrPathShader* shader)
-                : ProgramInfo(view->asRenderTargetProxy(), view->origin(), pipeline, shader) {
+        ProgramInfo(const GrSurfaceProxyView* view,
+                    const GrPipeline* pipeline,
+                    const GrPathShader* shader,
+                    GrXferBarrierFlags renderPassXferBarriers)
+                : ProgramInfo(view->asRenderTargetProxy(), view->origin(), pipeline, shader,
+                              renderPassXferBarriers) {
         }
-        ProgramInfo(const GrRenderTargetProxy* proxy, GrSurfaceOrigin origin,
-                    const GrPipeline* pipeline, const GrPathShader* shader)
+        ProgramInfo(const GrRenderTargetProxy* proxy,
+                    GrSurfaceOrigin origin,
+                    const GrPipeline* pipeline,
+                    const GrPathShader* shader,
+                    GrXferBarrierFlags renderPassXferBarriers)
                 : GrProgramInfo(proxy->numSamples(), proxy->numStencilSamples(),
                                 proxy->backendFormat(), origin, pipeline, shader,
-                                shader->fPrimitiveType, shader->fTessellationPatchVertexCount) {
+                                shader->fPrimitiveType, shader->fTessellationPatchVertexCount,
+                                renderPassXferBarriers) {
         }
     };
 
diff --git a/src/gpu/tessellate/GrPathTessellateOp.cpp b/src/gpu/tessellate/GrPathTessellateOp.cpp
index cd0254e..3b475e7 100644
--- a/src/gpu/tessellate/GrPathTessellateOp.cpp
+++ b/src/gpu/tessellate/GrPathTessellateOp.cpp
@@ -36,8 +36,8 @@
 void GrPathTessellateOp::onPrePrepare(GrRecordingContext*,
                                       const GrSurfaceProxyView* writeView,
                                       GrAppliedClip*,
-                                      const GrXferProcessor::DstProxyView&) {
-}
+                                      const GrXferProcessor::DstProxyView&,
+                                      GrXferBarrierFlags renderPassXferBarriers) {}
 
 void GrPathTessellateOp::onPrepare(GrOpFlushState* flushState) {
     int numVerbs = fPath.countVerbs();
@@ -544,7 +544,8 @@
         SkASSERT(fTriangleBuffer);
         GrStencilTriangleShader stencilTriangleShader(fViewMatrix);
         GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
-                                              &stencilTriangleShader);
+                                              &stencilTriangleShader,
+                                              flushState->renderPassBarriers());
         flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
         flushState->bindBuffers(nullptr, nullptr, fTriangleBuffer);
         flushState->draw(fTriangleVertexCount, fBaseTriangleVertex);
@@ -553,7 +554,8 @@
     if (fStencilCubicsShader) {
         SkASSERT(fCubicBuffer);
         GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
-                                              fStencilCubicsShader);
+                                              fStencilCubicsShader,
+                                              flushState->renderPassBarriers());
         flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
         if (fIndirectDrawBuffer) {
             SkASSERT(fIndirectIndexBuffer);
@@ -652,7 +654,8 @@
 
         GrFillTriangleShader fillTriangleShader(fViewMatrix, fColor);
         GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
-                                              &fillTriangleShader);
+                                              &fillTriangleShader,
+                                              flushState->renderPassBarriers());
         flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
         flushState->bindTextures(fillTriangleShader, nullptr, pipeline);
         flushState->bindBuffers(nullptr, nullptr, fTriangleBuffer);
@@ -667,7 +670,8 @@
             pipeline.setUserStencil(&kTestAndResetStencil);
             GrFillCubicHullShader fillCubicHullShader(fViewMatrix, fColor);
             GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
-                                                  &fillCubicHullShader);
+                                                  &fillCubicHullShader,
+                                                  flushState->renderPassBarriers());
             flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
             flushState->bindTextures(fillCubicHullShader, nullptr, pipeline);
 
@@ -685,7 +689,8 @@
     pipeline.setUserStencil(&kTestAndResetStencil);
     GrFillBoundingBoxShader fillBoundingBoxShader(fViewMatrix, fColor, fPath.getBounds());
     GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
-                                          &fillBoundingBoxShader);
+                                          &fillBoundingBoxShader,
+                                          flushState->renderPassBarriers());
     flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
     flushState->bindTextures(fillBoundingBoxShader, nullptr, pipeline);
     flushState->bindBuffers(nullptr, nullptr, nullptr);
diff --git a/src/gpu/tessellate/GrPathTessellateOp.h b/src/gpu/tessellate/GrPathTessellateOp.h
index de885ba..f4e9f0f 100644
--- a/src/gpu/tessellate/GrPathTessellateOp.h
+++ b/src/gpu/tessellate/GrPathTessellateOp.h
@@ -48,7 +48,8 @@
 
     FixedFunctionFlags fixedFunctionFlags() const override;
     void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView*, GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override;
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override;
     void onPrepare(GrOpFlushState* state) override;
 
     // Produces a non-overlapping triangulation of the path's inner polygon(s). The inner polygons
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.cpp b/src/gpu/tessellate/GrStrokeTessellateOp.cpp
index 8cd6816..10a2fbf 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.cpp
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.cpp
@@ -88,8 +88,9 @@
 }
 
 void GrStrokeTessellateOp::onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView* writeView,
-                                        GrAppliedClip*, const GrXferProcessor::DstProxyView&) {
-}
+                                        GrAppliedClip*,
+                                        const GrXferProcessor::DstProxyView&,
+                                        GrXferBarrierFlags renderPassXferBarriers) {}
 
 void GrStrokeTessellateOp::onPrepare(GrOpFlushState* flushState) {
     GrStrokePatchBuilder builder(flushState, &fPatchChunks, fMatrixScale, fTotalCombinedVerbCnt);
@@ -111,7 +112,8 @@
     GrPipeline pipeline(initArgs, std::move(fProcessors), flushState->detachAppliedClip());
 
     GrStrokeTessellateShader strokeShader(fMatrixScale, fMiterLimitOrZero, fViewMatrix, fColor);
-    GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, &strokeShader);
+    GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline, &strokeShader,
+                                          flushState->renderPassBarriers());
 
     SkASSERT(chainBounds == this->bounds());
     flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.h b/src/gpu/tessellate/GrStrokeTessellateOp.h
index a1ea0e0..1ea1e0f 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.h
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.h
@@ -35,7 +35,8 @@
                                       bool hasMixedSampledCoverage, GrClampType) override;
     CombineResult onCombineIfPossible(GrOp*, GrRecordingContext::Arenas*, const GrCaps&) override;
     void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView*, GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override;
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override;
     void onPrepare(GrOpFlushState* state) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
 
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 56e8127..0bbf0fe 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1627,6 +1627,13 @@
     return {};
 }
 
+GrDstSampleType GrVkCaps::onGetDstSampleTypeForProxy(const GrRenderTargetProxy* rt) const {
+    if (rt->supportsVkInputAttachment()) {
+        return GrDstSampleType::kAsInputAttachment;
+    }
+    return GrDstSampleType::kAsTextureCopy;
+}
+
 uint64_t GrVkCaps::computeFormatKey(const GrBackendFormat& format) const {
     VkFormat vkFormat;
     SkAssertResult(format.asVkFormat(&vkFormat));
@@ -1728,10 +1735,9 @@
     // GrVkPipelineStateBuilder.cpp).
     b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
 
-    // Currently we only support blend barriers with the advanced blend function. Thus we pass in
-    // nullptr for the texture.
-    auto barrierType = programInfo.pipeline().xferBarrierType(nullptr, *this);
-    bool usesXferBarriers = barrierType == kBlend_GrXferBarrierType;
+    auto barrierType = programInfo.pipeline().xferBarrierType(*this);
+    bool usesXferBarriers = barrierType == kBlend_GrXferBarrierType ||
+                            barrierType == kTexture_GrXferBarrierType;
 
     if (rt) {
         GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 9b37410..6856a63 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -247,6 +247,7 @@
 
     GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
 
+    GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const override;
 
     // ColorTypeInfo for a specific format
     struct ColorTypeInfo {
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 5275150..ce49a0e 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1939,10 +1939,9 @@
     GrVkRenderTarget::ReconstructAttachmentsDescriptor(this->vkCaps(), programInfo,
                                                        &attachmentsDescriptor, &attachmentFlags);
 
-    // Currently we only support blend barriers with the advanced blend function. Thus we pass in
-    // nullptr for the texture.
-    auto barrierType = programInfo.pipeline().xferBarrierType(nullptr, *this->caps());
-    bool willReadDst =  barrierType == kBlend_GrXferBarrierType;
+    auto barrierType = programInfo.pipeline().xferBarrierType(*this->caps());
+    bool willReadDst =  barrierType == kBlend_GrXferBarrierType ||
+                        barrierType == kTexture_GrXferBarrierType;
     sk_sp<const GrVkRenderPass> renderPass(this->resourceProvider().findCompatibleRenderPass(
                                                                          &attachmentsDescriptor,
                                                                          attachmentFlags,
diff --git a/tests/DrawOpAtlasTest.cpp b/tests/DrawOpAtlasTest.cpp
index fe89dfa..eec3a07 100644
--- a/tests/DrawOpAtlasTest.cpp
+++ b/tests/DrawOpAtlasTest.cpp
@@ -227,8 +227,8 @@
     GrOpFlushState::OpArgs opArgs(op.get(),
                                   &surfaceView,
                                   nullptr,
-                                  GrXferProcessor::DstProxyView(GrSurfaceProxyView(),
-                                                                SkIPoint::Make(0, 0)));
+                                  GrXferProcessor::DstProxyView(),
+                                  GrXferBarrierFlags::kNone);
 
     // Modify the atlas manager so it can't allocate any pages. This will force a failure
     // in the preparation of the text op
diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp
index 502700e..ee3e5c3 100644
--- a/tests/GrMeshTest.cpp
+++ b/tests/GrMeshTest.cpp
@@ -435,7 +435,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrepare(GrOpFlushState* state) override {
         fHelper = std::make_unique<DrawMeshHelper>(state);
         fPrepareFn(fHelper.get());
@@ -576,7 +577,7 @@
 
     GrProgramInfo programInfo(fState->proxy()->numSamples(), fState->proxy()->numStencilSamples(),
                               fState->proxy()->backendFormat(), fState->writeView()->origin(),
-                              pipeline, mtp, primitiveType);
+                              pipeline, mtp, primitiveType, 0, fState->renderPassBarriers());
 
     fState->opsRenderPass()->bindPipeline(programInfo, SkRect::MakeIWH(kImageWidth, kImageHeight));
     return fState->opsRenderPass();
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index ae57c49..11da0e2 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -147,7 +147,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrepare(GrOpFlushState*) override {}
     void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
         GrPipeline pipeline(fScissorTest, SkBlendMode::kSrc,
@@ -166,7 +167,8 @@
                                   flushState->writeView()->origin(),
                                   &pipeline,
                                   geomProc,
-                                  GrPrimitiveType::kTriangleStrip);
+                                  GrPrimitiveType::kTriangleStrip, 0,
+                                  flushState->renderPassBarriers());
 
         flushState->bindPipeline(programInfo, SkRect::MakeIWH(kScreenSize, kScreenSize));
         for (int i = 0; i < 4; ++i) {
diff --git a/tests/LazyProxyTest.cpp b/tests/LazyProxyTest.cpp
index 46338ec..2f5db6e 100644
--- a/tests/LazyProxyTest.cpp
+++ b/tests/LazyProxyTest.cpp
@@ -114,7 +114,8 @@
         void onPrePrepare(GrRecordingContext*,
                           const GrSurfaceProxyView* writeView,
                           GrAppliedClip*,
-                          const GrXferProcessor::DstProxyView&) override {}
+                          const GrXferProcessor::DstProxyView&,
+                          GrXferBarrierFlags renderPassXferBarriers) override {}
 
         void onPrepare(GrOpFlushState*) override {}
 
@@ -361,7 +362,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrepare(GrOpFlushState*) override {}
     void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
         *fTestExecuteValue = 2;
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index e56eb63..5bbfbc8 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -103,7 +103,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         using namespace GrDefaultGeoProcFactory;
 
         GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Make(
@@ -119,7 +120,8 @@
         }
 
         fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
-                                                 dstProxyView, gp, GrPrimitiveType::kTriangles);
+                                                 dstProxyView, gp, GrPrimitiveType::kTriangles,
+                                                 renderPassXferBarriers);
     }
 
     void onPrepareDraws(Target* target) override {
diff --git a/tests/OpChainTest.cpp b/tests/OpChainTest.cpp
index cdc9b19..1173f15 100644
--- a/tests/OpChainTest.cpp
+++ b/tests/OpChainTest.cpp
@@ -128,7 +128,8 @@
     void onPrePrepare(GrRecordingContext*,
                       const GrSurfaceProxyView* writeView,
                       GrAppliedClip*,
-                      const GrXferProcessor::DstProxyView&) override {}
+                      const GrXferProcessor::DstProxyView&,
+                      GrXferBarrierFlags renderPassXferBarriers) override {}
 
     void onPrepare(GrOpFlushState*) override {}
 
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp
index 491e302..2c3c006 100644
--- a/tests/PrimitiveProcessorTest.cpp
+++ b/tests/PrimitiveProcessorTest.cpp
@@ -64,7 +64,8 @@
                              SkArenaAlloc* arena,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&& appliedClip,
-                             const GrXferProcessor::DstProxyView& dstProxyView) override {
+                             const GrXferProcessor::DstProxyView& dstProxyView,
+                             GrXferBarrierFlags renderPassXferBarriers) override {
         class GP : public GrGeometryProcessor {
         public:
             static GrGeometryProcessor* Make(SkArenaAlloc* arena, int numAttribs) {
@@ -134,6 +135,7 @@
                                                                    gp,
                                                                    GrProcessorSet::MakeEmptySet(),
                                                                    GrPrimitiveType::kTriangles,
+                                                                   renderPassXferBarriers,
                                                                    GrPipeline::InputFlags::kNone);
     }
 
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 0d08777..99f46eb 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -69,11 +69,13 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override { return; }
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrePrepareDraws(GrRecordingContext*,
                            const GrSurfaceProxyView* writeView,
                            GrAppliedClip*,
-                           const GrXferProcessor::DstProxyView&) override { return; }
+                           const GrXferProcessor::DstProxyView&,
+                           GrXferBarrierFlags renderPassXferBarriers) override {}
     void onPrepareDraws(Target* target) override { return; }
     void onExecute(GrOpFlushState*, const SkRect&) override { return; }
 
diff --git a/tools/gpu/ProxyUtils.cpp b/tools/gpu/ProxyUtils.cpp
index b740c63..06b2e8a 100644
--- a/tools/gpu/ProxyUtils.cpp
+++ b/tools/gpu/ProxyUtils.cpp
@@ -67,6 +67,7 @@
                                  GrGeometryProcessor* geomProc,
                                  SkBlendMode blendMode,
                                  GrPrimitiveType primitiveType,
+                                 GrXferBarrierFlags renderPassXferBarriers,
                                  GrPipeline::InputFlags flags,
                                  const GrUserStencilSettings* stencilSettings) {
 
@@ -83,7 +84,8 @@
     return GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, writeView,
                                                        std::move(appliedClip), dstProxyView,
                                                        geomProc, std::move(processors),
-                                                       primitiveType, flags, stencilSettings);
+                                                       primitiveType, renderPassXferBarriers, flags,
+                                                       stencilSettings);
 }
 
 
diff --git a/tools/gpu/ProxyUtils.h b/tools/gpu/ProxyUtils.h
index eace13f..84277a4 100644
--- a/tools/gpu/ProxyUtils.h
+++ b/tools/gpu/ProxyUtils.h
@@ -34,6 +34,7 @@
                                  GrGeometryProcessor*,
                                  SkBlendMode,
                                  GrPrimitiveType,
+                                 GrXferBarrierFlags renderPassXferBarriers,
                                  GrPipeline::InputFlags flags = GrPipeline::InputFlags::kNone,
                                  const GrUserStencilSettings* stencil =
                                                                 &GrUserStencilSettings::kUnused);
diff --git a/tools/gpu/TestOps.cpp b/tools/gpu/TestOps.cpp
index cfd6815..30331fc 100644
--- a/tools/gpu/TestOps.cpp
+++ b/tools/gpu/TestOps.cpp
@@ -119,7 +119,8 @@
                              SkArenaAlloc*,
                              const GrSurfaceProxyView* writeView,
                              GrAppliedClip&&,
-                             const GrXferProcessor::DstProxyView&) override;
+                             const GrXferProcessor::DstProxyView&,
+                             GrXferBarrierFlags renderPassXferBarriers) override;
 
     void onPrepareDraws(Target*) override;
     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
@@ -179,7 +180,8 @@
                                      SkArenaAlloc* arena,
                                      const GrSurfaceProxyView* writeView,
                                      GrAppliedClip&& appliedClip,
-                                     const GrXferProcessor::DstProxyView& dstProxyView) {
+                                     const GrXferProcessor::DstProxyView& dstProxyView,
+                                     GrXferBarrierFlags renderPassXferBarriers) {
     fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps,
                                                                arena,
                                                                writeView,
@@ -188,6 +190,7 @@
                                                                &fGP,
                                                                std::move(fProcessorSet),
                                                                GrPrimitiveType::kTriangles,
+                                                               renderPassXferBarriers,
                                                                GrPipeline::InputFlags::kNone);
 }