Change UnrefDDLTask to just be the DDLTask (take 2)

This includes:

https://skia-review.googlesource.com/c/skia/+/333576 (Fix UMR (valgrind) bug in GrDrawingManager)

Change-Id: I162aba033e75b47a96b4dfdd840ba2cb1f70e42c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/334422
Reviewed-by: Adlai Holler <adlai@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkDeferredDisplayListPriv.h b/src/core/SkDeferredDisplayListPriv.h
index a8954c4..fc84970 100644
--- a/src/core/SkDeferredDisplayListPriv.h
+++ b/src/core/SkDeferredDisplayListPriv.h
@@ -33,6 +33,10 @@
     const SkTArray<GrRecordingContext::ProgramData>& programData() const {
         return fDDL->programData();
     }
+
+    const SkTArray<sk_sp<GrRenderTask>>& renderTasks() const {
+        return fDDL->fRenderTasks;
+    }
 #endif
 
 private:
diff --git a/src/gpu/GrDDLTask.cpp b/src/gpu/GrDDLTask.cpp
new file mode 100644
index 0000000..7f3bef2
--- /dev/null
+++ b/src/gpu/GrDDLTask.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/GrDDLTask.h"
+
+#include "include/core/SkDeferredDisplayList.h"
+#include "src/core/SkDeferredDisplayListPriv.h"
+#include "src/gpu/GrResourceAllocator.h"
+
+GrDDLTask::GrDDLTask(GrDrawingManager* drawingMgr,
+                     sk_sp<GrRenderTargetProxy> ddlTarget,
+                     sk_sp<const SkDeferredDisplayList> ddl)
+        : fDDL(std::move(ddl))
+        , fDDLTarget(std::move(ddlTarget)) {
+
+    for (const sk_sp<GrRenderTask>& task : fDDL->priv().renderTasks()) {
+        SkASSERT(task->isClosed());
+
+        for (int i = 0; i < task->numTargets(); ++i) {
+            drawingMgr->setLastRenderTask(task->target(i).proxy(), task.get());
+        }
+    }
+
+    // The DDL task never accepts additional tasks
+    this->setFlag(kClosed_Flag);
+}
+
+GrDDLTask::~GrDDLTask() { }
+
+void GrDDLTask::endFlush(GrDrawingManager* drawingManager) {
+    for (auto& task : fDDL->priv().renderTasks()) {
+        task->endFlush(drawingManager);
+    }
+
+    INHERITED::endFlush(drawingManager);
+}
+
+void GrDDLTask::disown(GrDrawingManager* drawingManager) {
+    for (auto& task : fDDL->priv().renderTasks()) {
+        task->disown(drawingManager);
+    }
+
+    INHERITED::disown(drawingManager);
+}
+
+bool GrDDLTask::onIsUsed(GrSurfaceProxy* proxy) const {
+    for (auto& task : fDDL->priv().renderTasks()) {
+        if (task->isUsed(proxy)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void GrDDLTask::handleInternalAllocationFailure() {
+    for (auto& task : fDDL->priv().renderTasks()) {
+        task->handleInternalAllocationFailure();
+    }
+}
+
+void GrDDLTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
+    // We don't have any proxies, but the resource allocator will still bark
+    // if a task doesn't claim any op indices, so we oblige it.
+    alloc->incOps();
+
+    for (auto& task : fDDL->priv().renderTasks()) {
+        task->gatherProxyIntervals(alloc);
+    }
+}
+
+GrRenderTask::ExpectedOutcome GrDDLTask::onMakeClosed(const GrCaps& caps,
+                                                      SkIRect* targetUpdateBounds) {
+    SkASSERT(0);
+    return ExpectedOutcome::kTargetUnchanged;
+}
+
+void GrDDLTask::gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const {
+    for (auto& task : fDDL->priv().renderTasks()) {
+        task->gatherIDs(idArray);
+    }
+}
+
+void GrDDLTask::onPrepare(GrOpFlushState* flushState) {
+    for (auto& task : fDDL->priv().renderTasks()) {
+        task->prepare(flushState);
+    }
+}
+
+bool GrDDLTask::onExecute(GrOpFlushState* flushState) {
+    bool anyCommandsIssued = false;
+    for (auto& task : fDDL->priv().renderTasks()) {
+        if (task->execute(flushState)) {
+            anyCommandsIssued = true;
+        }
+    }
+
+    return anyCommandsIssued;
+}
diff --git a/src/gpu/GrDDLTask.h b/src/gpu/GrDDLTask.h
new file mode 100644
index 0000000..3c129ac
--- /dev/null
+++ b/src/gpu/GrDDLTask.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDDLTask_DEFINED
+#define GrDDLTask_DEFINED
+
+#include "src/gpu/GrRenderTask.h"
+
+class GrRenderTargetProxy;
+
+/**
+ * This render task isolates the DDL's tasks from the rest of the DAG. This means that
+ * the DDL's tasks cannot be reordered by the topological sort and are always executed
+ * as a single block.
+ * It almost entirely just forwards calls down to the DDL's render tasks.
+ */
+class GrDDLTask final : public GrRenderTask {
+public:
+    GrDDLTask(GrDrawingManager*,
+              sk_sp<GrRenderTargetProxy> ddlTarget,
+              sk_sp<const SkDeferredDisplayList>);
+
+    ~GrDDLTask() override;
+
+    // The render tasks w/in the DDL don't appear in the DAG so need explicit notification
+    // when they can free their contents.
+    bool requiresExplicitCleanup() const override { return true; }
+
+    void endFlush(GrDrawingManager*) override;
+
+    void disown(GrDrawingManager*) override;
+
+private:
+    bool onIsUsed(GrSurfaceProxy* proxy) const override;
+
+    void handleInternalAllocationFailure() override;
+
+    void gatherProxyIntervals(GrResourceAllocator*) const override;
+
+    ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) override;
+
+    void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const override;
+
+    void onPrePrepare(GrRecordingContext*) override {
+        // This entry point is only called when a DDL is snapped off of a recorder.
+        // Since DDL tasks should never recursively appear within a DDL this should never
+        // be called.
+        SkASSERT(0);
+    }
+
+    void onPrepare(GrOpFlushState*) override;
+
+    bool onExecute(GrOpFlushState*) override;
+
+#if GR_TEST_UTILS
+    const char* name() const final { return "DDL"; }
+#endif
+#ifdef SK_DEBUG
+    void visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const override {}
+#endif
+
+    sk_sp<const SkDeferredDisplayList> fDDL;
+    sk_sp<GrRenderTargetProxy>         fDDLTarget;
+
+    typedef GrRenderTask INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrDirectContextPriv.cpp b/src/gpu/GrDirectContextPriv.cpp
index 1459461..5238e23 100644
--- a/src/gpu/GrDirectContextPriv.cpp
+++ b/src/gpu/GrDirectContextPriv.cpp
@@ -66,9 +66,9 @@
     return fContext->drawingManager()->flushSurfaces(proxies, access, info, newState);
 }
 
-void GrDirectContextPriv::copyRenderTasksFromDDL(sk_sp<const SkDeferredDisplayList> ddl,
-                                                 GrRenderTargetProxy* newDest) {
-    fContext->drawingManager()->copyRenderTasksFromDDL(std::move(ddl), newDest);
+void GrDirectContextPriv::createDDLTask(sk_sp<const SkDeferredDisplayList> ddl,
+                                        GrRenderTargetProxy* newDest) {
+    fContext->drawingManager()->createDDLTask(std::move(ddl), newDest);
 }
 
 bool GrDirectContextPriv::compile(const GrProgramDesc& desc, const GrProgramInfo& info) {
diff --git a/src/gpu/GrDirectContextPriv.h b/src/gpu/GrDirectContextPriv.h
index d96030e..5f52317 100644
--- a/src/gpu/GrDirectContextPriv.h
+++ b/src/gpu/GrDirectContextPriv.h
@@ -131,7 +131,7 @@
         return fContext->onGetSmallPathAtlasMgr();
     }
 
-    void copyRenderTasksFromDDL(sk_sp<const SkDeferredDisplayList>, GrRenderTargetProxy* newDest);
+    void createDDLTask(sk_sp<const SkDeferredDisplayList>, GrRenderTargetProxy* newDest);
 
     bool compile(const GrProgramDesc&, const GrProgramInfo&);
 
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 68b4690..5961715 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -19,6 +19,7 @@
 #include "src/gpu/GrAuditTrail.h"
 #include "src/gpu/GrClientMappedBufferManager.h"
 #include "src/gpu/GrCopyRenderTask.h"
+#include "src/gpu/GrDDLTask.h"
 #include "src/gpu/GrDirectContextPriv.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrMemoryPool.h"
@@ -38,7 +39,6 @@
 #include "src/gpu/GrTextureResolveRenderTask.h"
 #include "src/gpu/GrTracing.h"
 #include "src/gpu/GrTransferFromRenderTask.h"
-#include "src/gpu/GrUnrefDDLTask.h"
 #include "src/gpu/GrWaitRenderTask.h"
 #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
 #include "src/gpu/text/GrSDFTOptions.h"
@@ -149,10 +149,10 @@
 
     // Prepare any onFlush op lists (e.g. atlases).
     if (!fOnFlushCBObjects.empty()) {
-        fFlushingRenderTaskIDs.reset(fDAG.count());
-        for (int i = 0; i < fDAG.count(); i++) {
-            if (fDAG[i]) {
-                fFlushingRenderTaskIDs[i] = fDAG[i]->uniqueID();
+        fFlushingRenderTaskIDs.reserve_back(fDAG.count());
+        for (const auto& task : fDAG) {
+            if (task) {
+                task->gatherIDs(&fFlushingRenderTaskIDs);
             }
         }
 
@@ -376,8 +376,10 @@
         if (!task) {
             continue;
         }
-        if (!task->unique()) {
-            // TODO: Eventually this should be guaranteed unique: http://skbug.com/7111
+        if (!task->unique() || task->requiresExplicitCleanup()) {
+            // TODO: Eventually uniqueness should be guaranteed: http://skbug.com/7111.
+            // DDLs, however, will always require an explicit notification for when they
+            // can clean up resources.
             task->endFlush(this);
         }
         task->disown(this);
@@ -535,8 +537,8 @@
 
 void GrDrawingManager::setLastRenderTask(const GrSurfaceProxy* proxy, GrRenderTask* task) {
 #ifdef SK_DEBUG
-    if (GrRenderTask* prior = this->getLastRenderTask(proxy)) {
-        SkASSERT(prior->isClosed());
+    if (auto prior = this->getLastRenderTask(proxy)) {
+        SkASSERT(prior->isClosed() || prior == task);
     }
 #endif
     uint32_t key = proxy->uniqueID().asUInt();
@@ -565,6 +567,8 @@
     this->closeAllTasks();
     fActiveOpsTask = nullptr;
 
+    this->sortTasks();
+
     fDAG.swap(ddl->fRenderTasks);
     SkASSERT(fDAG.empty());
 
@@ -586,8 +590,8 @@
     SkDEBUGCODE(this->validate());
 }
 
-void GrDrawingManager::copyRenderTasksFromDDL(sk_sp<const SkDeferredDisplayList> ddl,
-                                              GrRenderTargetProxy* newDest) {
+void GrDrawingManager::createDDLTask(sk_sp<const SkDeferredDisplayList> ddl,
+                                     GrRenderTargetProxy* newDest) {
     SkDEBUGCODE(this->validate());
 
     if (fActiveOpsTask) {
@@ -599,7 +603,7 @@
         fActiveOpsTask = nullptr;
     }
 
-    // Propagate the DDL proxy's state information to the replaying DDL.
+    // Propagate the DDL proxy's state information to the replay target.
     if (ddl->priv().targetProxy()->isMSAADirty()) {
         newDest->markMSAADirty(ddl->priv().targetProxy()->msaaDirtyRect(),
                                ddl->characterization().origin());
@@ -612,7 +616,7 @@
     this->addDDLTarget(newDest, ddl->priv().targetProxy());
 
     // Here we jam the proxy that backs the current replay SkSurface into the LazyProxyData.
-    // The lazy proxy that references it (in the copied opsTasks) will steal its GrTexture.
+    // The lazy proxy that references it (in the DDL opsTasks) will then steal its GrTexture.
     ddl->fLazyProxyData->fReplayDest = newDest;
 
     if (ddl->fPendingPaths.size()) {
@@ -621,11 +625,11 @@
         ccpr->mergePendingPaths(ddl->fPendingPaths);
     }
 
-    this->appendTasks(ddl->fRenderTasks);
-
-    // Add a task to unref the DDL after flush.
-    GrRenderTask* unrefTask = this->appendTask(sk_make_sp<GrUnrefDDLTask>(std::move(ddl)));
-    unrefTask->makeClosed(*fContext->priv().caps());
+    // Add a task to handle drawing and lifetime management of the DDL.
+    SkDEBUGCODE(auto ddlTask =) this->appendTask(sk_make_sp<GrDDLTask>(this,
+                                                                       sk_ref_sp(newDest),
+                                                                       std::move(ddl)));
+    SkASSERT(ddlTask->isClosed());
 
     SkDEBUGCODE(this->validate());
 }
@@ -917,4 +921,3 @@
         resourceCache->purgeAsNeeded();
     }
 }
-
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 14cbb20..7281d2b 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -117,7 +117,7 @@
     void setLastRenderTask(const GrSurfaceProxy*, GrRenderTask*);
 
     void moveRenderTasksToDDL(SkDeferredDisplayList* ddl);
-    void copyRenderTasksFromDDL(sk_sp<const SkDeferredDisplayList>, GrRenderTargetProxy* newDest);
+    void createDDLTask(sk_sp<const SkDeferredDisplayList>, GrRenderTargetProxy* newDest);
 
 private:
     GrDrawingManager(GrRecordingContext*,
@@ -172,7 +172,8 @@
 
     SkTArray<sk_sp<GrRenderTask>>     fDAG;
     GrOpsTask*                        fActiveOpsTask = nullptr;
-    // These are the IDs of the opsTask currently being flushed (in internalFlush)
+    // These are the IDs of the opsTask currently being flushed (in internalFlush). They are
+    // only stored here to prevent memory thrashing.
     SkSTArray<8, uint32_t, true>      fFlushingRenderTaskIDs;
     // These are the new renderTasks generated by the onFlush CBs
     SkSTArray<4, sk_sp<GrRenderTask>> fOnFlushRenderTasks;
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index c6ca456..562bafb 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -875,8 +875,8 @@
     }
 }
 
-GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed(
-        const GrCaps& caps, SkIRect* targetUpdateBounds) {
+GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed(const GrCaps& caps,
+                                                      SkIRect* targetUpdateBounds) {
     this->forwardCombine(caps);
     if (!this->isNoOp()) {
         GrSurfaceProxy* proxy = this->target(0).proxy();
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index 2a0e915..460454a 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -257,19 +257,16 @@
 }
 
 bool GrRenderTask::isInstantiated() const {
-    // Some renderTasks (e.g. GrTransferFromRenderTask) don't have any targets.
-    if (0 == this->numTargets()) {
-        return true;
-    }
-    GrSurfaceProxy* proxy = this->target(0).proxy();
+    for (const GrSurfaceProxyView& target : fTargets) {
+        GrSurfaceProxy* proxy = target.proxy();
+        if (!proxy->isInstantiated()) {
+            return false;
+        }
 
-    if (!proxy->isInstantiated()) {
-        return false;
-    }
-
-    GrSurface* surface = proxy->peekSurface();
-    if (surface->wasDestroyed()) {
-        return false;
+        GrSurface* surface = proxy->peekSurface();
+        if (surface->wasDestroyed()) {
+            return false;
+        }
     }
 
     return true;
@@ -291,10 +288,9 @@
 
     if (!fTargets.empty()) {
         SkDebugf("Targets: \n");
-        for (int i = 0; i < fTargets.count(); ++i) {
-            GrSurfaceProxy* proxy = fTargets[i].proxy();
-            SkDebugf("[%d]: proxyID: %d - surfaceID: %d\n",
-                     i,
+        for (const GrSurfaceProxyView& target : fTargets) {
+            GrSurfaceProxy* proxy = target.proxy();
+            SkDebugf("proxyID: %d - surfaceID: %d\n",
                      proxy ? proxy->uniqueID().asUInt() : -1,
                      proxy && proxy->peekSurface()
                             ? proxy->peekSurface()->uniqueID().asUInt()
diff --git a/src/gpu/GrRenderTask.h b/src/gpu/GrRenderTask.h
index cdd3641..85ded83 100644
--- a/src/gpu/GrRenderTask.h
+++ b/src/gpu/GrRenderTask.h
@@ -37,6 +37,8 @@
     void prepare(GrOpFlushState* flushState);
     bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
 
+    virtual bool requiresExplicitCleanup() const { return false; }
+
     // Called when this class will survive a flush and needs to truncate its ops and start over.
     // TODO: ultimately it should be invalid for an op list to survive a flush.
     // https://bugs.chromium.org/p/skia/issues/detail?id=7111
@@ -66,8 +68,11 @@
      */
     bool dependsOn(const GrRenderTask* dependedOn) const;
 
+    virtual void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const {
+        idArray->push_back(fUniqueID);
+    }
     uint32_t uniqueID() const { return fUniqueID; }
-    int numTargets() const { return fTargets.count(); }
+    virtual int numTargets() const { return fTargets.count(); }
     const GrSurfaceProxyView& target(int i) const { return fTargets[i]; }
 
     /*
@@ -90,12 +95,22 @@
 
     void visitTargetAndSrcProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {
         this->visitProxies_debugOnly(fn);
-        for (int i = 0; i < this->numTargets(); ++i) {
-            fn(this->target(i).proxy(), GrMipmapped::kNo);
+       for (const GrSurfaceProxyView& target : fTargets) {
+            fn(target.proxy(), GrMipmapped::kNo);
         }
     }
 #endif
 
+    bool isUsed(GrSurfaceProxy* proxy) const {
+        for (const GrSurfaceProxyView& target : fTargets) {
+            if (target.proxy() == proxy) {
+                return true;
+            }
+        }
+
+        return this->onIsUsed(proxy);
+    }
+
 protected:
     // In addition to just the GrSurface being allocated, has the stencil buffer been allocated (if
     // it is required)?
@@ -129,6 +144,8 @@
 private:
     // for resetFlag, TopoSortTraits, gatherProxyIntervals, handleInternalAllocationFailure
     friend class GrDrawingManager;
+    friend class GrDDLTask; // for handleInternalAllocationFailure, gatherProxyIntervals, Flags
+
 
     // Drops any pending operations that reference proxies that are not instantiated.
     // NOTE: Derived classes don't need to check targets. That is handled when the
@@ -139,16 +156,6 @@
     // GrRenderTask itself will handle checking the target proxies.
     virtual bool onIsUsed(GrSurfaceProxy*) const = 0;
 
-    bool isUsed(GrSurfaceProxy* proxy) const {
-        for (const GrSurfaceProxyView& target : fTargets) {
-            if (target.proxy() == proxy) {
-                return true;
-            }
-        }
-
-        return this->onIsUsed(proxy);
-    }
-
     void addDependency(GrRenderTask* dependedOn);
     void addDependent(GrRenderTask* dependent);
     SkDEBUGCODE(bool isDependedent(const GrRenderTask* dependent) const;)
@@ -204,9 +211,9 @@
         }
     };
 
-    // Only the GrOpsTask currently overrides this virtual
-    virtual void onPrePrepare(GrRecordingContext*) {}
-    virtual void onPrepare(GrOpFlushState*) {} // Only the GrOpsTask overrides this virtual
+
+    virtual void onPrePrepare(GrRecordingContext*) {} // Only the GrOpsTask currently overrides this
+    virtual void onPrepare(GrOpFlushState*) {} // Only GrOpsTask and GrDDLTask override this virtual
     virtual bool onExecute(GrOpFlushState* flushState) = 0;
 
     const uint32_t         fUniqueID;
diff --git a/src/gpu/GrUnrefDDLTask.h b/src/gpu/GrUnrefDDLTask.h
deleted file mode 100644
index 41a6bba..0000000
--- a/src/gpu/GrUnrefDDLTask.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrUnrefDDLTask_DEFINED
-#define GrUnrefDDLTask_DEFINED
-
-#include "src/gpu/GrRenderTask.h"
-
-/** When a DDL is played back, the drawing manager refs the DDL and adds one
- *  of these to the DAG to release it after the flush. Thus the user is free
- *  to unref the DDL at their leisure without messing us up.
- */
-class GrUnrefDDLTask final : public GrRenderTask {
-public:
-    GrUnrefDDLTask(sk_sp<const SkDeferredDisplayList> ddl)
-            : GrRenderTask()
-            , fDDL(std::move(ddl)) {}
-
-    // We actually do the unreffing in dtor instead of onExecute, so that we maintain the invariant
-    // that DDLs are always the last owners of their render tasks (because those tasks depend on
-    // memory owned by the DDL.) If we had this in onExecute, the tasks would still be alive in
-    // the drawing manager although it would already have executed them.
-    ~GrUnrefDDLTask() override {
-        fDDL.reset();
-    }
-
-private:
-    bool onIsUsed(GrSurfaceProxy* proxy) const override { return false; }
-    void handleInternalAllocationFailure() override {}
-    void gatherProxyIntervals(GrResourceAllocator* alloc) const override {
-        // We don't have any proxies, but the resource allocator will still bark
-        // if a task doesn't claim any op indices, so we oblige it.
-        alloc->incOps();
-    }
-
-    ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
-        return ExpectedOutcome::kTargetUnchanged;
-    }
-
-    bool onExecute(GrOpFlushState*) override { return true; }
-
-#if GR_TEST_UTILS
-    const char* name() const final { return "UnrefDDL"; }
-#endif
-#ifdef SK_DEBUG
-    void visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const override {}
-#endif
-
-    sk_sp<const SkDeferredDisplayList> fDDL;
-};
-
-#endif
diff --git a/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp b/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp
index 40f1944..605b6b1 100644
--- a/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp
+++ b/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp
@@ -181,7 +181,7 @@
         return false;
     }
 
-    direct->priv().copyRenderTasksFromDDL(std::move(ddl), rtc->asRenderTargetProxy());
+    direct->priv().createDDLTask(std::move(ddl), rtc->asRenderTargetProxy());
     return true;
 }
 
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 22d82fd..8109b9f 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -382,7 +382,7 @@
         return false;
     }
 
-    direct->priv().copyRenderTasksFromDDL(std::move(ddl), rtc->asRenderTargetProxy());
+    direct->priv().createDDLTask(std::move(ddl), rtc->asRenderTargetProxy());
     return true;
 }