1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Benchmark.h"
9
10#if SK_SUPPORT_GPU
11
12#include "GrContext.h"
13#include "GrContextPriv.h"
14#include "GrGpu.h"
15#include "GrGpuResource.h"
16#include "GrGpuResourcePriv.h"
17#include "GrResourceCache.h"
18#include "SkCanvas.h"
19
20enum {
21    CACHE_SIZE_COUNT = 4096,
22};
23
24class BenchResource : public GrGpuResource {
25public:
26    BenchResource (GrGpu* gpu)
27        : INHERITED(gpu) {
28        this->registerWithCache(SkBudgeted::kYes);
29    }
30
31    static void ComputeKey(int i, int keyData32Count, GrUniqueKey* key) {
32        static GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
33        GrUniqueKey::Builder builder(key, kDomain, keyData32Count);
34        for (int j = 0; j < keyData32Count; ++j) {
35            builder[j] = i + j;
36        }
37    }
38
39private:
40    size_t onGpuMemorySize() const override { return 100; }
41    const char* getResourceType() const override { return "bench"; }
42    typedef GrGpuResource INHERITED;
43};
44
45static void populate_cache(GrGpu* gpu, int resourceCount, int keyData32Count) {
46    for (int i = 0; i < resourceCount; ++i) {
47        GrUniqueKey key;
48        BenchResource::ComputeKey(i, keyData32Count, &key);
49        GrGpuResource* resource = new BenchResource(gpu);
50        resource->resourcePriv().setUniqueKey(key);
51        resource->unref();
52    }
53}
54
55class GrResourceCacheBenchAdd : public Benchmark {
56public:
57    GrResourceCacheBenchAdd(int keyData32Count)
58        : fFullName("grresourcecache_add")
59        , fKeyData32Count(keyData32Count) {
60        if (keyData32Count > 1) {
61            fFullName.appendf("_%d", fKeyData32Count);
62        }
63    }
64
65    bool isSuitableFor(Backend backend) override {
66        return backend == kNonRendering_Backend;
67    }
68protected:
69    const char* onGetName() override {
70        return fFullName.c_str();
71    }
72
73    void onDraw(int loops, SkCanvas* canvas) override {
74        sk_sp<GrContext> context(GrContext::MakeMock(nullptr));
75        if (nullptr == context) {
76            return;
77        }
78        // Set the cache budget to be very large so no purging occurs.
79        context->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30);
80
81        GrResourceCache* cache = context->contextPriv().getResourceCache();
82
83        // Make sure the cache is empty.
84        cache->purgeAllUnlocked();
85        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
86
87        GrGpu* gpu = context->contextPriv().getGpu();
88
89        for (int i = 0; i < loops; ++i) {
90            populate_cache(gpu, CACHE_SIZE_COUNT, fKeyData32Count);
91            SkASSERT(CACHE_SIZE_COUNT == cache->getResourceCount());
92        }
93    }
94
95private:
96    SkString fFullName;
97    int fKeyData32Count;
98    typedef Benchmark INHERITED;
99};
100
101class GrResourceCacheBenchFind : public Benchmark {
102public:
103    GrResourceCacheBenchFind(int keyData32Count)
104        : fFullName("grresourcecache_find")
105        , fKeyData32Count(keyData32Count) {
106        if (keyData32Count > 1) {
107            fFullName.appendf("_%d", fKeyData32Count);
108        }
109    }
110
111    bool isSuitableFor(Backend backend) override {
112        return backend == kNonRendering_Backend;
113    }
114protected:
115    const char* onGetName() override {
116        return fFullName.c_str();
117    }
118
119    void onDelayedSetup() override {
120        fContext = GrContext::MakeMock(nullptr);
121        if (!fContext) {
122            return;
123        }
124        // Set the cache budget to be very large so no purging occurs.
125        fContext->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30);
126
127        GrResourceCache* cache = fContext->contextPriv().getResourceCache();
128
129        // Make sure the cache is empty.
130        cache->purgeAllUnlocked();
131        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
132
133        GrGpu* gpu = fContext->contextPriv().getGpu();
134
135        populate_cache(gpu, CACHE_SIZE_COUNT, fKeyData32Count);
136    }
137
138    void onDraw(int loops, SkCanvas* canvas) override {
139        if (!fContext) {
140            return;
141        }
142        GrResourceCache* cache = fContext->contextPriv().getResourceCache();
143        SkASSERT(CACHE_SIZE_COUNT == cache->getResourceCount());
144        for (int i = 0; i < loops; ++i) {
145            for (int k = 0; k < CACHE_SIZE_COUNT; ++k) {
146                GrUniqueKey key;
147                BenchResource::ComputeKey(k, fKeyData32Count, &key);
148                sk_sp<GrGpuResource> resource(cache->findAndRefUniqueResource(key));
149                SkASSERT(resource);
150            }
151        }
152    }
153
154private:
155    sk_sp<GrContext> fContext;
156    SkString fFullName;
157    int fKeyData32Count;
158    typedef Benchmark INHERITED;
159};
160
161DEF_BENCH( return new GrResourceCacheBenchAdd(1); )
162#ifdef SK_RELEASE
163// Only on release because on debug the SkTDynamicHash validation is too slow.
164DEF_BENCH( return new GrResourceCacheBenchAdd(2); )
165DEF_BENCH( return new GrResourceCacheBenchAdd(3); )
166DEF_BENCH( return new GrResourceCacheBenchAdd(4); )
167DEF_BENCH( return new GrResourceCacheBenchAdd(5); )
168DEF_BENCH( return new GrResourceCacheBenchAdd(10); )
169DEF_BENCH( return new GrResourceCacheBenchAdd(25); )
170DEF_BENCH( return new GrResourceCacheBenchAdd(54); )
171DEF_BENCH( return new GrResourceCacheBenchAdd(55); )
172DEF_BENCH( return new GrResourceCacheBenchAdd(56); )
173#endif
174
175DEF_BENCH( return new GrResourceCacheBenchFind(1); )
176#ifdef SK_RELEASE
177DEF_BENCH( return new GrResourceCacheBenchFind(2); )
178DEF_BENCH( return new GrResourceCacheBenchFind(3); )
179DEF_BENCH( return new GrResourceCacheBenchFind(4); )
180DEF_BENCH( return new GrResourceCacheBenchFind(5); )
181DEF_BENCH( return new GrResourceCacheBenchFind(10); )
182DEF_BENCH( return new GrResourceCacheBenchFind(25); )
183DEF_BENCH( return new GrResourceCacheBenchFind(54); )
184DEF_BENCH( return new GrResourceCacheBenchFind(55); )
185DEF_BENCH( return new GrResourceCacheBenchFind(56); )
186#endif
187
188#endif
189