diff options
author | bsalomon <bsalomon@google.com> | 2016-09-06 12:38:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-06 12:38:00 -0700 |
commit | 1dbb207babecdae8f1f74ed9d9900c73064df744 (patch) | |
tree | 179554685d20ab291fe8ecfb89b4e2b8f98c44c7 | |
parent | 0a441077dccd8b33ed1af3193b9d5df5143d4861 (diff) |
Restructure flushing relationship between GrContext, GrDrawingManager, and GrResourceCache.
Consolidates all flush actions into GrDrawingManager and makes GrContext::flush a passthrough.
Removes the unused and untested discard flush variation.
Replaces the indirect overbudget callback mechanism of GrResourceCache with a flag set by resource cache when it wants to flush that is checked after each draw by GrDrawContext.
Modifies GrResourceCache::notifyFlushOccurred() to take a param indicating whether it triggered the
flush that just occurred.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2307053002
Review-Url: https://codereview.chromium.org/2307053002
-rw-r--r-- | include/gpu/GrContext.h | 31 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 35 | ||||
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrDrawingManager.cpp | 13 | ||||
-rw-r--r-- | src/gpu/GrDrawingManager.h | 17 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.cpp | 37 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.h | 29 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 1 | ||||
-rw-r--r-- | tests/ResourceCacheTest.cpp | 10 |
9 files changed, 70 insertions, 105 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index f14c36e35c..996b77f2db 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -214,31 +214,10 @@ public: // Misc. /** - * Flags that affect flush() behavior. - */ - enum FlushBits { - /** - * A client may reach a point where it has partially rendered a frame - * through a GrContext that it knows the user will never see. This flag - * causes the flush to skip submission of deferred content to the 3D API - * during the flush. - */ - kDiscard_FlushBit = 0x2, - }; - - /** * Call to ensure all drawing to the context has been issued to the * underlying 3D API. - * @param flagsBitfield flags that control the flushing behavior. See - * FlushBits. */ - void flush(int flagsBitfield = 0); - - void flushIfNecessary() { - if (fFlushToReduceCacheSize || this->caps()->immediateFlush()) { - this->flush(); - } - } + void flush(); /** * These flags can be used with the read/write pixels functions below. @@ -409,8 +388,6 @@ private: GrBatchFontCache* fBatchFontCache; SkAutoTDelete<GrTextBlobCache> fTextBlobCache; - // Set by OverbudgetCB() to request that GrContext flush before exiting a draw. - bool fFlushToReduceCacheSize; bool fDidTestPMConversions; int fPMToUPMConversion; int fUPMToPMConversion; @@ -472,12 +449,6 @@ private: bool didFailPMUPMConversionTest() const; /** - * This callback allows the resource cache to callback into the GrContext - * when the cache is still over budget after a purge. - */ - static void OverBudgetCB(void* data); - - /** * A callback similar to the above for use by the TextBlobCache * TODO move textblob draw calls below context so we can use the call above. */ diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 3f4d2fa959..357f58e6e3 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -66,7 +66,6 @@ GrContext::GrContext() : fUniqueID(next_id()) { fResourceCache = nullptr; fResourceProvider = nullptr; fBatchFontCache = nullptr; - fFlushToReduceCacheSize = false; } bool GrContext::init(GrBackend backend, GrBackendContext backendContext, @@ -87,7 +86,6 @@ void GrContext::initCommon(const GrContextOptions& options) { fCaps = SkRef(fGpu->caps()); fResourceCache = new GrResourceCache(fCaps); - fResourceCache->setOverBudgetCallback(OverBudgetCB, this); fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner); fDidTestPMConversions = false; @@ -97,7 +95,8 @@ void GrContext::initCommon(const GrContextOptions& options) { dtOptions.fDrawBatchBounds = options.fDrawBatchBounds; dtOptions.fMaxBatchLookback = options.fMaxBatchLookback; dtOptions.fMaxBatchLookahead = options.fMaxBatchLookahead; - fDrawingManager.reset(new GrDrawingManager(this, dtOptions, &fSingleOwner)); + fDrawingManager.reset(new GrDrawingManager(this, dtOptions, options.fImmediateMode, + &fSingleOwner)); // GrBatchFontCache will eventually replace GrFontCache fBatchFontCache = new GrBatchFontCache(this); @@ -203,41 +202,21 @@ void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) //////////////////////////////////////////////////////////////////////////////// -void GrContext::OverBudgetCB(void* data) { - SkASSERT(data); - - GrContext* context = reinterpret_cast<GrContext*>(data); - - // Flush the GrBufferedDrawTarget to possibly free up some textures - context->fFlushToReduceCacheSize = true; -} - void GrContext::TextBlobCacheOverBudgetCB(void* data) { SkASSERT(data); - - // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they - // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move - // drawText calls to below the GrContext level, but this is not trivial because they call - // drawPath on SkGpuDevice + // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on GrDrawContext + // to perform a necessary flush. The solution is to move drawText calls to below the GrContext + // level, but this is not trivial because they call drawPath on SkGpuDevice. GrContext* context = reinterpret_cast<GrContext*>(data); context->flush(); } //////////////////////////////////////////////////////////////////////////////// -void GrContext::flush(int flagsBitfield) { +void GrContext::flush() { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED - bool flushed = false; - if (kDiscard_FlushBit & flagsBitfield) { - fDrawingManager->reset(); - } else { - flushed = fDrawingManager->flush(); - } - if (flushed) { - fResourceCache->notifyFlushOccurred(); - } - fFlushToReduceCacheSize = false; + fDrawingManager->flush(); } bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes, diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 87252f3979..ed02602499 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -59,7 +59,7 @@ public: AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) { SkASSERT(fDrawingManager); } - ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); } + ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); } private: GrDrawingManager* fDrawingManager; diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index 6c75c0d147..4642e1a3fe 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -5,8 +5,10 @@ * found in the LICENSE file. */ -#include "GrDrawContext.h" #include "GrDrawingManager.h" + +#include "GrContext.h" +#include "GrDrawContext.h" #include "GrDrawTarget.h" #include "GrPathRenderingDrawContext.h" #include "GrResourceProvider.h" @@ -74,9 +76,9 @@ void GrDrawingManager::reset() { fFlushState.reset(); } -bool GrDrawingManager::flush() { +void GrDrawingManager::internalFlush(GrResourceCache::FlushType type) { if (fFlushing || this->wasAbandoned()) { - return false; + return; } fFlushing = true; bool flushed = false; @@ -126,8 +128,11 @@ bool GrDrawingManager::flush() { #endif fFlushState.reset(); + // 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->getResourceCache()->notifyFlushOccurred(type); + } fFlushing = false; - return flushed; } GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) { diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h index 745820f439..bc6f7a361a 100644 --- a/src/gpu/GrDrawingManager.h +++ b/src/gpu/GrDrawingManager.h @@ -13,6 +13,7 @@ #include "GrBatchFlushState.h" #include "GrPathRendererChain.h" #include "GrPathRenderer.h" +#include "GrResourceCache.h" #include "SkTDArray.h" class GrContext; @@ -49,11 +50,19 @@ public: GrPathRendererChain::DrawType drawType, GrPathRenderer::StencilSupport* stencilSupport = NULL); + void flushIfNecessary() { + if (fContext->getResourceCache()->requestsFlush()) { + this->internalFlush(GrResourceCache::kCacheRequested); + } else if (fIsImmediateMode) { + this->internalFlush(GrResourceCache::kImmediateMode); + } + } + static bool ProgramUnitTest(GrContext* context, int maxStages); private: GrDrawingManager(GrContext* context, const GrDrawTarget::Options& optionsForDrawTargets, - GrSingleOwner* singleOwner) + bool isImmediateMode, GrSingleOwner* singleOwner) : fContext(context) , fOptionsForDrawTargets(optionsForDrawTargets) , fSingleOwner(singleOwner) @@ -68,8 +77,8 @@ private: void abandon(); void cleanup(); void reset(); - /** Returns true if there was anything to flush and false otherwise */ - bool flush(); + void flush() { this->internalFlush(GrResourceCache::FlushType::kExternal); } + void internalFlush(GrResourceCache::FlushType); friend class GrContext; // for access to: ctor, abandon, reset & flush @@ -92,6 +101,8 @@ private: GrBatchFlushState fFlushState; bool fFlushing; + + bool fIsImmediateMode; }; #endif diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp index 62360ed535..e3f4f9ff50 100644 --- a/src/gpu/GrResourceCache.cpp +++ b/src/gpu/GrResourceCache.cpp @@ -73,8 +73,6 @@ GrResourceCache::GrResourceCache(const GrCaps* caps) , fBytes(0) , fBudgetedCount(0) , fBudgetedBytes(0) - , fOverBudgetCB(nullptr) - , fOverBudgetData(nullptr) , fFlushTimestamps(nullptr) , fLastFlushTimestampIndex(0) , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { @@ -503,10 +501,9 @@ void GrResourceCache::purgeAsNeeded() { this->validate(); if (stillOverbudget) { - // Despite the purge we're still over budget. Call our over budget callback. If this frees - // any resources then we'll get notified and take appropriate action. - (*fOverBudgetCB)(fOverBudgetData); - this->validate(); + // Set this so that GrDrawingManager will issue a flush to free up resources with pending + // IO that we were unable to purge in this pass. + fRequestFlush = true; } } @@ -621,16 +618,26 @@ uint32_t GrResourceCache::getNextTimestamp() { return fTimestamp++; } -void GrResourceCache::notifyFlushOccurred() { - if (fFlushTimestamps) { - SkASSERT(SkIsPow2(fMaxUnusedFlushes)); - fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlushes - 1); - // get the timestamp before accessing fFlushTimestamps because getNextTimestamp will - // reallocate fFlushTimestamps on timestamp overflow. - uint32_t timestamp = this->getNextTimestamp(); - fFlushTimestamps[fLastFlushTimestampIndex] = timestamp; - this->purgeAsNeeded(); +void GrResourceCache::notifyFlushOccurred(FlushType type) { + switch (type) { + case FlushType::kImmediateMode: + break; + case FlushType::kCacheRequested: + SkASSERT(fRequestFlush); + fRequestFlush = false; + break; + case FlushType::kExternal: + if (fFlushTimestamps) { + SkASSERT(SkIsPow2(fMaxUnusedFlushes)); + fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlushes - 1); + // get the timestamp before accessing fFlushTimestamps because getNextTimestamp will + // reallocate fFlushTimestamps on timestamp overflow. + uint32_t timestamp = this->getNextTimestamp(); + fFlushTimestamps[fLastFlushTimestampIndex] = timestamp; + } + break; } + this->purgeAsNeeded(); } void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index 6c64ddc933..bf7b237006 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -11,6 +11,7 @@ #include "GrGpuResource.h" #include "GrGpuResourceCacheAccess.h" #include "GrGpuResourcePriv.h" +#include "GrResourceCache.h" #include "GrResourceKey.h" #include "SkMessageBus.h" #include "SkRefCnt.h" @@ -163,23 +164,16 @@ public: /** Purges all resources that don't have external owners. */ void purgeAllUnlocked(); - /** - * The callback function used by the cache when it is still over budget after a purge. The - * passed in 'data' is the same 'data' handed to setOverbudgetCallback. - */ - typedef void (*PFOverBudgetCB)(void* data); + /** Returns true if the cache would like a flush to occur in order to make more resources + purgeable. */ + bool requestsFlush() const { return fRequestFlush; } - /** - * Set the callback the cache should use when it is still over budget after a purge. The 'data' - * provided here will be passed back to the callback. Note that the cache will attempt to purge - * any resources newly freed by the callback. - */ - void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) { - fOverBudgetCB = overBudgetCB; - fOverBudgetData = data; - } - - void notifyFlushOccurred(); + enum FlushType { + kExternal, + kImmediateMode, + kCacheRequested, + }; + void notifyFlushOccurred(FlushType); #if GR_CACHE_STATS struct Stats { @@ -326,8 +320,7 @@ private: int fBudgetedCount; size_t fBudgetedBytes; - PFOverBudgetCB fOverBudgetCB; - void* fOverBudgetData; + bool fRequestFlush; // We keep track of the "timestamps" of the last n flushes. If a resource hasn't been used in // that time then we well preemptively purge it to reduce memory usage. diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 64df998e2f..790a19a506 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1008,7 +1008,6 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap, if (nullptr == texture) { return; } - sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(bitmap.colorSpace(), fDrawContext->getColorSpace()); diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 2cbf81c231..b568485e4b 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -1133,7 +1133,7 @@ static void test_flush(skiatest::Reporter* reporter) { make_unique_key<1>(&k, i); r->resourcePriv().setUniqueKey(k); r->unref(); - cache->notifyFlushOccurred(); + cache->notifyFlushOccurred(GrResourceCache::kExternal); } // Send flush notifications to the cache. Each flush should purge the oldest resource. @@ -1147,7 +1147,7 @@ static void test_flush(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !SkToBool(r)); SkSafeUnref(r); } - cache->notifyFlushOccurred(); + cache->notifyFlushOccurred(GrResourceCache::kExternal); } REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); @@ -1169,13 +1169,13 @@ static void test_flush(skiatest::Reporter* reporter) { } else { r->unref(); } - cache->notifyFlushOccurred(); + cache->notifyFlushOccurred(GrResourceCache::kExternal); } for (int i = 0; i < kFlushCount; ++i) { // Should get a resource purged every other flush. REPORTER_ASSERT(reporter, kFlushCount - i/2 - 1 == cache->getResourceCount()); - cache->notifyFlushOccurred(); + cache->notifyFlushOccurred(GrResourceCache::kExternal); } // Unref all the resources that we kept refs on in the first loop. @@ -1187,7 +1187,7 @@ static void test_flush(skiatest::Reporter* reporter) { // get kFlushCount additional flushes. Then everything should be purged. for (int i = 0; i < kFlushCount; ++i) { REPORTER_ASSERT(reporter, kFlushCount >> 1 == cache->getResourceCount()); - cache->notifyFlushOccurred(); + cache->notifyFlushOccurred(GrResourceCache::kExternal); } REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); |