Skip flush in GrDrawingManager if the specifed proxy doesn't have any work (take 2)

This is rather ham-fisted but I would like to have a short-term fix for the "always-flush" perf regressions.

Change-Id: I508e2d725ac18f50318baf31bc3243fe932c724b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206697
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/private/GrOpList.h b/include/private/GrOpList.h
index d795be8..72ef07e 100644
--- a/include/private/GrOpList.h
+++ b/include/private/GrOpList.h
@@ -113,6 +113,16 @@
 private:
     friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals
 
+    virtual bool onIsUsed(GrSurfaceProxy*) const = 0;
+
+    bool isUsed(GrSurfaceProxy* proxy) const {
+        if (proxy == fTarget.get()) {
+            return true;
+        }
+
+        return this->onIsUsed(proxy);
+    }
+
     void addDependency(GrOpList* dependedOn);
     void addDependent(GrOpList* dependent);
     SkDEBUGCODE(bool isDependedent(const GrOpList* dependent) const;)
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 149b112..897c473 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -72,6 +72,16 @@
     }
 }
 
+bool GrDrawingManager::OpListDAG::isUsed(GrSurfaceProxy* proxy) const {
+    for (int i = 0; i < fOpLists.count(); ++i) {
+        if (fOpLists[i] && fOpLists[i]->isUsed(proxy)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 void GrDrawingManager::OpListDAG::add(sk_sp<GrOpList> opList) {
     fOpLists.emplace_back(std::move(opList));
 }
@@ -209,6 +219,10 @@
 
     SkDEBUGCODE(this->validate());
 
+    if (SkSurface::kNone_FlushFlags == flags && !numSemaphores && proxy && !fDAG.isUsed(proxy)) {
+        return GrSemaphoresSubmitted::kNo;
+    }
+
     auto direct = fContext->priv().asDirectContext();
     if (!direct) {
         return GrSemaphoresSubmitted::kNo; // Can't flush while DDL recording
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 3f2245e..157a6c6 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -118,6 +118,8 @@
         bool empty() const { return fOpLists.empty(); }
         int numOpLists() const { return fOpLists.count(); }
 
+        bool isUsed(GrSurfaceProxy*) const;
+
         GrOpList* opList(int index) { return fOpLists[index].get(); }
         const GrOpList* opList(int index) const { return fOpLists[index].get(); }
 
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index f33755d..d2c47ac 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -130,9 +130,10 @@
     sk_sp<GrTexture> tex;
 
     if (SkBackingFit::kApprox == fit) {
-        tex = resourceProvider->createApproxTexture(desc, GrResourceProvider::Flags::kNone);
+        tex = resourceProvider->createApproxTexture(desc, GrResourceProvider::Flags::kNoPendingIO);
     } else {
-        tex = resourceProvider->createTexture(desc, budgeted, GrResourceProvider::Flags::kNone);
+        tex = resourceProvider->createTexture(desc, budgeted,
+                                              GrResourceProvider::Flags::kNoPendingIO);
     }
     if (!tex) {
         return nullptr;
@@ -244,6 +245,9 @@
             surfaceFlags |= GrInternalSurfaceFlags::kMixedSampled;
         }
     }
+    if (fImageContext->priv().explicitlyAllocateGPUResources()) {
+        surfaceFlags |= GrInternalSurfaceFlags::kNoPendingIO;
+    }
 
     GrSurfaceDesc desc;
     desc.fWidth = srcImage->width();
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 66300df..f66fec9 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -610,6 +610,21 @@
     }
 }
 
+bool GrRenderTargetOpList::onIsUsed(GrSurfaceProxy* proxyToCheck) const {
+    bool used = false;
+
+    auto visit = [ proxyToCheck, &used ] (GrSurfaceProxy* p) {
+        if (p == proxyToCheck) {
+            used = true;
+        }
+    };
+    for (const OpChain& recordedOp : fOpChains) {
+        recordedOp.visitProxies(visit, GrOp::VisitorType::kOther);
+    }
+
+    return used;
+}
+
 void GrRenderTargetOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
 
     for (int i = 0; i < fDeferredProxies.count(); ++i) {
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index 7faae2a..44cc39f 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -126,6 +126,8 @@
     // however, requires that the RTC be able to coordinate with the op list to achieve similar ends
     friend class GrRenderTargetContext;
 
+    bool onIsUsed(GrSurfaceProxy*) const override;
+
     // Must only be called if native stencil buffer clearing is enabled
     void setStencilLoadOp(GrLoadOp op);
     // Must only be called if native color buffer clearing is enabled.
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index 2d93f77..1b18c09 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -180,6 +180,24 @@
     }
 }
 
