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 
20 enum {
21     CACHE_SIZE_COUNT = 4096,
22 };
23 
24 class BenchResource : public GrGpuResource {
25 public:
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 
39 private:
40     size_t onGpuMemorySize() const override { return 100; }
41     const char* getResourceType() const override { return "bench"; }
42     typedef GrGpuResource INHERITED;
43 };
44 
45 static 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 
55 class GrResourceCacheBenchAdd : public Benchmark {
56 public:
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     }
68 protected:
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 
95 private:
96     SkString fFullName;
97     int fKeyData32Count;
98     typedef Benchmark INHERITED;
99 };
100 
101 class GrResourceCacheBenchFind : public Benchmark {
102 public:
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     }
114 protected:
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 
154 private:
155     sk_sp<GrContext> fContext;
156     SkString fFullName;
157     int fKeyData32Count;
158     typedef Benchmark INHERITED;
159 };
160 
161 DEF_BENCH( return new GrResourceCacheBenchAdd(1); )
162 #ifdef SK_RELEASE
163 // Only on release because on debug the SkTDynamicHash validation is too slow.
164 DEF_BENCH( return new GrResourceCacheBenchAdd(2); )
165 DEF_BENCH( return new GrResourceCacheBenchAdd(3); )
166 DEF_BENCH( return new GrResourceCacheBenchAdd(4); )
167 DEF_BENCH( return new GrResourceCacheBenchAdd(5); )
168 DEF_BENCH( return new GrResourceCacheBenchAdd(10); )
169 DEF_BENCH( return new GrResourceCacheBenchAdd(25); )
170 DEF_BENCH( return new GrResourceCacheBenchAdd(54); )
171 DEF_BENCH( return new GrResourceCacheBenchAdd(55); )
172 DEF_BENCH( return new GrResourceCacheBenchAdd(56); )
173 #endif
174 
175 DEF_BENCH( return new GrResourceCacheBenchFind(1); )
176 #ifdef SK_RELEASE
177 DEF_BENCH( return new GrResourceCacheBenchFind(2); )
178 DEF_BENCH( return new GrResourceCacheBenchFind(3); )
179 DEF_BENCH( return new GrResourceCacheBenchFind(4); )
180 DEF_BENCH( return new GrResourceCacheBenchFind(5); )
181 DEF_BENCH( return new GrResourceCacheBenchFind(10); )
182 DEF_BENCH( return new GrResourceCacheBenchFind(25); )
183 DEF_BENCH( return new GrResourceCacheBenchFind(54); )
184 DEF_BENCH( return new GrResourceCacheBenchFind(55); )
185 DEF_BENCH( return new GrResourceCacheBenchFind(56); )
186 #endif
187 
188 #endif
189