#include "src/gpu/ganesh/GrResourceCache.h"
#include "include/core/SkString.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/private/base/SingleOwner.h"
#include "include/private/base/SkNoncopyable.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkMathPriv.h"
#include "src/base/SkRandom.h"
#include "src/base/SkTSort.h"
#include "src/core/SkMessageBus.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrGpuResourceCacheAccess.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrThreadSafeCache.h"
#include <algorithm>
#include <chrono>
#include <cstring>
#include <vector>
usingnamespaceskia_private;
DECLARE_SKMESSAGEBUS_MESSAGE(…)
DECLARE_SKMESSAGEBUS_MESSAGE(…)
#define ASSERT_SINGLE_OWNER …
class GrResourceCache::AutoValidate : ::SkNoncopyable { … };
GrResourceCache::GrResourceCache(skgpu::SingleOwner* singleOwner,
GrDirectContext::DirectContextID owningContextID,
uint32_t familyID)
: … { … }
GrResourceCache::~GrResourceCache() { … }
void GrResourceCache::setLimit(size_t bytes) { … }
void GrResourceCache::insertResource(GrGpuResource* resource) { … }
void GrResourceCache::removeResource(GrGpuResource* resource) { … }
void GrResourceCache::abandonAll() { … }
void GrResourceCache::releaseAll() { … }
void GrResourceCache::refResource(GrGpuResource* resource) { … }
GrGpuResource* GrResourceCache::findAndRefScratchResource(const skgpu::ScratchKey& scratchKey) { … }
void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { … }
void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { … }
void GrResourceCache::changeUniqueKey(GrGpuResource* resource, const skgpu::UniqueKey& newKey) { … }
void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { … }
void GrResourceCache::notifyARefCntReachedZero(GrGpuResource* resource,
GrGpuResource::LastRemovedRef removedRef) { … }
void GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) { … }
void GrResourceCache::purgeAsNeeded() { … }
void GrResourceCache::purgeUnlockedResources(const skgpu::StdSteadyClock::time_point* purgeTime,
GrPurgeResourceOptions opts) { … }
bool GrResourceCache::purgeToMakeHeadroom(size_t desiredHeadroomBytes) { … }
void GrResourceCache::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) { … }
bool GrResourceCache::requestsFlush() const { … }
void GrResourceCache::processFreedGpuResources() { … }
void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) { … }
void GrResourceCache::removeFromNonpurgeableArray(GrGpuResource* resource) { … }
uint32_t GrResourceCache::getNextTimestamp() { … }
void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { … }
#if GR_CACHE_STATS
void GrResourceCache::getStats(Stats* stats) const { … }
#if defined(GPU_TEST_UTILS)
void GrResourceCache::dumpStats(SkString* out) const {
this->validate();
Stats stats;
this->getStats(&stats);
float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
out->appendf("Budget: %d bytes\n", (int)fMaxBytes);
out->appendf("\t\tEntry Count: current %d"
" (%d budgeted, %d wrapped, %d locked, %d scratch), high %d\n",
stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
stats.fScratch, fHighWaterCount);
out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
}
void GrResourceCache::dumpStatsKeyValuePairs(TArray<SkString>* keys,
TArray<double>* values) const {
this->validate();
Stats stats;
this->getStats(&stats);
keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
}
#endif
#endif
#ifdef SK_DEBUG
void GrResourceCache::validate() const { … }
bool GrResourceCache::isInCache(const GrGpuResource* resource) const { … }
#endif
#if defined(GPU_TEST_UTILS)
int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
int count = 0;
fUniqueHash.foreach([&](const GrGpuResource& resource){
if (0 == strcmp(tag, resource.getUniqueKey().tag())) {
++count;
}
});
return count;
}
void GrResourceCache::changeTimestamp(uint32_t newTimestamp) {
fTimestamp = newTimestamp;
}
void GrResourceCache::visitSurfaces(
const std::function<void(const GrSurface*, bool purgeable)>& func) const {
for (int i = 0; i < fNonpurgeableResources.size(); ++i) {
if (const GrSurface* surf = fNonpurgeableResources[i]->asSurface()) {
func(surf, false);
}
}
for (int i = 0; i < fPurgeableQueue.count(); ++i) {
if (const GrSurface* surf = fPurgeableQueue.at(i)->asSurface()) {
func(surf, true);
}
}
}
#endif