+bool GrTextureOpList::onIsUsed(GrSurfaceProxy* proxyToCheck) const {
+    bool used = false;
+
+    auto visit = [ proxyToCheck, &used ] (GrSurfaceProxy* p) {
+        if (p == proxyToCheck) {
+            used = true;
+        }
+    };
+    for (int i = 0; i < fRecordedOps.count(); ++i) {
+        const GrOp* op = fRecordedOps[i].get();
+        if (op) {
+            op->visitProxies(visit, GrOp::VisitorType::kOther);
+        }
+    }
+
+    return used;
+}
+
 void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
 
     // Add the interval for all the writes to this opList's target
diff --git a/src/gpu/GrTextureOpList.h b/src/gpu/GrTextureOpList.h
index 133fb2d..839b863 100644
--- a/src/gpu/GrTextureOpList.h
+++ b/src/gpu/GrTextureOpList.h
@@ -59,6 +59,8 @@
     SkDEBUGCODE(void dump(bool printDependencies) const override;)
 
 private:
+    bool onIsUsed(GrSurfaceProxy*) const override;
+
     void deleteOp(int index);
     void deleteOps();
 
diff --git a/src/gpu/ccpr/GrCCAtlas.cpp b/src/gpu/ccpr/GrCCAtlas.cpp
index 82b06f0..417bf96 100644
--- a/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/src/gpu/ccpr/GrCCAtlas.cpp
@@ -91,7 +91,8 @@
                         desc.fWidth = fWidth;
                         desc.fHeight = fHeight;
                         desc.fConfig = pixelConfig;
-                        fBackingTexture = resourceProvider->createTexture(desc, SkBudgeted::kYes);
+                        fBackingTexture = resourceProvider->createTexture(
+                            desc, SkBudgeted::kYes, GrResourceProvider::Flags::kNoPendingIO);
                     }
                     return GrSurfaceProxy::LazyInstantiationResult(fBackingTexture);
             },
diff --git a/tests/BlendTest.cpp b/tests/BlendTest.cpp
index 0dd5506..8e52c25 100644
--- a/tests/BlendTest.cpp
+++ b/tests/BlendTest.cpp
@@ -99,7 +99,8 @@
 
     auto resourceProvider = context->priv().resourceProvider();
 
-    *backingSurface = resourceProvider->createTexture(backingDesc, SkBudgeted::kNo);
+    *backingSurface = resourceProvider->createTexture(backingDesc, SkBudgeted::kNo,
+                                                      GrResourceProvider::Flags::kNoPendingIO);
     if (!(*backingSurface)) {
         return nullptr;
     }
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 7c0d3a8..d85b6f1 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -33,7 +33,8 @@
     desc.fHeight = 256;
     desc.fConfig = kRGBA_8888_GrPixelConfig;
     desc.fSampleCnt = 1;
-    sk_sp<GrSurface> texRT1 = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+    sk_sp<GrSurface> texRT1 = resourceProvider->createTexture(
+        desc, SkBudgeted::kNo, GrResourceProvider::Flags::kNoPendingIO);
 
     REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asRenderTarget());
     REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asTexture());
@@ -45,7 +46,8 @@
                     static_cast<GrSurface*>(texRT1->asTexture()));
 
     desc.fFlags = kNone_GrSurfaceFlags;
-    sk_sp<GrTexture> tex1 = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+    sk_sp<GrTexture> tex1 = resourceProvider->createTexture(
+        desc, SkBudgeted::kNo, GrResourceProvider::Flags::kNoPendingIO);
     REPORTER_ASSERT(reporter, nullptr == tex1->asRenderTarget());
     REPORTER_ASSERT(reporter, tex1.get() == tex1->asTexture());
     REPORTER_ASSERT(reporter, static_cast<GrSurface*>(tex1.get()) == tex1->asTexture());
@@ -114,7 +116,8 @@
             desc.fConfig = config;
             desc.fSampleCnt = 1;
 
