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