From 238069b3f58d3b20f710f77a64632470a3bf256a Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Wed, 11 Jul 2018 15:58:57 -0400 Subject: Reland "Make GPU cache invalidation SkMessageBus messages go to one GrContext." This is a reland of f4c5bb9aba485aa47c27b15905d81992b7cf4707 Original change's description: > Make GPU cache invalidation SkMessageBus messages go to one GrContext. > > Makes it so the template param to SkMessageBus must implement: > bool shouldSend(uint32_t inboxID) const > > Updates all GPU backend message types to only go to the GrContext that > is adding a cache entry. > > Bug: skia: > Change-Id: I3e8a4eb90654b7b8ac57cac9fb508c0ef1d51058 > Reviewed-on: https://skia-review.googlesource.com/140220 > Reviewed-by: Robert Phillips > Reviewed-by: Jim Van Verth Bug: skia: Change-Id: I8402bfe3ed0170c99936d47050458817030b473b Reviewed-on: https://skia-review.googlesource.com/140801 Reviewed-by: Brian Salomon Commit-Queue: Brian Salomon --- include/gpu/GrResourceKey.h | 18 ++++++++----- include/private/SkMessageBus.h | 16 ++++++----- src/core/SkResourceCache.h | 4 ++- src/gpu/GrBitmapTextureMaker.cpp | 10 ++++--- src/gpu/GrBitmapTextureMaker.h | 2 +- src/gpu/GrClipStackClip.cpp | 9 ++++--- src/gpu/GrContext.cpp | 6 +++-- src/gpu/GrImageTextureMaker.cpp | 2 +- src/gpu/GrImageTextureMaker.h | 2 +- src/gpu/GrOnFlushResourceProvider.cpp | 5 ++++ src/gpu/GrOnFlushResourceProvider.h | 5 ++-- src/gpu/GrProxyProvider.cpp | 21 +++++++++++++++ src/gpu/GrProxyProvider.h | 4 +++ src/gpu/GrRenderTargetContext.h | 1 + src/gpu/GrResourceCache.cpp | 43 +++++++++++++++--------------- src/gpu/GrResourceCache.h | 7 +++++ src/gpu/GrResourceProvider.h | 1 + src/gpu/GrSoftwarePathRenderer.cpp | 7 +++-- src/gpu/GrTextureAdjuster.cpp | 4 +-- src/gpu/GrTextureAdjuster.h | 2 +- src/gpu/GrTextureMaker.cpp | 2 +- src/gpu/GrTextureProducer.h | 3 +-- src/gpu/SkGr.cpp | 12 ++++++--- src/gpu/SkGr.h | 3 ++- src/gpu/ccpr/GrCCDrawPathsOp.cpp | 8 +++--- src/gpu/ccpr/GrCCPathCache.cpp | 12 ++++++--- src/gpu/ccpr/GrCCPathCache.h | 12 +++++---- src/gpu/ops/GrMeshDrawOp.h | 1 + src/gpu/ops/GrTessellatingPathRenderer.cpp | 6 +++-- src/gpu/text/GrTextBlobCache.cpp | 6 ++--- src/gpu/text/GrTextBlobCache.h | 7 ++++- tests/MessageBusTest.cpp | 43 ++++++++++++++++++++++++++++++ tests/ResourceCacheTest.cpp | 6 ++--- tests/TextureProxyTest.cpp | 3 ++- 34 files changed, 208 insertions(+), 85 deletions(-) diff --git a/include/gpu/GrResourceKey.h b/include/gpu/GrResourceKey.h index 90b84d72bf..5e9bf1f5c0 100644 --- a/include/gpu/GrResourceKey.h +++ b/include/gpu/GrResourceKey.h @@ -8,13 +8,13 @@ #ifndef GrResourceKey_DEFINED #define GrResourceKey_DEFINED +#include #include "../private/SkOnce.h" #include "../private/SkTemplates.h" #include "../private/SkTo.h" #include "GrTypes.h" #include "SkData.h" #include "SkString.h" -#include uint32_t GrResourceKeyHash(const uint32_t* data, size_t size); @@ -315,18 +315,22 @@ static inline void gr_init_static_unique_key_once(SkAlignedSTStorage<1,GrUniqueK // The cache listens for these messages to purge junk resources proactively. class GrUniqueKeyInvalidatedMessage { public: - explicit GrUniqueKeyInvalidatedMessage(const GrUniqueKey& key) : fKey(key) {} + GrUniqueKeyInvalidatedMessage(const GrUniqueKey& key, uint32_t contextUniqueID) + : fKey(key), fContextID(contextUniqueID) { + SkASSERT(SK_InvalidUniqueID != contextUniqueID); + } - GrUniqueKeyInvalidatedMessage(const GrUniqueKeyInvalidatedMessage& that) : fKey(that.fKey) {} + GrUniqueKeyInvalidatedMessage(const GrUniqueKeyInvalidatedMessage&) = default; - GrUniqueKeyInvalidatedMessage& operator=(const GrUniqueKeyInvalidatedMessage& that) { - fKey = that.fKey; - return *this; - } + GrUniqueKeyInvalidatedMessage& operator=(const GrUniqueKeyInvalidatedMessage&) = default; const GrUniqueKey& key() const { return fKey; } + bool shouldSend(uint32_t inboxID) const { return fContextID == inboxID; } + private: GrUniqueKey fKey; + uint32_t fContextID; }; + #endif diff --git a/include/private/SkMessageBus.h b/include/private/SkMessageBus.h index 19e937555d..418235d68e 100644 --- a/include/private/SkMessageBus.h +++ b/include/private/SkMessageBus.h @@ -14,13 +14,17 @@ #include "SkTDArray.h" #include "SkTypes.h" +/** + * Message must implement bool Message::shouldSend(uint32_t inboxID) const. Perhaps someday we + * can use std::experimental::is_detected to avoid this requirement by sending to all inboxes when + * the method is not detected on Message. + */ template class SkMessageBus : SkNoncopyable { public: - // Post a message to be received by Inboxes for this Message type. Threadsafe. - // If id is SK_InvalidUniqueID then it will be sent to all inboxes. - // Otherwise it will be sent to the inbox with that id. - static void Post(const Message& m, uint32_t destID = SK_InvalidUniqueID); + // Post a message to be received by Inboxes for this Message type. Checks + // Message::shouldSend() for each inbox. Threadsafe. + static void Post(const Message& m); class Inbox { public: @@ -102,11 +106,11 @@ template SkMessageBus::SkMessageBus() {} template -/*static*/ void SkMessageBus::Post(const Message& m, uint32_t destID) { +/*static*/ void SkMessageBus::Post(const Message& m) { SkMessageBus* bus = SkMessageBus::Get(); SkAutoMutexAcquire lock(bus->fInboxesMutex); for (int i = 0; i < bus->fInboxes.count(); i++) { - if (SK_InvalidUniqueID == destID || bus->fInboxes[i]->fUniqueID == destID) { + if (m.shouldSend(bus->fInboxes[i]->fUniqueID)) { bus->fInboxes[i]->receive(m); } } diff --git a/src/core/SkResourceCache.h b/src/core/SkResourceCache.h index 6087be7824..4794669492 100644 --- a/src/core/SkResourceCache.h +++ b/src/core/SkResourceCache.h @@ -112,7 +112,9 @@ public: // Used with SkMessageBus struct PurgeSharedIDMessage { PurgeSharedIDMessage(uint64_t sharedID) : fSharedID(sharedID) {} - + // SkResourceCache is typically used as a singleton and we don't label Inboxes so all + // messages go to all inboxes. + bool shouldSend(uint32_t inboxID) const { return true; } uint64_t fSharedID; }; diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp index d2a1fbe3e9..7a70587619 100644 --- a/src/gpu/GrBitmapTextureMaker.cpp +++ b/src/gpu/GrBitmapTextureMaker.cpp @@ -61,7 +61,8 @@ sk_sp GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeM if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) { SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin); if (fOriginalKey.isValid()) { - GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, fBitmap.pixelRef()); + GrInstallBitmapUniqueKeyInvalidator( + fOriginalKey, proxyProvider->contextUniqueID(), fBitmap.pixelRef()); } return proxy; } @@ -85,7 +86,8 @@ sk_sp GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeM // time it too will be deleted or recycled. proxyProvider->removeUniqueKeyFromProxy(fOriginalKey, proxy.get()); proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy.get()); - GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, fBitmap.pixelRef()); + GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextUniqueID(), + fBitmap.pixelRef()); } return mippedProxy; } @@ -105,8 +107,8 @@ void GrBitmapTextureMaker::makeCopyKey(const CopyParams& copyParams, GrUniqueKey } } -void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey) { - GrInstallBitmapUniqueKeyInvalidator(copyKey, fBitmap.pixelRef()); +void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) { + GrInstallBitmapUniqueKeyInvalidator(copyKey, contextUniqueID, fBitmap.pixelRef()); } SkAlphaType GrBitmapTextureMaker::alphaType() const { diff --git a/src/gpu/GrBitmapTextureMaker.h b/src/gpu/GrBitmapTextureMaker.h index f945cbc4c6..22d8ca37ed 100644 --- a/src/gpu/GrBitmapTextureMaker.h +++ b/src/gpu/GrBitmapTextureMaker.h @@ -26,7 +26,7 @@ protected: void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey, SkColorSpace* dstColorSpace) override; - void didCacheCopy(const GrUniqueKey& copyKey) override; + void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override; SkAlphaType alphaType() const override; sk_sp getColorSpace(SkColorSpace* dstColorSpace) override; diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index 8095286329..7704d929f9 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -313,12 +313,13 @@ static void create_clip_mask_key(uint32_t clipGenID, const SkIRect& bounds, int } static void add_invalidate_on_pop_message(const SkClipStack& stack, uint32_t clipGenID, - const GrUniqueKey& clipMaskKey) { + const GrUniqueKey& clipMaskKey, + uint32_t contextUniqueID) { SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart); while (const Element* element = iter.prev()) { if (element->getGenID() == clipGenID) { std::unique_ptr msg( - new GrUniqueKeyInvalidatedMessage(clipMaskKey)); + new GrUniqueKeyInvalidatedMessage(clipMaskKey, contextUniqueID)); element->addResourceInvalidationMessage(std::move(msg)); return; } @@ -363,7 +364,7 @@ sk_sp GrClipStackClip::createAlphaClipMask(GrContext* context, SkASSERT(result->origin() == kTopLeft_GrSurfaceOrigin); proxyProvider->assignUniqueKeyToProxy(key, result.get()); - add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key); + add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key, context->uniqueID()); return result; } @@ -504,6 +505,6 @@ sk_sp GrClipStackClip::createSoftwareClipMask( SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin); proxyProvider->assignUniqueKeyToProxy(key, proxy.get()); - add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key); + add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key, context->uniqueID()); return proxy; } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 6cf5d050a8..dd4f3218fa 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -85,10 +85,12 @@ bool GrContext::initCommon(const GrContextOptions& options) { fResourceCache = new GrResourceCache(fCaps.get(), fUniqueID); fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, &fSingleOwner, options.fExplicitlyAllocateGPUResources); + fProxyProvider = + new GrProxyProvider(fResourceProvider, fResourceCache, fCaps, &fSingleOwner); + } else { + fProxyProvider = new GrProxyProvider(this->uniqueID(), fCaps, &fSingleOwner); } - fProxyProvider = new GrProxyProvider(fResourceProvider, fResourceCache, fCaps, &fSingleOwner); - if (fResourceCache) { fResourceCache->setProxyProvider(fProxyProvider); } diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp index 732811615f..a8e62162a6 100644 --- a/src/gpu/GrImageTextureMaker.cpp +++ b/src/gpu/GrImageTextureMaker.cpp @@ -42,7 +42,7 @@ void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* pa } } -void GrImageTextureMaker::didCacheCopy(const GrUniqueKey& copyKey) { +void GrImageTextureMaker::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) { as_IB(fClient)->notifyAddedToCache(); } diff --git a/src/gpu/GrImageTextureMaker.h b/src/gpu/GrImageTextureMaker.h index 1a72f68e1b..1fe882a4f3 100644 --- a/src/gpu/GrImageTextureMaker.h +++ b/src/gpu/GrImageTextureMaker.h @@ -29,7 +29,7 @@ protected: void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey, SkColorSpace* dstColorSpace) override; - void didCacheCopy(const GrUniqueKey& copyKey) override; + void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override; SkAlphaType alphaType() const override; sk_sp getColorSpace(SkColorSpace* dstColorSpace) override; diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp index ddf66020d2..26b59f93b9 100644 --- a/src/gpu/GrOnFlushResourceProvider.cpp +++ b/src/gpu/GrOnFlushResourceProvider.cpp @@ -6,6 +6,7 @@ */ #include "GrOnFlushResourceProvider.h" +#include "GrContext.h" #include "GrContextPriv.h" #include "GrDrawingManager.h" #include "GrProxyProvider.h" @@ -130,6 +131,10 @@ sk_sp GrOnFlushResourceProvider::findOrMakeStaticBuffer(GrBuffer return buffer; } +uint32_t GrOnFlushResourceProvider::contextUniqueID() const { + return fDrawingMgr->getContext()->uniqueID(); +} + const GrCaps* GrOnFlushResourceProvider::caps() const { return fDrawingMgr->getContext()->contextPriv().caps(); } diff --git a/src/gpu/GrOnFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h index d01f1342ea..c30ec61daa 100644 --- a/src/gpu/GrOnFlushResourceProvider.h +++ b/src/gpu/GrOnFlushResourceProvider.h @@ -8,7 +8,6 @@ #ifndef GrOnFlushResourceProvider_DEFINED #define GrOnFlushResourceProvider_DEFINED -#include "GrTypes.h" #include "GrDeferredUpload.h" #include "GrOpFlushState.h" #include "GrResourceProvider.h" @@ -21,7 +20,6 @@ class GrOnFlushResourceProvider; class GrRenderTargetOpList; class GrRenderTargetContext; class GrSurfaceProxy; - class SkColorSpace; class SkSurfaceProps; @@ -31,7 +29,7 @@ class SkSurfaceProps; */ class GrOnFlushCallbackObject { public: - virtual ~GrOnFlushCallbackObject() { } + virtual ~GrOnFlushCallbackObject() {} /* * The onFlush callback allows subsystems (e.g., text, path renderers) to create atlases @@ -91,6 +89,7 @@ public: sk_sp findOrMakeStaticBuffer(GrBufferType, size_t, const void* data, const GrUniqueKey&); + uint32_t contextUniqueID() const; const GrCaps* caps() const; private: diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp index e259e34e28..df7b61e700 100644 --- a/src/gpu/GrProxyProvider.cpp +++ b/src/gpu/GrProxyProvider.cpp @@ -37,11 +37,32 @@ GrProxyProvider::GrProxyProvider(GrResourceProvider* resourceProvider, , fResourceCache(resourceCache) , fAbandoned(false) , fCaps(caps) + , fContextUniqueID(resourceCache->contextUniqueID()) #ifdef SK_DEBUG , fSingleOwner(owner) #endif { + SkASSERT(fResourceProvider); + SkASSERT(fResourceCache); + SkASSERT(fCaps); + SkASSERT(fSingleOwner); +} +GrProxyProvider::GrProxyProvider(uint32_t contextUniqueID, + sk_sp caps, + GrSingleOwner* owner) + : fResourceProvider(nullptr) + , fResourceCache(nullptr) + , fAbandoned(false) + , fCaps(caps) + , fContextUniqueID(contextUniqueID) +#ifdef SK_DEBUG + , fSingleOwner(owner) +#endif +{ + SkASSERT(fContextUniqueID != SK_InvalidUniqueID); + SkASSERT(fCaps); + SkASSERT(fSingleOwner); } GrProxyProvider::~GrProxyProvider() { diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h index 64b9ac4355..89f9518e46 100644 --- a/src/gpu/GrProxyProvider.h +++ b/src/gpu/GrProxyProvider.h @@ -27,6 +27,7 @@ class SkImage; class GrProxyProvider { public: GrProxyProvider(GrResourceProvider*, GrResourceCache*, sk_sp, GrSingleOwner*); + GrProxyProvider(uint32_t contextUniqueID, sk_sp, GrSingleOwner*); ~GrProxyProvider(); @@ -211,6 +212,7 @@ public: */ void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface); + uint32_t contextUniqueID() const { return fContextUniqueID; } const GrCaps* caps() const { return fCaps.get(); } sk_sp refCaps() const { return fCaps; } @@ -258,6 +260,8 @@ private: GrResourceCache* fResourceCache; bool fAbandoned; sk_sp fCaps; + // If this provider is owned by a DDLContext then this is the DirectContext's ID. + uint32_t fContextUniqueID; // In debug builds we guard against improper thread handling SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;) diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index ee0d183981..376fe10735 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -16,6 +16,7 @@ #include "GrSurfaceContext.h" #include "GrTypesPriv.h" #include "GrXferProcessor.h" +#include "SkCanvas.h" #include "SkRefCnt.h" #include "SkSurfaceProps.h" #include "text/GrTextUtils.h" diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp index c4e940980e..23c8e7c996 100644 --- a/src/gpu/GrResourceCache.cpp +++ b/src/gpu/GrResourceCache.cpp @@ -63,27 +63,29 @@ private: ////////////////////////////////////////////////////////////////////////////// - GrResourceCache::GrResourceCache(const GrCaps* caps, uint32_t contextUniqueID) - : fProxyProvider(nullptr) - , fTimestamp(0) - , fMaxCount(kDefaultMaxCount) - , fMaxBytes(kDefaultMaxSize) - , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) + : fProxyProvider(nullptr) + , fTimestamp(0) + , fMaxCount(kDefaultMaxCount) + , fMaxBytes(kDefaultMaxSize) + , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) #if GR_CACHE_STATS - , fHighWaterCount(0) - , fHighWaterBytes(0) - , fBudgetedHighWaterCount(0) - , fBudgetedHighWaterBytes(0) + , fHighWaterCount(0) + , fHighWaterBytes(0) + , fBudgetedHighWaterCount(0) + , fBudgetedHighWaterBytes(0) #endif - , fBytes(0) - , fBudgetedCount(0) - , fBudgetedBytes(0) - , fPurgeableBytes(0) - , fRequestFlush(false) - , fExternalFlushCnt(0) - , fContextUniqueID(contextUniqueID) - , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { + , fBytes(0) + , fBudgetedCount(0) + , fBudgetedBytes(0) + , fPurgeableBytes(0) + , fRequestFlush(false) + , fExternalFlushCnt(0) + , fInvalidUniqueKeyInbox(contextUniqueID) + , fFreedGpuResourceInbox(contextUniqueID) + , fContextUniqueID(contextUniqueID) + , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { + SkASSERT(contextUniqueID != SK_InvalidUniqueID); SkDEBUGCODE(fCount = 0;) SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) } @@ -604,9 +606,8 @@ void GrResourceCache::processFreedGpuResources() { SkTArray msgs; fFreedGpuResourceInbox.poll(&msgs); for (int i = 0; i < msgs.count(); ++i) { - if (msgs[i].fOwningUniqueID == fContextUniqueID) { - msgs[i].fResource->unref(); - } + SkASSERT(msgs[i].fOwningUniqueID == fContextUniqueID); + msgs[i].fResource->unref(); } } diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index 771b13fb26..507c192f43 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -27,6 +27,10 @@ class SkTraceMemoryDump; struct GrGpuResourceFreedMessage { GrGpuResource* fResource; uint32_t fOwningUniqueID; + bool shouldSend(uint32_t inboxID) const { + // The inbox's ID is the unique ID of the owning GrContext. + return inboxID == fOwningUniqueID; + } }; /** @@ -67,6 +71,9 @@ public: class ResourceAccess; ResourceAccess resourceAccess(); + /** Unique ID of the owning GrContext. */ + uint32_t contextUniqueID() const { return fContextUniqueID; } + /** * Sets the cache limits in terms of number of resources, max gpu memory byte size, and number * of external GrContext flushes that a resource can be unused before it is evicted. The latter diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h index 35c36826af..347a5de2cd 100644 --- a/src/gpu/GrResourceProvider.h +++ b/src/gpu/GrResourceProvider.h @@ -251,6 +251,7 @@ public: fGpu = nullptr; } + uint32_t contextUniqueID() const { return fCache->contextUniqueID(); } const GrCaps* caps() const { return fCaps.get(); } bool overBudget() const { return fCache->overBudget(); } diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp index ee52122840..213dbdb025 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -216,7 +216,9 @@ private: // When the SkPathRef genID changes, invalidate a corresponding GrResource described by key. class PathInvalidator : public SkPathRef::GenIDChangeListener { public: - explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {} + PathInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID) + : fMsg(key, contextUniqueID) {} + private: GrUniqueKeyInvalidatedMessage fMsg; @@ -366,7 +368,8 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) { if (useCache) { SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin); fProxyProvider->assignUniqueKeyToProxy(maskKey, proxy.get()); - args.fShape->addGenIDChangeListener(sk_make_sp(maskKey)); + args.fShape->addGenIDChangeListener( + sk_make_sp(maskKey, args.fContext->uniqueID())); } } if (inverseFilled) { diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp index 4b21bac9d0..d016896c3f 100644 --- a/src/gpu/GrTextureAdjuster.cpp +++ b/src/gpu/GrTextureAdjuster.cpp @@ -33,7 +33,7 @@ void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyK MakeCopyKeyFromOrigKey(baseKey, params, copyKey); } -void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) { +void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) { // We don't currently have a mechanism for notifications on Images! } @@ -67,7 +67,7 @@ sk_sp GrTextureAdjuster::refTextureProxyCopy(const CopyParams& c proxyProvider->removeUniqueKeyFromProxy(key, cachedCopy.get()); } proxyProvider->assignUniqueKeyToProxy(key, copy.get()); - this->didCacheCopy(key); + this->didCacheCopy(key, proxyProvider->contextUniqueID()); } } return copy; diff --git a/src/gpu/GrTextureAdjuster.h b/src/gpu/GrTextureAdjuster.h index 885e39059d..e43e87b1dc 100644 --- a/src/gpu/GrTextureAdjuster.h +++ b/src/gpu/GrTextureAdjuster.h @@ -37,7 +37,7 @@ protected: SkAlphaType alphaType() const override { return fAlphaType; } void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey, SkColorSpace* dstColorSpace) override; - void didCacheCopy(const GrUniqueKey& copyKey) override; + void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override; GrTextureProxy* originalProxy() const { return fOriginal.get(); } sk_sp originalProxyRef() const { return fOriginal; } diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp index f9ee7585d2..22870cc7c8 100644 --- a/src/gpu/GrTextureMaker.cpp +++ b/src/gpu/GrTextureMaker.cpp @@ -109,7 +109,7 @@ sk_sp GrTextureMaker::onRefTextureProxyForParams(const GrSampler proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get()); } proxyProvider->assignUniqueKeyToProxy(copyKey, result.get()); - this->didCacheCopy(copyKey); + this->didCacheCopy(copyKey, proxyProvider->contextUniqueID()); } return result; } diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h index c458d4fbe6..176247b67e 100644 --- a/src/gpu/GrTextureProducer.h +++ b/src/gpu/GrTextureProducer.h @@ -158,8 +158,7 @@ protected: * makeCopyKey() returns true). In that case, the maker is notified in case it * wants to note that for when the maker is destroyed. */ - virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0; - + virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0; enum DomainMode { kNoDomain_DomainMode, diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index ff2b9843e8..5baf0d4017 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -88,17 +88,20 @@ sk_sp GrUploadBitmapToTextureProxy(GrProxyProvider* proxyProvide //////////////////////////////////////////////////////////////////////////////// -void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) { +void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID, + SkPixelRef* pixelRef) { class Invalidator : public SkPixelRef::GenIDChangeListener { public: - explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {} + explicit Invalidator(const GrUniqueKey& key, uint32_t contextUniqueID) + : fMsg(key, contextUniqueID) {} + private: GrUniqueKeyInvalidatedMessage fMsg; void onChange() override { SkMessageBus::Post(fMsg); } }; - pixelRef->addGenIDChangeListener(new Invalidator(key)); + pixelRef->addGenIDChangeListener(new Invalidator(key, contextUniqueID)); } sk_sp GrCopyBaseMipMapToTextureProxy(GrContext* ctx, GrTextureProxy* baseProxy) { @@ -199,7 +202,8 @@ sk_sp GrMakeCachedImageProxy(GrProxyProvider* proxyProvider, // When recording DDLs we do not want to install change listeners because doing // so isn't threadsafe. if (bm && !proxyProvider->recordingDDL()) { - GrInstallBitmapUniqueKeyInvalidator(originalKey, bm->pixelRef()); + GrInstallBitmapUniqueKeyInvalidator(originalKey, proxyProvider->contextUniqueID(), + bm->pixelRef()); } } } diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h index a2ac670712..ec9f30a3bf 100644 --- a/src/gpu/SkGr.h +++ b/src/gpu/SkGr.h @@ -243,6 +243,7 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& ima /** Call this after installing a GrUniqueKey on texture. It will cause the texture's key to be removed should the bitmap's contents change or be destroyed. */ -void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef); +void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID, + SkPixelRef* pixelRef); #endif diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp index 2d250deb00..016756a7f6 100644 --- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp +++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp @@ -251,7 +251,8 @@ void GrCCDrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP, GrCCAtlas* atlas = resources->copyPathToCachedAtlas(*cacheEntry, doEvenOddFill, &newOffset); cacheEntry->updateToCachedAtlas(atlas->getOrAssignUniqueKey(onFlushRP), - newOffset, atlas->refOrMakeCachedAtlasInfo()); + onFlushRP->contextUniqueID(), newOffset, + atlas->refOrMakeCachedAtlasInfo()); this->recordInstance(atlas->textureProxy(), resources->nextPathInstanceIdx()); resources->appendDrawPathInstance().set(*cacheEntry, draw.fCachedMaskShift, draw.fColor); @@ -296,8 +297,9 @@ void GrCCDrawPathsOp::setupResources(GrOnFlushResourceProvider* onFlushRP, const GrUniqueKey& atlasKey = resources->nextAtlasToStash()->getOrAssignUniqueKey(onFlushRP); - cacheEntry->initAsStashedAtlas(atlasKey, devToAtlasOffset, devBounds, devBounds45, - devIBounds, draw.fCachedMaskShift); + cacheEntry->initAsStashedAtlas(atlasKey, onFlushRP->contextUniqueID(), + devToAtlasOffset, devBounds, devBounds45, devIBounds, + draw.fCachedMaskShift); // Remember this atlas in case we encounter the path again during the same flush. cacheEntry->setCurrFlushAtlas(atlas); } diff --git a/src/gpu/ccpr/GrCCPathCache.cpp b/src/gpu/ccpr/GrCCPathCache.cpp index b22b1dd726..d7dc714c82 100644 --- a/src/gpu/ccpr/GrCCPathCache.cpp +++ b/src/gpu/ccpr/GrCCPathCache.cpp @@ -149,13 +149,16 @@ GrCCPathCacheEntry::~GrCCPathCacheEntry() { this->invalidateAtlas(); } -void GrCCPathCacheEntry::initAsStashedAtlas(const GrUniqueKey& atlasKey, +void GrCCPathCacheEntry::initAsStashedAtlas(const GrUniqueKey& atlasKey, uint32_t contextUniqueID, const SkIVector& atlasOffset, const SkRect& devBounds, const SkRect& devBounds45, const SkIRect& devIBounds, const SkIVector& maskShift) { + SkASSERT(contextUniqueID != SK_InvalidUniqueID); SkASSERT(atlasKey.isValid()); SkASSERT(!fCurrFlushAtlas); // Otherwise we should reuse the atlas from last time. + fContextUniqueID = contextUniqueID; + fAtlasKey = atlasKey; fAtlasOffset = atlasOffset + maskShift; SkASSERT(!fCachedAtlasInfo); // Otherwise they should have reused the cached atlas instead. @@ -166,12 +169,15 @@ void GrCCPathCacheEntry::initAsStashedAtlas(const GrUniqueKey& atlasKey, fDevIBounds = devIBounds.makeOffset(-maskShift.fX, -maskShift.fY); } -void GrCCPathCacheEntry::updateToCachedAtlas(const GrUniqueKey& atlasKey, +void GrCCPathCacheEntry::updateToCachedAtlas(const GrUniqueKey& atlasKey, uint32_t contextUniqueID, const SkIVector& newAtlasOffset, sk_sp info) { + SkASSERT(contextUniqueID != SK_InvalidUniqueID); SkASSERT(atlasKey.isValid()); SkASSERT(!fCurrFlushAtlas); // Otherwise we should reuse the atlas from last time. + fContextUniqueID = contextUniqueID; + fAtlasKey = atlasKey; fAtlasOffset = newAtlasOffset; @@ -188,7 +194,7 @@ void GrCCPathCacheEntry::invalidateAtlas() { fCachedAtlasInfo->fNumInvalidatedPathPixels >= fCachedAtlasInfo->fNumPathPixels / 2) { // Too many invalidated pixels: purge the atlas texture from the resource cache. SkMessageBus::Post( - GrUniqueKeyInvalidatedMessage(fAtlasKey)); + GrUniqueKeyInvalidatedMessage(fAtlasKey, fContextUniqueID)); fCachedAtlasInfo->fIsPurgedFromResourceCache = true; } } diff --git a/src/gpu/ccpr/GrCCPathCache.h b/src/gpu/ccpr/GrCCPathCache.h index 67e7d9f571..7a552bbc2a 100644 --- a/src/gpu/ccpr/GrCCPathCache.h +++ b/src/gpu/ccpr/GrCCPathCache.h @@ -121,14 +121,15 @@ public: // Called once our path has been rendered into the mainline CCPR (fp16, coverage count) atlas. // The caller will stash this atlas texture away after drawing, and during the next flush, // recover it and attempt to copy any paths that got reused into permanent 8-bit atlases. - void initAsStashedAtlas(const GrUniqueKey& atlasKey, const SkIVector& atlasOffset, - const SkRect& devBounds, const SkRect& devBounds45, - const SkIRect& devIBounds, const SkIVector& maskShift); + void initAsStashedAtlas(const GrUniqueKey& atlasKey, uint32_t contextUniqueID, + const SkIVector& atlasOffset, const SkRect& devBounds, + const SkRect& devBounds45, const SkIRect& devIBounds, + const SkIVector& maskShift); // Called once our path mask has been copied into a permanent, 8-bit atlas. This method points // the entry at the new atlas and updates the CachedAtlasInfo data. - void updateToCachedAtlas(const GrUniqueKey& atlasKey, const SkIVector& newAtlasOffset, - sk_sp); + void updateToCachedAtlas(const GrUniqueKey& atlasKey, uint32_t contextUniqueID, + const SkIVector& newAtlasOffset, sk_sp); const GrUniqueKey& atlasKey() const { return fAtlasKey; } @@ -162,6 +163,7 @@ private: // Called when our corresponding path is modified or deleted. void onChange() override; + uint32_t fContextUniqueID; GrCCPathCache* fCacheWeakPtr; // Gets manually reset to null by the path cache upon eviction. MaskTransform fMaskTransform; int fHitCount = 1; diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h index ddc29f1dab..449fd53807 100644 --- a/src/gpu/ops/GrMeshDrawOp.h +++ b/src/gpu/ops/GrMeshDrawOp.h @@ -170,6 +170,7 @@ public: virtual const GrXferProcessor::DstProxy& dstProxy() const = 0; virtual GrResourceProvider* resourceProvider() const = 0; + uint32_t contextUniqueID() const { return this->resourceProvider()->contextUniqueID(); } virtual GrGlyphCache* glyphCache() const = 0; virtual GrAtlasManager* atlasManager() const = 0; diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp index 1c0a7f5551..475197e197 100644 --- a/src/gpu/ops/GrTessellatingPathRenderer.cpp +++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp @@ -42,7 +42,9 @@ struct TessInfo { // When the SkPathRef genID changes, invalidate a corresponding GrResource described by key. class PathInvalidator : public SkPathRef::GenIDChangeListener { public: - explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {} + PathInvalidator(const GrUniqueKey& key, uint32_t contextUniqueID) + : fMsg(key, contextUniqueID) {} + private: GrUniqueKeyInvalidatedMessage fMsg; @@ -284,7 +286,7 @@ private: info.fCount = count; key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info))); rp->assignUniqueKeyToResource(key, allocator.vertexBuffer()); - fShape.addGenIDChangeListener(sk_make_sp(key)); + fShape.addGenIDChangeListener(sk_make_sp(key, target->contextUniqueID())); } void drawAA(Target* target, const GrGeometryProcessor* gp, size_t vertexStride) { diff --git a/src/gpu/text/GrTextBlobCache.cpp b/src/gpu/text/GrTextBlobCache.cpp index 71d9052ade..a60903fca3 100644 --- a/src/gpu/text/GrTextBlobCache.cpp +++ b/src/gpu/text/GrTextBlobCache.cpp @@ -30,7 +30,7 @@ void GrTextBlobCache::freeAll() { void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) { SkASSERT(blobID != SK_InvalidGenID); - SkMessageBus::Post(PurgeBlobMessage({blobID}), cacheID); + SkMessageBus::Post(PurgeBlobMessage(blobID, cacheID)); } void GrTextBlobCache::purgeStaleBlobs() { @@ -38,7 +38,7 @@ void GrTextBlobCache::purgeStaleBlobs() { fPurgeBlobInbox.poll(&msgs); for (const auto& msg : msgs) { - auto* idEntry = fBlobIDCache.find(msg.fID); + auto* idEntry = fBlobIDCache.find(msg.fBlobID); if (!idEntry) { // no cache entries for id continue; @@ -51,7 +51,7 @@ void GrTextBlobCache::purgeStaleBlobs() { } // drop the idEntry itself (unrefs all blobs) - fBlobIDCache.remove(msg.fID); + fBlobIDCache.remove(msg.fBlobID); } } diff --git a/src/gpu/text/GrTextBlobCache.h b/src/gpu/text/GrTextBlobCache.h index b41d401aee..a174c9cf90 100644 --- a/src/gpu/text/GrTextBlobCache.h +++ b/src/gpu/text/GrTextBlobCache.h @@ -99,7 +99,12 @@ public: } struct PurgeBlobMessage { - uint32_t fID; + PurgeBlobMessage(uint32_t blobID, uint32_t contextUniqueID) + : fBlobID(blobID), fContextID(contextUniqueID) {} + bool shouldSend(uint32_t inboxID) const { return fContextID == inboxID; } + + uint32_t fBlobID; + uint32_t fContextID; }; static void PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID); diff --git a/tests/MessageBusTest.cpp b/tests/MessageBusTest.cpp index 163addf8f0..145176ba1b 100644 --- a/tests/MessageBusTest.cpp +++ b/tests/MessageBusTest.cpp @@ -8,10 +8,15 @@ #include "SkMessageBus.h" #include "Test.h" +namespace { struct TestMessage { + bool shouldSend(uint32_t inboxID) const { return true; } + TestMessage(int i, float f) : x(i), y(f) {} + int x; float y; }; +} DECLARE_SKMESSAGEBUS_MESSAGE(TestMessage) DEF_TEST(MessageBus, r) { @@ -50,4 +55,42 @@ DEF_TEST(MessageBus, r) { REPORTER_ASSERT(r, 1 == messages[2].x); } +namespace { +struct AddressedMessage { + uint32_t fInboxID; + + bool shouldSend(uint32_t inboxID) const { + SkASSERT(inboxID); + if (!fInboxID) { + return true; + } + return inboxID == fInboxID; + } +}; +} +DECLARE_SKMESSAGEBUS_MESSAGE(AddressedMessage) + +DEF_TEST(MessageBus_shouldSend, r) { + SkMessageBus::Inbox inbox1(1), inbox2(2); + + SkMessageBus::Post({0}); // Should go to both + SkMessageBus::Post({1}); // Should go to inbox1 + SkMessageBus::Post({2}); // Should go to inbox2 + SkMessageBus::Post({3}); // Should go nowhere + + SkTArray messages; + inbox1.poll(&messages); + REPORTER_ASSERT(r, messages.count() == 2); + if (messages.count() == 2) { + REPORTER_ASSERT(r, messages[0].fInboxID == 0); + REPORTER_ASSERT(r, messages[1].fInboxID == 1); + } + inbox2.poll(&messages); + REPORTER_ASSERT(r, messages.count() == 2); + if (messages.count() == 2) { + REPORTER_ASSERT(r, messages[0].fInboxID == 0); + REPORTER_ASSERT(r, messages[1].fInboxID == 2); + } +} + // Multithreaded tests tbd. diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index dceb3e74ed..5b7a67a648 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -1003,8 +1003,8 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) { typedef SkMessageBus Bus; // Invalidate two of the three, they should be purged and no longer accessible via their keys. - Bus::Post(Msg(key1)); - Bus::Post(Msg(key2)); + Bus::Post(Msg(key1, context->uniqueID())); + Bus::Post(Msg(key2, context->uniqueID())); cache->purgeAsNeeded(); // a should be deleted now, but we still have a ref on b. REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1)); @@ -1013,7 +1013,7 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3)); // Invalidate the third. - Bus::Post(Msg(key3)); + Bus::Post(Msg(key3, context->uniqueID())); cache->purgeAsNeeded(); // we still have a ref on b, c should be recycled as scratch. REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive()); diff --git a/tests/TextureProxyTest.cpp b/tests/TextureProxyTest.cpp index 15e3ef6d9f..da072b5750 100644 --- a/tests/TextureProxyTest.cpp +++ b/tests/TextureProxyTest.cpp @@ -255,7 +255,8 @@ static void invalidation_and_instantiation_test(GrContext* context, skiatest::Re SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get())); // Send an invalidation message, which will be sitting in the cache's inbox - SkMessageBus::Post(GrUniqueKeyInvalidatedMessage(key)); + SkMessageBus::Post( + GrUniqueKeyInvalidatedMessage(key, context->uniqueID())); REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly()); REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); -- cgit v1.2.3