-            sk_sp<GrSurface> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+            sk_sp<GrSurface> tex = resourceProvider->createTexture(
+                desc, SkBudgeted::kNo, GrResourceProvider::Flags::kNoPendingIO);
             bool ict = caps->isConfigTexturable(desc.fConfig);
             REPORTER_ASSERT(reporter, SkToBool(tex) == ict,
                             "config:%d, tex:%d, isConfigTexturable:%d", config, SkToBool(tex), ict);
@@ -131,14 +134,16 @@
                              caps->mipMapSupport()));
 
             desc.fFlags = kRenderTarget_GrSurfaceFlag;
-            tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+            tex = resourceProvider->createTexture(desc, SkBudgeted::kNo,
+                                                  GrResourceProvider::Flags::kNoPendingIO);
             bool isRenderable = caps->isConfigRenderable(config);
             REPORTER_ASSERT(reporter, SkToBool(tex) == isRenderable,
                             "config:%d, tex:%d, isRenderable:%d", config, SkToBool(tex),
                             isRenderable);
 
             desc.fSampleCnt = 2;
-            tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+            tex = resourceProvider->createTexture(desc, SkBudgeted::kNo,
+                                                  GrResourceProvider::Flags::kNoPendingIO);
             isRenderable = SkToBool(caps->getRenderTargetSampleCount(2, config));
             REPORTER_ASSERT(reporter, SkToBool(tex) == isRenderable,
                             "config:%d, tex:%d, isRenderable:%d", config, SkToBool(tex),
@@ -371,7 +376,8 @@
     desc.fConfig = kRGBA_8888_GrPixelConfig;
     desc.fWidth = desc.fHeight = 10;
     desc.fFlags = renderable ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
-    return context->priv().resourceProvider()->createTexture(desc, SkBudgeted::kNo);
+    return context->priv().resourceProvider()->createTexture(
+        desc, SkBudgeted::kNo, GrResourceProvider::Flags::kNoPendingIO);
 }
 
 DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
diff --git a/tests/LazyProxyTest.cpp b/tests/LazyProxyTest.cpp
index 1bb1151..6dcfb2b 100644
--- a/tests/LazyProxyTest.cpp
+++ b/tests/LazyProxyTest.cpp
@@ -95,7 +95,8 @@
                             desc.fWidth = 1234;
                             desc.fHeight = 567;
                             desc.fConfig = kRGB_565_GrPixelConfig;
-                            sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes);
+                            sk_sp<GrTexture> texture = rp->createTexture(
+                                desc, SkBudgeted::kYes, GrResourceProvider::Flags::kNoPendingIO);
                             REPORTER_ASSERT(fTest->fReporter, texture);
                             return std::move(texture);
                         }
@@ -337,7 +338,8 @@
                         *testExecuteValue = 1;
                         return {};
                     }
-                    return {rp->createTexture(desc, SkBudgeted::kNo),
+                    return {rp->createTexture(desc, SkBudgeted::kNo,
+                                              GrResourceProvider::Flags::kNoPendingIO),
                             GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
                 },
                 format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
diff --git a/tests/PromiseImageTest.cpp b/tests/PromiseImageTest.cpp
index b409e88..89bcefa 100644
--- a/tests/PromiseImageTest.cpp
+++ b/tests/PromiseImageTest.cpp
@@ -420,7 +420,8 @@
         GrSurfaceDesc desc;
         desc.fConfig = kRGBA_8888_GrPixelConfig;
         desc.fWidth = desc.fHeight = 100;
-        textures[i] = ctx->priv().resourceProvider()->createTexture(desc, SkBudgeted::kYes);
+        textures[i] = ctx->priv().resourceProvider()->createTexture(
+            desc, SkBudgeted::kYes, GrResourceProvider::Flags::kNoPendingIO);
         REPORTER_ASSERT(reporter, textures[i]);
     }
 
diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp
index d8bd651..c65d221 100644
--- a/tests/ProxyTest.cpp
+++ b/tests/ProxyTest.cpp
@@ -143,7 +143,8 @@
                                     tex = resourceProvider->createApproxTexture(
                                             desc, GrResourceProvider::Flags::kNoPendingIO);
                                 } else {
-                                    tex = resourceProvider->createTexture(desc, budgeted);
+                                    tex = resourceProvider->createTexture(
+                                        desc, budgeted, GrResourceProvider::Flags::kNoPendingIO);
                                 }
 
                                 sk_sp<GrTextureProxy> proxy =
