Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1059)

Side by Side Diff: bench/ImageCacheBudgetBench.cpp

Issue 2317263002: Benchmarks for testing GrResourceCache replacement policy when over budget. (Closed)
Patch Set: fix uninit warning Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 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 #include "GrContext.h"
10 #include "sk_tool_utils.h"
11 #include "SkCanvas.h"
12 #include "SkImage.h"
13 #include "SkSurface.h"
14
15 /** These benchmarks were designed to measure changes to GrResourceCache's repla cement policy */
16
17 //////////////////////////////////////////////////////////////////////////////
18
19 // The width/height of the images to draw. The small size underestimates the val ue of a good
20 // replacement strategy since the texture uploads are quite small. However, the effects are still
21 // significant and this lets the benchmarks complete a lot faster, especially on mobile.
22 static constexpr int kS = 25;
23
24 static void make_images(sk_sp<SkImage> imgs[], int cnt) {
25 for (int i = 0; i < cnt; ++i) {
26 SkBitmap bmp = sk_tool_utils::create_checkerboard_bitmap(kS, kS, SK_Colo rBLACK,
27 SK_ColorCYAN, 1 0);
28 imgs[i] = SkImage::MakeFromBitmap(bmp);
29 }
30 }
31
32 static void draw_image(SkCanvas* canvas, SkImage* img) {
33 // Make the paint transparent to avoid any issues of deferred tiler blending
34 // optmizations
35 SkPaint paint;
36 paint.setAlpha(0x10);
37 canvas->drawImage(img, 0, 0, &paint);
38 }
39
40 void set_cache_budget(SkCanvas* canvas, int approxImagesInBudget) {
41 // This is inexact but we attempt to figure out a baseline number of resourc es GrContext needs
42 // to render an SkImage and add one additional resource for each image we'd like to fit.
43 GrContext* context = canvas->getGrContext();
44 SkASSERT(context);
45 context->flush();
46 context->purgeAllUnlockedResources();
47 sk_sp<SkImage> image;
48 make_images(&image, 1);
49 draw_image(canvas, image.get());
50 context->flush();
51 int baselineCount;
52 context->getResourceCacheUsage(&baselineCount, nullptr);
53 baselineCount -= 1; // for the image's textures.
54 context->setResourceCacheLimits(baselineCount + approxImagesInBudget, 1 << 3 0);
55 context->purgeAllUnlockedResources();
56 }
57
58 //////////////////////////////////////////////////////////////////////////////
59
60 /**
61 * Tests repeatedly drawing the same set of images in each frame. Different inst ances of the bench
62 * run with different cache sizes and either repeat the image order each frame o r use a random
63 * order. Every variation of this bench draws the same image set, only the budge t and order of
64 * images differs. Since the total fill is the same they can be cross-compared.
65 */
66 class ImageCacheBudgetBench : public Benchmark {
67 public:
68 /** budgetSize is the number of images that can fit in the cache. 100 images will be drawn. */
69 ImageCacheBudgetBench(int budgetSize, bool shuffle)
70 : fBudgetSize(budgetSize)
71 , fShuffle(shuffle)
72 , fIndices(nullptr) {
73 float imagesOverBudget = float(kImagesToDraw) / budgetSize;
74 // Make the benchmark name contain the percentage of the budget that is used in each
75 // simulated frame.
76 fName.printf("image_cache_budget_%.0f%s", imagesOverBudget * 100,
77 (shuffle ? "_shuffle" : ""));
78 }
79
80 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backen d; }
81
82 protected:
83 const char* onGetName() override {
84 return fName.c_str();
85 }
86
87 void onPerCanvasPreDraw(SkCanvas* canvas) override {
88 GrContext* context = canvas->getGrContext();
89 SkASSERT(context);
90 context->getResourceCacheLimits(&fOldCount, &fOldBytes);
91 set_cache_budget(canvas, fBudgetSize);
92 make_images(fImages, kImagesToDraw);
93 if (fShuffle) {
94 SkRandom random;
95 fIndices.reset(new int[kSimulatedFrames * kImagesToDraw]);
96 for (int frame = 0; frame < kSimulatedFrames; ++frame) {
97 int* base = fIndices.get() + frame * kImagesToDraw;
98 for (int i = 0; i < kImagesToDraw; ++i) {
99 base[i] = i;
100 }
101 for (int i = 0; i < kImagesToDraw - 1; ++i) {
102 int other = random.nextULessThan(kImagesToDraw - i) + i;
103 SkTSwap(base[i], base[other]);
104 }
105 }
106 }
107 }
108
109 void onPerCanvasPostDraw(SkCanvas* canvas) override {
110 GrContext* context = canvas->getGrContext();
111 SkASSERT(context);
112 context->setResourceCacheLimits(fOldCount, fOldBytes);
113 for (int i = 0; i < kImagesToDraw; ++i) {
114 fImages[i].reset();
115 }
116 fIndices.reset(nullptr);
117 }
118
119 void onDraw(int loops, SkCanvas* canvas) override {
120 for (int i = 0; i < loops; ++i) {
121 for (int frame = 0; frame < kSimulatedFrames; ++frame) {
122 for (int j = 0; j < kImagesToDraw; ++j) {
123 int idx;
124 if (fShuffle) {
125 idx = fIndices[frame * kImagesToDraw + j];
126 } else {
127 idx = j;
128 }
129 draw_image(canvas, fImages[idx].get());
130 }
131 // Simulate a frame boundary by flushing. This should notify GrR esourceCache.
132 canvas->flush();
133 }
134 }
135 }
136
137 private:
138 static constexpr int kImagesToDraw = 100;
139 static constexpr int kSimulatedFrames = 5;
140
141 int fBudgetSize;
142 bool fShuffle;
143 SkString fName;
144 sk_sp<SkImage> fImages[kImagesToDraw];
145 SkAutoTDeleteArray<int> fIndices;
146 size_t fOldBytes;
147 int fOldCount;
148
149 typedef Benchmark INHERITED;
150 };
151
152 DEF_BENCH( return new ImageCacheBudgetBench(105, false); )
153
154 DEF_BENCH( return new ImageCacheBudgetBench(90, false); )
155
156 DEF_BENCH( return new ImageCacheBudgetBench(80, false); )
157
158 DEF_BENCH( return new ImageCacheBudgetBench(50, false); )
159
160 DEF_BENCH( return new ImageCacheBudgetBench(105, true); )
161
162 DEF_BENCH( return new ImageCacheBudgetBench(90, true); )
163
164 DEF_BENCH( return new ImageCacheBudgetBench(80, true); )
165
166 DEF_BENCH( return new ImageCacheBudgetBench(50, true); )
167
168 //////////////////////////////////////////////////////////////////////////////
169
170 /**
171 * Similar to above but changes between being over and under budget by varying t he number of images
172 * rendered. This is not directly comparable to the non-dynamic benchmarks.
173 */
174 class ImageCacheBudgetDynamicBench : public Benchmark {
175 public:
176 enum class Mode {
177 // Increase from min to max images drawn gradually over simulated frames and then back.
178 kPingPong,
179 // Alternate between under and over budget every other simulated frame.
180 kFlipFlop
181 };
182
183 ImageCacheBudgetDynamicBench(Mode mode) : fMode(mode) {}
184
185 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backen d; }
186
187 protected:
188 const char* onGetName() override {
189 switch (fMode) {
190 case Mode::kPingPong:
191 return "image_cache_budget_dynamic_ping_pong";
192 case Mode::kFlipFlop:
193 return "image_cache_budget_dynamic_flip_flop";
194 }
195 return "";
196 }
197
198 void onPerCanvasPreDraw(SkCanvas* canvas) override {
199 GrContext* context = canvas->getGrContext();
200 SkASSERT(context);
201 context->getResourceCacheLimits(&fOldCount, &fOldBytes);
202 make_images(fImages, kMaxImagesToDraw);
203 set_cache_budget(canvas, kImagesInBudget);
204 }
205
206 void onPerCanvasPostDraw(SkCanvas* canvas) override {
207 GrContext* context = canvas->getGrContext();
208 SkASSERT(context);
209 context->setResourceCacheLimits(fOldCount, fOldBytes);
210 for (int i = 0; i < kMaxImagesToDraw; ++i) {
211 fImages[i].reset();
212 }
213 }
214
215 void onDraw(int loops, SkCanvas* canvas) override {
216 int delta = 0;
217 switch (fMode) {
218 case Mode::kPingPong:
219 delta = 1;
220 break;
221 case Mode::kFlipFlop:
222 delta = kMaxImagesToDraw - kMinImagesToDraw;
223 break;
224 }
225 for (int i = 0; i < loops; ++i) {
226 int imgsToDraw = kMinImagesToDraw;
227 for (int frame = 0; frame < kSimulatedFrames; ++frame) {
228 for (int j = 0; j < imgsToDraw; ++j) {
229 draw_image(canvas, fImages[j].get());
230 }
231 imgsToDraw += delta;
232 if (imgsToDraw > kMaxImagesToDraw || imgsToDraw < kMinImagesToDr aw) {
233 delta = -delta;
234 imgsToDraw += 2 * delta;
235 }
236 // Simulate a frame boundary by flushing. This should notify GrR esourceCache.
237 canvas->flush();
238 }
239 }
240 }
241
242 private:
243 static constexpr int kImagesInBudget = 25;
244 static constexpr int kMinImagesToDraw = 15;
245 static constexpr int kMaxImagesToDraw = 35;
246 static constexpr int kSimulatedFrames = 80;
247
248 Mode fMode;
249 sk_sp<SkImage> fImages[kMaxImagesToDraw];
250 size_t fOldBytes;
251 int fOldCount;
252
253 typedef Benchmark INHERITED;
254 };
255
256 DEF_BENCH( return new ImageCacheBudgetDynamicBench(ImageCacheBudgetDynamicBench: :Mode::kPingPong); )
257 DEF_BENCH( return new ImageCacheBudgetDynamicBench(ImageCacheBudgetDynamicBench: :Mode::kFlipFlop); )
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698