Use an array of nonpurgeable resources in GrResourceCache
Review URL: https://codereview.chromium.org/932863004
This commit is contained in:
parent
91d1d621de
commit
f320e04c50
@ -12,7 +12,6 @@
|
||||
#include "GrTypesPriv.h"
|
||||
#include "SkData.h"
|
||||
#include "SkInstCnt.h"
|
||||
#include "SkTInternalLList.h"
|
||||
|
||||
class GrContext;
|
||||
class GrGpu;
|
||||
@ -283,11 +282,8 @@ private:
|
||||
|
||||
static uint32_t CreateUniqueID();
|
||||
|
||||
// We're in an internal doubly linked list owned by GrResourceCache. TODO: Replace this with an
|
||||
// array of unpurgeable resources in the cache.
|
||||
SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrGpuResource);
|
||||
|
||||
// An index into a heap when this resource is purgeable. This is maintained by the cache.
|
||||
// An index into a heap when this resource is purgeable or an array when not. This is maintained
|
||||
// by the cache.
|
||||
int fCacheArrayIndex;
|
||||
// This value reflects how recently this resource was accessed in the cache. This is maintained
|
||||
// by the cache.
|
||||
|
@ -67,12 +67,12 @@ GrResourceCache::GrResourceCache()
|
||||
, fBudgetedHighWaterCount(0)
|
||||
, fBudgetedHighWaterBytes(0)
|
||||
#endif
|
||||
, fCount(0)
|
||||
, fBytes(0)
|
||||
, fBudgetedCount(0)
|
||||
, fBudgetedBytes(0)
|
||||
, fOverBudgetCB(NULL)
|
||||
, fOverBudgetData(NULL) {
|
||||
SkDEBUGCODE(fCount = 0;)
|
||||
}
|
||||
|
||||
GrResourceCache::~GrResourceCache() {
|
||||
@ -87,15 +87,16 @@ void GrResourceCache::setLimits(int count, size_t bytes) {
|
||||
|
||||
void GrResourceCache::insertResource(GrGpuResource* resource) {
|
||||
SkASSERT(resource);
|
||||
SkASSERT(!resource->wasDestroyed());
|
||||
SkASSERT(!this->isInCache(resource));
|
||||
fResources.addToHead(resource);
|
||||
SkASSERT(!resource->wasDestroyed());
|
||||
SkASSERT(!resource->isPurgeable());
|
||||
this->addToNonpurgeableArray(resource);
|
||||
|
||||
size_t size = resource->gpuMemorySize();
|
||||
++fCount;
|
||||
SkDEBUGCODE(++fCount;)
|
||||
fBytes += size;
|
||||
#if GR_CACHE_STATS
|
||||
fHighWaterCount = SkTMax(fCount, fHighWaterCount);
|
||||
fHighWaterCount = SkTMax(this->getResourceCount(), fHighWaterCount);
|
||||
fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
|
||||
#endif
|
||||
if (resource->resourcePriv().isBudgeted()) {
|
||||
@ -122,17 +123,18 @@ void GrResourceCache::removeResource(GrGpuResource* resource) {
|
||||
|
||||
if (resource->isPurgeable()) {
|
||||
fPurgeableQueue.remove(resource);
|
||||
} else {
|
||||
this->removeFromNonpurgeableArray(resource);
|
||||
}
|
||||
|
||||
size_t size = resource->gpuMemorySize();
|
||||
--fCount;
|
||||
SkDEBUGCODE(--fCount;)
|
||||
fBytes -= size;
|
||||
if (resource->resourcePriv().isBudgeted()) {
|
||||
--fBudgetedCount;
|
||||
fBudgetedBytes -= size;
|
||||
}
|
||||
|
||||
fResources.remove(resource);
|
||||
if (resource->resourcePriv().getScratchKey().isValid()) {
|
||||
fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource);
|
||||
}
|
||||
@ -145,15 +147,22 @@ void GrResourceCache::removeResource(GrGpuResource* resource) {
|
||||
void GrResourceCache::abandonAll() {
|
||||
AutoValidate av(this);
|
||||
|
||||
while (GrGpuResource* head = fResources.head()) {
|
||||
SkASSERT(!head->wasDestroyed());
|
||||
head->cacheAccess().abandon();
|
||||
// abandon should have already removed this from the list.
|
||||
SkASSERT(head != fResources.head());
|
||||
while (fNonpurgeableResources.count()) {
|
||||
GrGpuResource* back = *(fNonpurgeableResources.end() - 1);
|
||||
SkASSERT(!back->wasDestroyed());
|
||||
back->cacheAccess().abandon();
|
||||
}
|
||||
|
||||
while (fPurgeableQueue.count()) {
|
||||
GrGpuResource* top = fPurgeableQueue.peek();
|
||||
SkASSERT(!top->wasDestroyed());
|
||||
top->cacheAccess().abandon();
|
||||
}
|
||||
|
||||
SkASSERT(!fScratchMap.count());
|
||||
SkASSERT(!fContentHash.count());
|
||||
SkASSERT(!fCount);
|
||||
SkASSERT(!this->getResourceCount());
|
||||
SkASSERT(!fBytes);
|
||||
SkASSERT(!fBudgetedCount);
|
||||
SkASSERT(!fBudgetedBytes);
|
||||
@ -162,14 +171,22 @@ void GrResourceCache::abandonAll() {
|
||||
void GrResourceCache::releaseAll() {
|
||||
AutoValidate av(this);
|
||||
|
||||
while (GrGpuResource* head = fResources.head()) {
|
||||
SkASSERT(!head->wasDestroyed());
|
||||
head->cacheAccess().release();
|
||||
// release should have already removed this from the list.
|
||||
SkASSERT(head != fResources.head());
|
||||
while(fNonpurgeableResources.count()) {
|
||||
GrGpuResource* back = *(fNonpurgeableResources.end() - 1);
|
||||
SkASSERT(!back->wasDestroyed());
|
||||
back->cacheAccess().release();
|
||||
}
|
||||
|
||||
while (fPurgeableQueue.count()) {
|
||||
GrGpuResource* top = fPurgeableQueue.peek();
|
||||
SkASSERT(!top->wasDestroyed());
|
||||
top->cacheAccess().release();
|
||||
}
|
||||
|
||||
SkASSERT(!fScratchMap.count());
|
||||
SkASSERT(!fContentHash.count());
|
||||
SkASSERT(!fCount);
|
||||
SkASSERT(!this->getResourceCount());
|
||||
SkASSERT(!fBytes);
|
||||
SkASSERT(!fBudgetedCount);
|
||||
SkASSERT(!fBudgetedBytes);
|
||||
@ -248,10 +265,11 @@ void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) {
|
||||
if (resource->isPurgeable()) {
|
||||
// It's about to become unpurgeable.
|
||||
fPurgeableQueue.remove(resource);
|
||||
this->addToNonpurgeableArray(resource);
|
||||
}
|
||||
resource->ref();
|
||||
resource->cacheAccess().setTimestamp(fTimestamp++);
|
||||
SkASSERT(!resource->isPurgeable());
|
||||
this->validate();
|
||||
}
|
||||
|
||||
void GrResourceCache::notifyPurgeable(GrGpuResource* resource) {
|
||||
@ -259,7 +277,7 @@ void GrResourceCache::notifyPurgeable(GrGpuResource* resource) {
|
||||
SkASSERT(this->isInCache(resource));
|
||||
SkASSERT(resource->isPurgeable());
|
||||
|
||||
SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex());
|
||||
this->removeFromNonpurgeableArray(resource);
|
||||
fPurgeableQueue.insert(resource);
|
||||
|
||||
if (!resource->resourcePriv().isBudgeted()) {
|
||||
@ -267,29 +285,26 @@ void GrResourceCache::notifyPurgeable(GrGpuResource* resource) {
|
||||
if (!resource->cacheAccess().isWrapped() &&
|
||||
resource->resourcePriv().getScratchKey().isValid()) {
|
||||
// We won't purge an existing resource to make room for this one.
|
||||
bool underBudget = fBudgetedCount < fMaxCount &&
|
||||
fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes;
|
||||
if (underBudget) {
|
||||
if (fBudgetedCount < fMaxCount &&
|
||||
fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) {
|
||||
resource->resourcePriv().makeBudgeted();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Purge the resource immediately if we're over budget
|
||||
bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
|
||||
|
||||
// Also purge if the resource has neither a valid scratch key nor a content key.
|
||||
bool noKey = !resource->resourcePriv().getScratchKey().isValid() &&
|
||||
!resource->getContentKey().isValid();
|
||||
if (!overBudget && !noKey) {
|
||||
!resource->getContentKey().isValid();
|
||||
if (!this->overBudget() && !noKey) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkDEBUGCODE(int beforeCount = fCount;)
|
||||
SkDEBUGCODE(int beforeCount = this->getResourceCount();)
|
||||
resource->cacheAccess().release();
|
||||
// We should at least free this resource, perhaps dependent resources as well.
|
||||
SkASSERT(fCount < beforeCount);
|
||||
SkASSERT(this->getResourceCount() < beforeCount);
|
||||
this->validate();
|
||||
}
|
||||
|
||||
@ -338,14 +353,14 @@ void GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) {
|
||||
}
|
||||
|
||||
void GrResourceCache::internalPurgeAsNeeded() {
|
||||
SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
|
||||
SkASSERT(this->overBudget());
|
||||
|
||||
bool stillOverbudget = true;
|
||||
while (fPurgeableQueue.count()) {
|
||||
GrGpuResource* resource = fPurgeableQueue.peek();
|
||||
SkASSERT(resource->isPurgeable());
|
||||
resource->cacheAccess().release();
|
||||
if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
|
||||
if (!this->overBudget()) {
|
||||
stillOverbudget = false;
|
||||
break;
|
||||
}
|
||||
@ -384,6 +399,24 @@ void GrResourceCache::processInvalidContentKeys(
|
||||
}
|
||||
}
|
||||
|
||||
void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) {
|
||||
int index = fNonpurgeableResources.count();
|
||||
*fNonpurgeableResources.append() = resource;
|
||||
*resource->cacheAccess().accessCacheIndex() = index;
|
||||
}
|
||||
|
||||
void GrResourceCache::removeFromNonpurgeableArray(GrGpuResource* resource) {
|
||||
int* index = resource->cacheAccess().accessCacheIndex();
|
||||
// Fill the whole we will create in the array with the tail object, adjust its index, and
|
||||
// then pop the array
|
||||
GrGpuResource* tail = *(fNonpurgeableResources.end() - 1);
|
||||
SkASSERT(fNonpurgeableResources[*index] == resource);
|
||||
fNonpurgeableResources[*index] = tail;
|
||||
*tail->cacheAccess().accessCacheIndex() = *index;
|
||||
fNonpurgeableResources.pop();
|
||||
SkDEBUGCODE(*index = -1);
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void GrResourceCache::validate() const {
|
||||
// Reduce the frequency of validations for large resource counts.
|
||||
@ -393,80 +426,108 @@ void GrResourceCache::validate() const {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytes = 0;
|
||||
int count = 0;
|
||||
int budgetedCount = 0;
|
||||
size_t budgetedBytes = 0;
|
||||
int locked = 0;
|
||||
int scratch = 0;
|
||||
int couldBeScratch = 0;
|
||||
int content = 0;
|
||||
struct Stats {
|
||||
size_t fBytes;
|
||||
int fBudgetedCount;
|
||||
size_t fBudgetedBytes;
|
||||
int fLocked;
|
||||
int fScratch;
|
||||
int fCouldBeScratch;
|
||||
int fContent;
|
||||
const ScratchMap* fScratchMap;
|
||||
const ContentHash* fContentHash;
|
||||
|
||||
ResourceList::Iter iter;
|
||||
GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
|
||||
for ( ; resource; resource = iter.next()) {
|
||||
bytes += resource->gpuMemorySize();
|
||||
++count;
|
||||
|
||||
if (!resource->isPurgeable()) {
|
||||
++locked;
|
||||
Stats(const GrResourceCache* cache) {
|
||||
memset(this, 0, sizeof(*this));
|
||||
fScratchMap = &cache->fScratchMap;
|
||||
fContentHash = &cache->fContentHash;
|
||||
}
|
||||
|
||||
if (resource->cacheAccess().isScratch()) {
|
||||
SkASSERT(!resource->getContentKey().isValid());
|
||||
++scratch;
|
||||
SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratchKey()));
|
||||
SkASSERT(!resource->cacheAccess().isWrapped());
|
||||
} else if (resource->resourcePriv().getScratchKey().isValid()) {
|
||||
SkASSERT(!resource->resourcePriv().isBudgeted() ||
|
||||
resource->getContentKey().isValid());
|
||||
++couldBeScratch;
|
||||
SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratchKey()));
|
||||
SkASSERT(!resource->cacheAccess().isWrapped());
|
||||
}
|
||||
const GrContentKey& contentKey = resource->getContentKey();
|
||||
if (contentKey.isValid()) {
|
||||
++content;
|
||||
SkASSERT(fContentHash.find(contentKey) == resource);
|
||||
SkASSERT(!resource->cacheAccess().isWrapped());
|
||||
SkASSERT(resource->resourcePriv().isBudgeted());
|
||||
}
|
||||
void update(GrGpuResource* resource) {
|
||||
fBytes += resource->gpuMemorySize();
|
||||
|
||||
if (resource->resourcePriv().isBudgeted()) {
|
||||
++budgetedCount;
|
||||
budgetedBytes += resource->gpuMemorySize();
|
||||
}
|
||||
if (!resource->isPurgeable()) {
|
||||
++fLocked;
|
||||
}
|
||||
|
||||
if (!resource->isPurgeable()) {
|
||||
SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex());
|
||||
if (resource->cacheAccess().isScratch()) {
|
||||
SkASSERT(!resource->getContentKey().isValid());
|
||||
++fScratch;
|
||||
SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
|
||||
SkASSERT(!resource->cacheAccess().isWrapped());
|
||||
} else if (resource->resourcePriv().getScratchKey().isValid()) {
|
||||
SkASSERT(!resource->resourcePriv().isBudgeted() ||
|
||||
resource->getContentKey().isValid());
|
||||
++fCouldBeScratch;
|
||||
SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
|
||||
SkASSERT(!resource->cacheAccess().isWrapped());
|
||||
}
|
||||
const GrContentKey& contentKey = resource->getContentKey();
|
||||
if (contentKey.isValid()) {
|
||||
++fContent;
|
||||
SkASSERT(fContentHash->find(contentKey) == resource);
|
||||
SkASSERT(!resource->cacheAccess().isWrapped());
|
||||
SkASSERT(resource->resourcePriv().isBudgeted());
|
||||
}
|
||||
|
||||
if (resource->resourcePriv().isBudgeted()) {
|
||||
++fBudgetedCount;
|
||||
fBudgetedBytes += resource->gpuMemorySize();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Stats stats(this);
|
||||
|
||||
for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
|
||||
SkASSERT(!fNonpurgeableResources[i]->isPurgeable());
|
||||
SkASSERT(*fNonpurgeableResources[i]->cacheAccess().accessCacheIndex() == i);
|
||||
SkASSERT(!fNonpurgeableResources[i]->wasDestroyed());
|
||||
stats.update(fNonpurgeableResources[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fPurgeableQueue.count(); ++i) {
|
||||
SkASSERT(fPurgeableQueue.at(i)->isPurgeable());
|
||||
SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i);
|
||||
SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed());
|
||||
stats.update(fPurgeableQueue.at(i));
|
||||
}
|
||||
|
||||
SkASSERT(fCount - locked == fPurgeableQueue.count());
|
||||
SkASSERT(fCount == this->getResourceCount());
|
||||
SkASSERT(fBudgetedCount <= fCount);
|
||||
SkASSERT(fBudgetedBytes <= fBudgetedBytes);
|
||||
SkASSERT(bytes == fBytes);
|
||||
SkASSERT(count == fCount);
|
||||
SkASSERT(budgetedBytes == fBudgetedBytes);
|
||||
SkASSERT(budgetedCount == fBudgetedCount);
|
||||
SkASSERT(fBudgetedBytes <= fBytes);
|
||||
SkASSERT(stats.fBytes == fBytes);
|
||||
SkASSERT(stats.fBudgetedBytes == fBudgetedBytes);
|
||||
SkASSERT(stats.fBudgetedCount == fBudgetedCount);
|
||||
#if GR_CACHE_STATS
|
||||
SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
|
||||
SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
|
||||
SkASSERT(bytes <= fHighWaterBytes);
|
||||
SkASSERT(count <= fHighWaterCount);
|
||||
SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
|
||||
SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
|
||||
SkASSERT(fBytes <= fHighWaterBytes);
|
||||
SkASSERT(fCount <= fHighWaterCount);
|
||||
SkASSERT(fBudgetedBytes <= fBudgetedHighWaterBytes);
|
||||
SkASSERT(fBudgetedCount <= fBudgetedHighWaterCount);
|
||||
#endif
|
||||
SkASSERT(content == fContentHash.count());
|
||||
SkASSERT(scratch + couldBeScratch == fScratchMap.count());
|
||||
SkASSERT(stats.fContent == fContentHash.count());
|
||||
SkASSERT(stats.fScratch + stats.fCouldBeScratch == fScratchMap.count());
|
||||
|
||||
// This assertion is not currently valid because we can be in recursive notifyIsPurgeable()
|
||||
// calls. This will be fixed when subresource registration is explicit.
|
||||
// bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
|
||||
// SkASSERT(!overBudget || locked == count || fPurging);
|
||||
}
|
||||
|
||||
bool GrResourceCache::isInCache(const GrGpuResource* resource) const {
|
||||
int index = *resource->cacheAccess().accessCacheIndex();
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource) {
|
||||
return true;
|
||||
}
|
||||
if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) {
|
||||
return true;
|
||||
}
|
||||
SkDEBUGFAIL("Resource index should be -1 or the resource should be in the cache.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -55,7 +55,9 @@ public:
|
||||
/**
|
||||
* Returns the number of resources.
|
||||
*/
|
||||
int getResourceCount() const { return fCount; }
|
||||
int getResourceCount() const {
|
||||
return fPurgeableQueue.count() + fNonpurgeableResources.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of resources that count against the budget.
|
||||
@ -185,9 +187,12 @@ private:
|
||||
|
||||
void internalPurgeAsNeeded();
|
||||
void processInvalidContentKeys(const SkTArray<GrContentKeyInvalidatedMessage>&);
|
||||
void addToNonpurgeableArray(GrGpuResource*);
|
||||
void removeFromNonpurgeableArray(GrGpuResource*);
|
||||
bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCount > fMaxCount; }
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
bool isInCache(const GrGpuResource* r) const { return fResources.isInList(r); }
|
||||
bool isInCache(const GrGpuResource* r) const;
|
||||
void validate() const;
|
||||
#else
|
||||
void validate() const {}
|
||||
@ -215,8 +220,6 @@ private:
|
||||
};
|
||||
typedef SkTDynamicHash<GrGpuResource, GrContentKey, ContentHashTraits> ContentHash;
|
||||
|
||||
typedef SkTInternalLList<GrGpuResource> ResourceList;
|
||||
|
||||
static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) {
|
||||
return a->cacheAccess().timestamp() < b->cacheAccess().timestamp();
|
||||
}
|
||||
@ -227,15 +230,14 @@ private:
|
||||
|
||||
typedef SkMessageBus<GrContentKeyInvalidatedMessage>::Inbox InvalidContentKeyInbox;
|
||||
typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue;
|
||||
typedef SkTDArray<GrGpuResource*> ResourceArray;
|
||||
|
||||
// Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is
|
||||
// assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the
|
||||
// purgeable resources by this value, and thus is used to purge resources in LRU order.
|
||||
uint32_t fTimestamp;
|
||||
PurgeableQueue fPurgeableQueue;
|
||||
|
||||
// TODO: Replace this with an array of nonpurgeable resources
|
||||
ResourceList fResources;
|
||||
ResourceArray fNonpurgeableResources;
|
||||
|
||||
// This map holds all resources that can be used as scratch resources.
|
||||
ScratchMap fScratchMap;
|
||||
@ -254,7 +256,7 @@ private:
|
||||
#endif
|
||||
|
||||
// our current stats for all resources
|
||||
int fCount;
|
||||
SkDEBUGCODE(int fCount;)
|
||||
size_t fBytes;
|
||||
|
||||
// our current stats for resources that count against the budget
|
||||
|
@ -79,27 +79,35 @@ void GrGpu::Stats::dump(SkString* out) {
|
||||
void GrResourceCache::dumpStats(SkString* out) const {
|
||||
this->validate();
|
||||
|
||||
int locked = 0;
|
||||
int scratch = 0;
|
||||
int wrapped = 0;
|
||||
size_t unbudgetedSize = 0;
|
||||
int locked = fNonpurgeableResources.count();
|
||||
|
||||
ResourceList::Iter iter;
|
||||
GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
|
||||
struct Stats {
|
||||
int fScratch;
|
||||
int fWrapped;
|
||||
size_t fUnbudgetedSize;
|
||||
|
||||
for ( ; resource; resource = iter.next()) {
|
||||
if (!resource->isPurgeable()) {
|
||||
++locked;
|
||||
}
|
||||
if (resource->cacheAccess().isScratch()) {
|
||||
++scratch;
|
||||
}
|
||||
if (resource->cacheAccess().isWrapped()) {
|
||||
++wrapped;
|
||||
}
|
||||
if (!resource->resourcePriv().isBudgeted()) {
|
||||
unbudgetedSize += resource->gpuMemorySize();
|
||||
Stats() : fScratch(0), fWrapped(0), fUnbudgetedSize(0) {}
|
||||
|
||||
void update(GrGpuResource* resource) {
|
||||
if (resource->cacheAccess().isScratch()) {
|
||||
++fScratch;
|
||||
}
|
||||
if (resource->cacheAccess().isWrapped()) {
|
||||
++fWrapped;
|
||||
}
|
||||
if (!resource->resourcePriv().isBudgeted()) {
|
||||
fUnbudgetedSize += resource->gpuMemorySize();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Stats stats;
|
||||
|
||||
for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
|
||||
stats.update(fNonpurgeableResources[i]);
|
||||
}
|
||||
for (int i = 0; i < fPurgeableQueue.count(); ++i) {
|
||||
stats.update(fPurgeableQueue.at(i));
|
||||
}
|
||||
|
||||
float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
|
||||
@ -108,11 +116,11 @@ void GrResourceCache::dumpStats(SkString* out) const {
|
||||
out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
|
||||
out->appendf("\t\tEntry Count: current %d"
|
||||
" (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
|
||||
fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization,
|
||||
fCount, fBudgetedCount, stats.fWrapped, locked, stats.fScratch, countUtilization,
|
||||
fHighWaterCount);
|
||||
out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
|
||||
(int)fBytes, (int)fBudgetedBytes, byteUtilization,
|
||||
(int)unbudgetedSize, (int)fHighWaterBytes);
|
||||
SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
|
||||
SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user