@@ -176,9 +177,10 @@
                                 sk_sp<GrTexture> tex;
                                 if (SkBackingFit::kApprox == fit) {
                                     tex = resourceProvider->createApproxTexture(
-                                            desc, GrResourceProvider::Flags::kNone);
+                                            desc, GrResourceProvider::Flags::kNoPendingIO);
                                 } else {
-                                    tex = resourceProvider->createTexture(desc, budgeted);
+                                    tex = resourceProvider->createTexture(
+                                        desc, budgeted, GrResourceProvider::Flags::kNoPendingIO);
                                 }
 
                                 sk_sp<GrTextureProxy> proxy(
diff --git a/tests/ResourceAllocatorTest.cpp b/tests/ResourceAllocatorTest.cpp
index 2e107a1..ce6b731 100644
--- a/tests/ResourceAllocatorTest.cpp
+++ b/tests/ResourceAllocatorTest.cpp
@@ -317,9 +317,11 @@
     auto callback = [fit, desc](GrResourceProvider* resourceProvider) {
         sk_sp<GrTexture> texture;
         if (fit == SkBackingFit::kApprox) {
-            texture = resourceProvider->createApproxTexture(desc, GrResourceProvider::Flags::kNone);
+            texture = resourceProvider->createApproxTexture(
+                desc, GrResourceProvider::Flags::kNoPendingIO);
         } else {
-            texture = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+            texture = resourceProvider->createTexture(desc, SkBudgeted::kNo,
+                                                      GrResourceProvider::Flags::kNoPendingIO);
         }
         return GrSurfaceProxy::LazyInstantiationResult(std::move(texture));
     };
@@ -335,45 +337,43 @@
     GrContext* context = ctxInfo.grContext();
     GrResourceProvider* resourceProvider = ctxInfo.grContext()->priv().resourceProvider();
     GrResourceCache* resourceCache = ctxInfo.grContext()->priv().getResourceCache();
-    for (auto explicitlyAllocating : {false, true}) {
-        resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(explicitlyAllocating);
-        ProxyParams texParams;
-        texParams.fFit = SkBackingFit::kExact;
-        texParams.fOrigin = kTopLeft_GrSurfaceOrigin;
-        texParams.fColorType = kRGBA_8888_SkColorType;
-        texParams.fIsRT = false;
-        texParams.fSampleCnt = 1;
-        texParams.fSize = 100;
-        texParams.fBudgeted = SkBudgeted::kNo;
-        ProxyParams rtParams = texParams;
-        rtParams.fIsRT = true;
-        auto proxyProvider = context->priv().proxyProvider();
-        auto caps = context->priv().caps();
-        auto p0 = make_lazy(proxyProvider, caps, texParams, true);
-        auto p1 = make_lazy(proxyProvider, caps, texParams, false);
-        texParams.fFit = rtParams.fFit = SkBackingFit::kApprox;
-        auto p2 = make_lazy(proxyProvider, caps, rtParams, true);
-        auto p3 = make_lazy(proxyProvider, caps, rtParams, false);
+    resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(true);
+    ProxyParams texParams;
+    texParams.fFit = SkBackingFit::kExact;
+    texParams.fOrigin = kTopLeft_GrSurfaceOrigin;
+    texParams.fColorType = kRGBA_8888_SkColorType;
+    texParams.fIsRT = false;
+    texParams.fSampleCnt = 1;
+    texParams.fSize = 100;
+    texParams.fBudgeted = SkBudgeted::kNo;
+    ProxyParams rtParams = texParams;
+    rtParams.fIsRT = true;
+    auto proxyProvider = context->priv().proxyProvider();
+    auto caps = context->priv().caps();
+    auto p0 = make_lazy(proxyProvider, caps, texParams, true);
+    auto p1 = make_lazy(proxyProvider, caps, texParams, false);
+    texParams.fFit = rtParams.fFit = SkBackingFit::kApprox;
+    auto p2 = make_lazy(proxyProvider, caps, rtParams, true);
+    auto p3 = make_lazy(proxyProvider, caps, rtParams, false);
 
-        GrDeinstantiateProxyTracker deinstantiateTracker(resourceCache);
-        {
-            GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker SkDEBUGCODE(, 1));
-            alloc.addInterval(p0.get(), 0, 1);
-            alloc.addInterval(p1.get(), 0, 1);
-            alloc.addInterval(p2.get(), 0, 1);
-            alloc.addInterval(p3.get(), 0, 1);
-            alloc.incOps();
-            alloc.markEndOfOpList(0);
-            int startIndex, stopIndex;
-            GrResourceAllocator::AssignError error;
-            alloc.assign(&startIndex, &stopIndex, &error);
-        }
-        deinstantiateTracker.deinstantiateAllProxies();
-        REPORTER_ASSERT(reporter, !p0->isInstantiated());
-        REPORTER_ASSERT(reporter, p1->isInstantiated());
-        REPORTER_ASSERT(reporter, !p2->isInstantiated());
-        REPORTER_ASSERT(reporter, p3->isInstantiated());
+    GrDeinstantiateProxyTracker deinstantiateTracker(resourceCache);
+    {
+        GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker SkDEBUGCODE(, 1));
+        alloc.addInterval(p0.get(), 0, 1);
+        alloc.addInterval(p1.get(), 0, 1);
+        alloc.addInterval(p2.get(), 0, 1);
+        alloc.addInterval(p3.get(), 0, 1);
+        alloc.incOps();
+        alloc.markEndOfOpList(0);
+        int startIndex, stopIndex;
+        GrResourceAllocator::AssignError error;
+        alloc.assign(&startIndex, &stopIndex, &error);
     }
