Revert "Do register allocation in GrResourceAllocator"

This reverts commit c6f78ff55dca3576ced1773b873565d574698958.

Reason for revert: Broke Chrome roll and MSAN

Original change's description:
> Do register allocation in GrResourceAllocator
>
> This lets us plan out the allocation of resources without
> actually committing to the resulting plan. In the future,
> the user will be able to do the register allocation, then
> query the estimated memory cost, and either commit to
> that allocation or try a different order of operations.
>
> Bug: skia:10877
> Change-Id: I34f92b01986dc2a0dd72e85d42283fc438c5fc82
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/386097
> Commit-Queue: Adlai Holler <adlai@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>

TBR=robertphillips@google.com,adlai@google.com

Change-Id: I7492c12b8188ed22c3cd80fd4068da402d8d3543
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:10877
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/386856
Reviewed-by: Adlai Holler <adlai@google.com>
Commit-Queue: Adlai Holler <adlai@google.com>
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 37733f0..67480ec 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -98,63 +98,10 @@
     fIntvlHash.set(proxyID, newIntvl);
 }
 
-bool GrResourceAllocator::Register::isRecyclable(const GrCaps& caps,
-                                                 GrSurfaceProxy* proxy,
-                                                 int knownUseCount) const {
-    if (!caps.reuseScratchTextures() && !proxy->asRenderTargetProxy()) {
-        // Tragically, scratch texture reuse is totally disabled in this case.
-        return false;
-    }
-
-    if (!this->scratchKey().isValid()) {
-        return false; // no scratch key, no free pool
-    }
-    if (this->uniqueKey().isValid()) {
-        return false; // rely on the resource cache to hold onto uniquely-keyed surfaces.
-    }
-    // If all the refs on the proxy are known to the resource allocator then no one
+bool GrResourceAllocator::Interval::isSurfaceRecyclable() const {
+    // All the refs on the proxy are known to the resource allocator thus no one
     // should be holding onto it outside of Ganesh.
-    return !proxy->refCntGreaterThan(knownUseCount);
-}
-
-bool GrResourceAllocator::Register::instantiateSurface(GrSurfaceProxy* proxy,
-                                                       GrResourceProvider* resourceProvider) {
-    SkASSERT(!proxy->peekSurface());
-
-    sk_sp<GrSurface> surface;
-    if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
-        SkASSERT(uniqueKey == fOriginatingProxy->getUniqueKey());
-        // First try to reattach to a cached surface if the proxy is uniquely keyed
-        surface = resourceProvider->findByUniqueKey<GrSurface>(uniqueKey);
-    }
-    if (!surface) {
-        if (proxy == fOriginatingProxy) {
-            surface = proxy->priv().createSurface(resourceProvider);
-        } else {
-            surface = sk_ref_sp(fOriginatingProxy->peekSurface());
-        }
-    }
-    if (!surface) {
-        return false;
-    }
-
-    // Make surface budgeted if this proxy is budgeted.
-    if (SkBudgeted::kYes == proxy->isBudgeted() &&
-        GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
-        // This gets the job done but isn't quite correct. It would be better to try to
-        // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
-        surface->resourcePriv().makeBudgeted();
-    }
-
-    // Propagate the proxy unique key to the surface if we have one.
-    if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
-        if (!surface->getUniqueKey().isValid()) {
-            resourceProvider->assignUniqueKeyToResource(uniqueKey, surface.get());
-        }
-        SkASSERT(surface->getUniqueKey() == uniqueKey);
-    }
-    proxy->priv().assign(std::move(surface));
-    return true;
+    return !fProxy->refCntGreaterThan(fUses);
 }
 
 GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
@@ -247,49 +194,78 @@
 }
 #endif
 
+// 'surface' can be reused. Add it back to the free pool.
+void GrResourceAllocator::recycleRegister(Register* r) {
+    const GrScratchKey &key = r->scratchKey();
+
+    if (!key.isValid()) {
+        return; // can't do it w/o a valid scratch key
+    }
+
+    GrSurface* surface = r->surface();
+    if (surface->getUniqueKey().isValid()) {
+        // If the surface has a unique key we throw it back into the resource cache.
+        // If things get really tight 'findRegisterFor' may pull it back out but there is
+        // no need to have it in tight rotation.
+        return;
+    }
+
+#if GR_ALLOCATION_SPEW
+    SkDebugf("putting register %d back into pool\n", r->uniqueID());
+#endif
+    // TODO: fix this insertion so we get a more LRU-ish behavior
+    fFreePool.insert(key, r);
+}
+
 // First try to reuse one of the recently allocated/used registers in the free pool.
