/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Benchmark.h" #if SK_SUPPORT_GPU #include "GrGpuResource.h" #include "GrGpuResourcePriv.h" #include "GrContext.h" #include "GrGpu.h" #include "GrResourceCache.h" #include "SkCanvas.h" enum { CACHE_SIZE_COUNT = 4096, }; class BenchResource : public GrGpuResource { public: SK_DECLARE_INST_COUNT(BenchResource); BenchResource (GrGpu* gpu) : INHERITED(gpu, kCached_LifeCycle) { this->registerWithCache(); } static void ComputeKey(int i, GrUniqueKey* key) { static GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey::Builder builder(key, kDomain, 1); builder[0] = i; } private: size_t onGpuMemorySize() const override { return 100; } typedef GrGpuResource INHERITED; }; static void populate_cache(GrGpu* gpu, int resourceCount) { for (int i = 0; i < resourceCount; ++i) { GrUniqueKey key; BenchResource::ComputeKey(i, &key); GrGpuResource* resource = SkNEW_ARGS(BenchResource, (gpu)); resource->resourcePriv().setUniqueKey(key); resource->unref(); } } class GrResourceCacheBenchAdd : public Benchmark { public: bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } protected: const char* onGetName() override { return "grresourcecache_add"; } void onDraw(const int loops, SkCanvas* canvas) override { SkAutoTUnref<GrContext> context(GrContext::CreateMockContext()); if (NULL == context) { return; } // Set the cache budget to be very large so no purging occurs. context->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30); GrResourceCache* cache = context->getResourceCache(); // Make sure the cache is empty. cache->purgeAllUnlocked(); SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes()); GrGpu* gpu = context->getGpu(); for (int i = 0; i < loops; ++i) { populate_cache(gpu, CACHE_SIZE_COUNT); SkASSERT(CACHE_SIZE_COUNT == cache->getResourceCount()); } } private: typedef Benchmark INHERITED; }; class GrResourceCacheBenchFind : public Benchmark { public: bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } protected: const char* onGetName() override { return "grresourcecache_find"; } void onPreDraw() override { fContext.reset(GrContext::CreateMockContext()); if (!fContext) { return; } // Set the cache budget to be very large so no purging occurs. fContext->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30); GrResourceCache* cache = fContext->getResourceCache(); // Make sure the cache is empty. cache->purgeAllUnlocked(); SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes()); GrGpu* gpu = fContext->getGpu(); populate_cache(gpu, CACHE_SIZE_COUNT); } void onDraw(const int loops, SkCanvas* canvas) override { if (!fContext) { return; } GrResourceCache* cache = fContext->getResourceCache(); SkASSERT(CACHE_SIZE_COUNT == cache->getResourceCount()); for (int i = 0; i < loops; ++i) { for (int k = 0; k < CACHE_SIZE_COUNT; ++k) { GrUniqueKey key; BenchResource::ComputeKey(k, &key); SkAutoTUnref<GrGpuResource> resource(cache->findAndRefUniqueResource(key)); SkASSERT(resource); } } } private: SkAutoTUnref<GrContext> fContext; typedef Benchmark INHERITED; }; DEF_BENCH( return new GrResourceCacheBenchAdd(); ) DEF_BENCH( return new GrResourceCacheBenchFind(); ) #endif