From 4684f82ebca85d4c7043e5c1028e34cf5631da32 Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Thu, 8 Mar 2018 15:27:36 -0500 Subject: Add ability to uninstantiate lazy proxies after every flush. Bug: skia: Change-Id: Id32540cda54a9c5e3e6cb721776699be3cc8ac1a Reviewed-on: https://skia-review.googlesource.com/113263 Commit-Queue: Greg Daniel Reviewed-by: Brian Salomon Reviewed-by: Robert Phillips --- src/gpu/GrDrawingManager.cpp | 5 ++++- src/gpu/GrOnFlushResourceProvider.cpp | 2 ++ src/gpu/GrOpFlushState.h | 8 ++++++++ src/gpu/GrResourceAllocator.cpp | 10 +++++++++- src/gpu/GrResourceAllocator.h | 4 +++- src/gpu/GrSurfaceProxyPriv.h | 6 ++++++ src/gpu/GrUninstantiateProxyTracker.cpp | 30 ++++++++++++++++++++++++++++++ src/gpu/GrUninstantiateProxyTracker.h | 30 ++++++++++++++++++++++++++++++ src/gpu/mock/GrMockGpu.cpp | 16 ++++++++++++++++ src/gpu/mock/GrMockGpu.h | 4 +--- src/gpu/mock/GrMockTexture.h | 25 +++++++++++++++++++++++++ 11 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 src/gpu/GrUninstantiateProxyTracker.cpp create mode 100644 src/gpu/GrUninstantiateProxyTracker.h (limited to 'src') diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index 62db98edd4..63d1175930 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -214,7 +214,8 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*, } GrResourceAllocator::AssignError error = GrResourceAllocator::AssignError::kNoError; - while (alloc.assign(&startIndex, &stopIndex, &error)) { + while (alloc.assign(&startIndex, &stopIndex, flushState.uninstantiateProxyTracker(), + &error)) { if (GrResourceAllocator::AssignError::kFailedProxyInstantiation == error) { for (int i = startIndex; i < stopIndex; ++i) { fOpLists[i]->purgeOpsWithUninstantiatedProxies(); @@ -231,6 +232,8 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*, GrSemaphoresSubmitted result = gpu->finishFlush(numSemaphores, backendSemaphores); + flushState.uninstantiateProxyTracker()->uninstantiateAllProxies(); + // We always have to notify the cache when it requested a flush so it can reset its state. if (flushed || type == GrResourceCache::FlushType::kCacheRequested) { fContext->contextPriv().getResourceCache()->notifyFlushOccurred(type); diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp index 9abd3f63b2..c33bc514da 100644 --- a/src/gpu/GrOnFlushResourceProvider.cpp +++ b/src/gpu/GrOnFlushResourceProvider.cpp @@ -85,6 +85,8 @@ bool GrOnFlushResourceProvider::instatiateProxy(GrSurfaceProxy* proxy) { auto resourceProvider = fDrawingMgr->getContext()->contextPriv().resourceProvider(); if (GrSurfaceProxy::LazyState::kNot != proxy->lazyInstantiationState()) { + // DDL TODO: Decide if we ever plan to have these proxies use the GrUninstantiateTracker + // to support unistantiating them at the end of a flush. return proxy->priv().doLazyInstantiation(resourceProvider); } diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h index 4f210a83d2..a6f0c26e5e 100644 --- a/src/gpu/GrOpFlushState.h +++ b/src/gpu/GrOpFlushState.h @@ -12,6 +12,7 @@ #include "GrAppliedClip.h" #include "GrBufferAllocPool.h" #include "GrDeferredUpload.h" +#include "GrUninstantiateProxyTracker.h" #include "SkArenaAlloc.h" #include "SkArenaAllocList.h" #include "ops/GrMeshDrawOp.h" @@ -96,6 +97,10 @@ public: // permissible). GrAtlasManager* atlasManager() const final; + GrUninstantiateProxyTracker* uninstantiateProxyTracker() { + return &fUninstantiateProxyTracker; + } + private: /** GrMeshDrawOp::Target override. */ SkArenaAlloc* pipelineArena() override { return &fArena; } @@ -150,6 +155,9 @@ private: SkArenaAllocList::Iter fCurrDraw; int fCurrMesh; SkArenaAllocList::Iter fCurrUpload; + + // Used to track the proxies that need to be uninstantiated after we finish a flush + GrUninstantiateProxyTracker fUninstantiateProxyTracker; }; #endif diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp index f41169c110..d3895073aa 100644 --- a/src/gpu/GrResourceAllocator.cpp +++ b/src/gpu/GrResourceAllocator.cpp @@ -16,6 +16,7 @@ #include "GrSurfaceProxy.h" #include "GrSurfaceProxyPriv.h" #include "GrTextureProxy.h" +#include "GrUninstantiateProxyTracker.h" void GrResourceAllocator::Interval::assign(sk_sp s) { SkASSERT(!fAssignedSurface); @@ -200,7 +201,9 @@ void GrResourceAllocator::expire(unsigned int curIndex) { } } -bool GrResourceAllocator::assign(int* startIndex, int* stopIndex, AssignError* outError) { +bool GrResourceAllocator::assign(int* startIndex, int* stopIndex, + GrUninstantiateProxyTracker* uninstantiateTracker, + AssignError* outError) { SkASSERT(outError); *outError = AssignError::kNoError; @@ -252,6 +255,11 @@ bool GrResourceAllocator::assign(int* startIndex, int* stopIndex, AssignError* o if (GrSurfaceProxy::LazyState::kNot != cur->proxy()->lazyInstantiationState()) { if (!cur->proxy()->priv().doLazyInstantiation(fResourceProvider)) { *outError = AssignError::kFailedProxyInstantiation; + } else { + if (GrSurfaceProxy::LazyInstantiationType::kUninstantiate == + cur->proxy()->priv().lazyInstantiationType()) { + uninstantiateTracker->addProxy(cur->proxy()); + } } } else if (sk_sp surface = this->findSurfaceFor(cur->proxy(), needsStencil)) { // TODO: make getUniqueKey virtual on GrSurfaceProxy diff --git a/src/gpu/GrResourceAllocator.h b/src/gpu/GrResourceAllocator.h index f25bef309e..427ff327cb 100644 --- a/src/gpu/GrResourceAllocator.h +++ b/src/gpu/GrResourceAllocator.h @@ -17,6 +17,7 @@ #include "SkTMultiMap.h" class GrResourceProvider; +class GrUninstantiateProxyTracker; /* * The ResourceAllocator explicitly distributes GPU resources at flush time. It operates by @@ -68,7 +69,8 @@ public: // If this happens, the caller should remove all ops which reference an uninstantiated proxy. // This is used to execute a portion of the queued opLists in order to reduce the total // amount of GPU resources required. - bool assign(int* startIndex, int* stopIndex, AssignError* outError); + bool assign(int* startIndex, int* stopIndex, GrUninstantiateProxyTracker*, + AssignError* outError); void markEndOfOpList(int opListIndex); diff --git a/src/gpu/GrSurfaceProxyPriv.h b/src/gpu/GrSurfaceProxyPriv.h index e5d1f906a2..10203b71d0 100644 --- a/src/gpu/GrSurfaceProxyPriv.h +++ b/src/gpu/GrSurfaceProxyPriv.h @@ -74,6 +74,12 @@ public: return fProxy->fLazyInstantiationType; } + bool isSafeToUninstantiate() const { + return SkToBool(fProxy->fTarget) && + SkToBool(fProxy->fLazyInstantiateCallback) && + GrSurfaceProxy::LazyInstantiationType::kUninstantiate == lazyInstantiationType(); + } + void testingOnly_setLazyInstantiationType(GrSurfaceProxy::LazyInstantiationType lazyType) { fProxy->fLazyInstantiationType = lazyType; } diff --git a/src/gpu/GrUninstantiateProxyTracker.cpp b/src/gpu/GrUninstantiateProxyTracker.cpp new file mode 100644 index 0000000000..c4da21b9dc --- /dev/null +++ b/src/gpu/GrUninstantiateProxyTracker.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrUninstantiateProxyTracker.h" + +#include "GrSurfaceProxy.h" +#include "GrSurfaceProxyPriv.h" + +void GrUninstantiateProxyTracker::addProxy(GrSurfaceProxy* proxy) { +#ifdef SK_DEBUG + using LazyType = GrSurfaceProxy::LazyInstantiationType; + SkASSERT(LazyType::kUninstantiate == proxy->priv().lazyInstantiationType()); + for (int i = 0; i < fProxies.count(); ++i) { + SkASSERT(proxy != fProxies[i]); + } +#endif + fProxies.push_back(proxy); +} + +void GrUninstantiateProxyTracker::uninstantiateAllProxies() { + for (int i = 0; i < fProxies.count(); ++i) { + GrSurfaceProxy* proxy = fProxies[i]; + SkASSERT(proxy->priv().isSafeToUninstantiate()); + proxy->deInstantiate(); + } +} diff --git a/src/gpu/GrUninstantiateProxyTracker.h b/src/gpu/GrUninstantiateProxyTracker.h new file mode 100644 index 0000000000..a862bb640c --- /dev/null +++ b/src/gpu/GrUninstantiateProxyTracker.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrUninstantiateProxyTracker_DEFINED +#define GrUninstantiateProxyTracker_DEFINED + +#include "SkTArray.h" + +class GrSurfaceProxy; + +class GrUninstantiateProxyTracker { +public: + GrUninstantiateProxyTracker() {} + + // Adds a proxy which will be uninstantiated at the end of flush. The same proxy may not be + // added multiple times. + void addProxy(GrSurfaceProxy* proxy); + + // Loops through all tracked proxies and uninstantiates them. + void uninstantiateAllProxies(); + +private: + SkTArray fProxies; +}; + +#endif diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp index 9341472090..e31a775730 100644 --- a/src/gpu/mock/GrMockGpu.cpp +++ b/src/gpu/mock/GrMockGpu.cpp @@ -78,6 +78,22 @@ sk_sp GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgete return sk_sp(new GrMockTexture(this, budgeted, desc, mipMapsStatus, info)); } +sk_sp GrMockGpu::onWrapBackendTexture(const GrBackendTexture& tex, + GrWrapOwnership ownership) { + GrSurfaceDesc desc; + desc.fWidth = tex.width(); + desc.fHeight = tex.height(); + SkASSERT(tex.getMockTextureInfo()); + GrMockTextureInfo info = *tex.getMockTextureInfo(); + desc.fConfig = info.fConfig; + + GrMipMapsStatus mipMapsStatus = tex.hasMipMaps() ? GrMipMapsStatus::kValid + : GrMipMapsStatus::kNotAllocated; + + return sk_sp(new GrMockTexture(this, GrMockTexture::kWrapped, desc, mipMapsStatus, + info)); +} + GrBuffer* GrMockGpu::onCreateBuffer(size_t sizeInBytes, GrBufferType type, GrAccessPattern accessPattern, const void*) { return new GrMockBuffer(this, sizeInBytes, type, accessPattern); diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h index d3e665c2e4..00b19ac82e 100644 --- a/src/gpu/mock/GrMockGpu.h +++ b/src/gpu/mock/GrMockGpu.h @@ -58,9 +58,7 @@ private: sk_sp onCreateTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel[], int mipLevelCount) override; - sk_sp onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override { - return nullptr; - } + sk_sp onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override; sk_sp onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, diff --git a/src/gpu/mock/GrMockTexture.h b/src/gpu/mock/GrMockTexture.h index 8a5a1758a6..5ed785e052 100644 --- a/src/gpu/mock/GrMockTexture.h +++ b/src/gpu/mock/GrMockTexture.h @@ -20,6 +20,14 @@ public: : GrMockTexture(gpu, desc, mipMapsStatus, info) { this->registerWithCache(budgeted); } + + enum Wrapped { kWrapped }; + GrMockTexture(GrMockGpu* gpu, Wrapped, const GrSurfaceDesc& desc, + GrMipMapsStatus mipMapsStatus, const GrMockTextureInfo& info) + : GrMockTexture(gpu, desc, mipMapsStatus, info) { + this->registerWithCacheWrapped(); + } + ~GrMockTexture() override {} GrBackendObject getTextureHandle() const override { @@ -44,11 +52,28 @@ protected: mipMapsStatus) , fInfo(info) {} + void onRelease() override { + this->invokeReleaseProc(); + INHERITED::onRelease(); + } + + void onAbandon() override { + this->invokeReleaseProc(); + INHERITED::onAbandon(); + } + bool onStealBackendTexture(GrBackendTexture*, SkImage::BackendTextureReleaseProc*) override { return false; } private: + void invokeReleaseProc() { + if (fReleaseHelper) { + // Depending on the ref count of fReleaseHelper this may or may not actually trigger the + // ReleaseProc to be called. + fReleaseHelper.reset(); + } + } GrMockTextureInfo fInfo; sk_sp fReleaseHelper; -- cgit v1.2.3