+    deinstantiateTracker.deinstantiateAllProxies();
+    REPORTER_ASSERT(reporter, !p0->isInstantiated());
+    REPORTER_ASSERT(reporter, p1->isInstantiated());
+    REPORTER_ASSERT(reporter, !p2->isInstantiated());
+    REPORTER_ASSERT(reporter, p3->isInstantiated());
 }
 
 // Set up so there are two opLists that need to be flushed but the resource allocator thinks
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 292300c..747bf2c 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -103,7 +103,8 @@
     desc.fConfig = kRGBA_8888_GrPixelConfig;
     desc.fSampleCnt = sampleCount;
 
-    sk_sp<GrTexture> tex(provider->createTexture(desc, budgeted));
+    sk_sp<GrTexture> tex(provider->createTexture(desc, budgeted,
+                                                 GrResourceProvider::Flags::kNoPendingIO));
     if (!tex || !tex->asRenderTarget()) {
         return nullptr;
     }
@@ -1624,7 +1625,8 @@
     desc.fConfig = kRGBA_8888_GrPixelConfig;
     desc.fSampleCnt = sampleCnt;
 
-    return provider->createTexture(desc, SkBudgeted::kYes);
+    return provider->createTexture(desc, SkBudgeted::kYes,
+                                   GrResourceProvider::Flags::kNoPendingIO);
 }
 
 static sk_sp<GrTextureProxy> make_mipmap_proxy(GrProxyProvider* proxyProvider,
diff --git a/tests/TextureProxyTest.cpp b/tests/TextureProxyTest.cpp
index 11e4f29..f26dbb7 100644
--- a/tests/TextureProxyTest.cpp
+++ b/tests/TextureProxyTest.cpp
@@ -105,7 +105,8 @@
 
     const GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
 
-    *backingSurface = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+    *backingSurface = resourceProvider->createTexture(desc, SkBudgeted::kNo,
+                                                      GrResourceProvider::Flags::kNoPendingIO);
     if (!(*backingSurface)) {
         return nullptr;
     }
diff --git a/tests/TransferPixelsTest.cpp b/tests/TransferPixelsTest.cpp
index 0db85bb..9ce9f30 100644
--- a/tests/TransferPixelsTest.cpp
+++ b/tests/TransferPixelsTest.cpp
@@ -117,7 +117,8 @@
             continue;
         }
 
-        sk_sp<GrTexture> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
+        sk_sp<GrTexture> tex = resourceProvider->createTexture(
+            desc, SkBudgeted::kNo, GrResourceProvider::Flags::kNoPendingIO);
         if (!tex) {
             continue;
         }