-GrResourceAllocator::Register* GrResourceAllocator::findOrCreateRegisterFor(GrSurfaceProxy* proxy) {
-    // Handle uniquely keyed proxies
+// If we can't find a usable one, try to instantiate a surface and wrap it in a new one.
+GrResourceAllocator::Register* GrResourceAllocator::findRegisterFor(const GrSurfaceProxy* proxy) {
     if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
-        if (auto p = fUniqueKeyRegisters.find(uniqueKey)) {
-            return *p;
+        // First try to reattach to a cached surface if the proxy is uniquely keyed
+        if (sk_sp<GrSurface> surface = fResourceProvider->findByUniqueKey<GrSurface>(uniqueKey)) {
+            // TODO: Find the register if we've encountered this unique key before.
+            return fInternalAllocator.make<Register>(std::move(surface));
         }
-        // No need for a scratch key. These don't go in the free pool.
-        Register* r = fInternalAllocator.make<Register>(proxy, GrScratchKey());
-        fUniqueKeyRegisters.set(uniqueKey, r);
-        return r;
     }
 
     // Then look in the free pool
-    GrScratchKey scratchKey;
-    proxy->priv().computeScratchKey(*fResourceProvider->caps(), &scratchKey);
+    GrScratchKey key;
+
+    proxy->priv().computeScratchKey(*fResourceProvider->caps(), &key);
 
     auto filter = [] (const Register* r) {
         return true;
     };
-    if (Register* r = fFreePool.findAndRemove(scratchKey, filter)) {
+    if (Register* r = fFreePool.findAndRemove(key, filter)) {
+        GrSurface* surface = r->surface();
+        if (SkBudgeted::kYes == proxy->isBudgeted() &&
+            GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
+            // This gets the job done but isn't quite correct. It would be better to try to
+            // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
+            surface->resourcePriv().makeBudgeted();
+        }
+        SkASSERT(!surface->getUniqueKey().isValid());
         return r;
     }
 
-    return fInternalAllocator.make<Register>(proxy, std::move(scratchKey));
+    if (sk_sp<GrSurface> surf = proxy->priv().createSurface(fResourceProvider)) {
+        return fInternalAllocator.make<Register>(std::move(surf));
+    }
+    return nullptr;
 }
 
-// Remove any intervals that end before the current index. Add their registers
+// Remove any intervals that end before the current index. Return their GrSurfaces
 // to the free pool if possible.
 void GrResourceAllocator::expire(unsigned int curIndex) {
     while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->end() < curIndex) {
         Interval* intvl = fActiveIntvls.popHead();
         SkASSERT(!intvl->next());
 
-        Register* r = intvl->getRegister();
-        if (r && r->isRecyclable(*fResourceProvider->caps(), intvl->proxy(), intvl->uses())) {
-#if GR_ALLOCATION_SPEW
-            SkDebugf("putting register %d back into pool\n", r->uniqueID());
-#endif
-            // TODO: fix this insertion so we get a more LRU-ish behavior
-            fFreePool.insert(r->scratchKey(), r);
+        if (Register* r = intvl->getRegister()) {
+            if (intvl->isSurfaceRecyclable()) {
+                this->recycleRegister(r);
+            }
         }
-        fFinishedIntvls.insertByIncreasingEnd(intvl);
     }
 }
 
@@ -310,48 +286,47 @@
     while (Interval* cur = fIntvlList.popHead()) {
         this->expire(cur->start());
 
-        // Already-instantiated proxies and lazy proxies don't use registers.
-        // No need to compute scratch keys (or CANT, in the case of fully-lazy).
-        if (cur->proxy()->isInstantiated() || cur->proxy()->isLazy()) {
+        if (cur->proxy()->isInstantiated()) {
             fActiveIntvls.insertByIncreasingEnd(cur);
 
             continue;
         }
 
-        Register* r = this->findOrCreateRegisterFor(cur->proxy());
+        if (cur->proxy()->isLazy()) {
+            if (!cur->proxy()->priv().doLazyInstantiation(fResourceProvider)) {
+                fFailedInstantiation = true;
+            }
+        } else if (Register* r = this->findRegisterFor(cur->proxy())) {
+            sk_sp<GrSurface> surface = r->refSurface();
+
+            // propagate the proxy unique key to the surface if we have one.
+            if (const auto& uniqueKey = cur->proxy()->getUniqueKey(); uniqueKey.isValid()) {
+                if (!surface->getUniqueKey().isValid()) {
+                    fResourceProvider->assignUniqueKeyToResource(uniqueKey, surface.get());
+                }
+                SkASSERT(surface->getUniqueKey() == uniqueKey);
+            }
+
 #if GR_ALLOCATION_SPEW
-        SkDebugf("Assigning register %d to %d\n",
-             r->uniqueID(),
-             cur->proxy()->uniqueID().asUInt());
+            SkDebugf("Assigning %d to %d\n",
+                 surface->uniqueID().asUInt(),
+                 cur->proxy()->uniqueID().asUInt());
 #endif
-        SkASSERT(!cur->proxy()->peekSurface());
-        cur->setRegister(r);
+
+            SkASSERT(!cur->proxy()->peekSurface());
+            cur->setRegister(r);
+            // TODO: surface creation and assignment should happen later
+            cur->proxy()->priv().assign(std::move(surface));
+        } else {
+            SkASSERT(!cur->proxy()->isInstantiated());
+            fFailedInstantiation = true;
+        }
 
         fActiveIntvls.insertByIncreasingEnd(cur);
     }
 
     // expire all the remaining intervals to drain the active interval list
     this->expire(std::numeric_limits<unsigned int>::max());
-
-    // TODO: Return here and give the caller a chance to estimate memory cost and bail before
-    // instantiating anything.
-
-    // Instantiate surfaces
-    while (Interval* cur = fFinishedIntvls.popHead()) {
-        if (fFailedInstantiation) {
-            break;
-        }
-        if (cur->proxy()->isInstantiated()) {
-            continue;
-        }
-        if (cur->proxy()->isLazy()) {
-            fFailedInstantiation = !cur->proxy()->priv().doLazyInstantiation(fResourceProvider);
-            continue;
-        }
-        Register* r = cur->getRegister();
-        SkASSERT(r);
-        fFailedInstantiation = !r->instantiateSurface(cur->proxy(), fResourceProvider);
-    }
     return !fFailedInstantiation;
 }