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

Side by Side Diff: tools/VisualBench/VisualBench.cpp

Issue 1304083007: Create module system for VisualBench (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: feedback inc Created 5 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 | « tools/VisualBench/VisualBench.h ('k') | tools/VisualBench/VisualFlags.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 * 6 *
7 */ 7 */
8 8
9 #include "VisualBench.h" 9 #include "VisualBench.h"
10 10
11 #include "ProcStats.h" 11 #include "ProcStats.h"
12 #include "SkApplication.h" 12 #include "SkApplication.h"
13 #include "SkCanvas.h" 13 #include "SkCanvas.h"
14 #include "SkCommandLineFlags.h" 14 #include "SkCommandLineFlags.h"
15 #include "SkForceLinking.h"
16 #include "SkGraphics.h" 15 #include "SkGraphics.h"
17 #include "SkGr.h" 16 #include "SkGr.h"
18 #include "SkImageDecoder.h"
19 #include "SkOSFile.h" 17 #include "SkOSFile.h"
20 #include "SkStream.h" 18 #include "SkStream.h"
21 #include "Stats.h" 19 #include "Stats.h"
20 #include "VisualLightweightBenchModule.h"
22 #include "gl/GrGLInterface.h" 21 #include "gl/GrGLInterface.h"
23 22
24 __SK_FORCE_IMAGE_DECODER_LINKING;
25
26 // Between samples we reset context
27 // Between frames we swap buffers
28 // Between flushes we call flush on GrContext
29
30 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allow s to lag.");
31 DEFINE_int32(samples, 10, "Number of times to time each skp.");
32 DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample.");
33 DEFINE_double(loopMs, 5, "Target loop time in millseconds.");
34 DEFINE_int32(msaa, 0, "Number of msaa samples.");
35 DEFINE_bool2(fullscreen, f, true, "Run fullscreen."); 23 DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
36 DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
37 DEFINE_string(key, "", ""); // dummy to enable gm tests that have platform-spec ific names
38 DEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
39 DEFINE_string(properties, "",
40 "Space-separated key/value pairs to add to JSON identifying this r un.");
41
42 static SkString humanize(double ms) {
43 if (FLAGS_verbose) {
44 return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
45 }
46 return HumanizeMs(ms);
47 }
48
49 #define HUMANIZE(time) humanize(time).c_str()
50 24
51 VisualBench::VisualBench(void* hwnd, int argc, char** argv) 25 VisualBench::VisualBench(void* hwnd, int argc, char** argv)
52 : INHERITED(hwnd) 26 : INHERITED(hwnd)
53 , fCurrentSample(0) 27 , fModule(new VisualLightweightBenchModule(this)) {
54 , fCurrentFrame(0)
55 , fLoops(1)
56 , fState(kPreWarmLoops_State)
57 , fBenchmark(nullptr)
58 , fResults(new ResultsWriter) {
59 SkCommandLineFlags::Parse(argc, argv); 28 SkCommandLineFlags::Parse(argc, argv);
60 29
61 this->setTitle(); 30 this->setTitle();
62 this->setupBackend(); 31 this->setupBackend();
63
64 fBenchmarkStream.reset(new VisualBenchmarkStream);
65
66 // Print header
67 SkDebugf("curr/maxrss\tloops\tflushes\tmin\tmedian\tmean\tmax\tstddev\tbench \n");
68
69 // setup json logging if required
70 if (!FLAGS_outResultsFile.isEmpty()) {
71 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
72 }
73
74 if (1 == FLAGS_properties.count() % 2) {
75 SkDebugf("ERROR: --properties must be passed with an even number of argu ments.\n");
76 } else {
77 for (int i = 1; i < FLAGS_properties.count(); i += 2) {
78 fResults->property(FLAGS_properties[i - 1], FLAGS_properties[i]);
79 }
80 }
81 } 32 }
82 33
83 VisualBench::~VisualBench() { 34 VisualBench::~VisualBench() {
84 INHERITED::detach(); 35 INHERITED::detach();
85 } 36 }
86 37
87 void VisualBench::setTitle() { 38 void VisualBench::setTitle() {
88 SkString title("VisualBench"); 39 SkString title("VisualBench");
89 INHERITED::setTitle(title.c_str()); 40 INHERITED::setTitle(title.c_str());
90 } 41 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 // setup rendertargets 84 // setup rendertargets
134 this->setupRenderTarget(); 85 this->setupRenderTarget();
135 } 86 }
136 87
137 void VisualBench::setupRenderTarget() { 88 void VisualBench::setupRenderTarget() {
138 if (fContext) { 89 if (fContext) {
139 fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fCon text)); 90 fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fCon text));
140 } 91 }
141 } 92 }
142 93
143 inline void VisualBench::renderFrame(SkCanvas* canvas) {
144 fBenchmark->draw(fLoops, canvas);
145 canvas->flush();
146 INHERITED::present();
147 }
148
149 void VisualBench::printStats() {
150 const SkTArray<double>& measurements = fRecords.back().fMeasurements;
151 const char* shortName = fBenchmark->getUniqueName();
152
153 // update log
154 // Note: We currently log only the minimum. It would be interesting to log more information
155 SkString configName;
156 if (FLAGS_msaa > 0) {
157 configName.appendf("msaa_%d", FLAGS_msaa);
158 } else {
159 configName.appendf("gpu");
160 }
161 fResults->config(configName.c_str());
162 fResults->configOption("name", fBenchmark->getUniqueName());
163 SkASSERT(measurements.count());
164 Stats stats(measurements);
165 fResults->metric("min_ms", stats.min);
166
167 // Print output
168 if (FLAGS_verbose) {
169 for (int i = 0; i < measurements.count(); i++) {
170 SkDebugf("%s ", HUMANIZE(measurements[i]));
171 }
172 SkDebugf("%s\n", shortName);
173 } else {
174 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean;
175 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\n",
176 sk_tools::getCurrResidentSetSizeMB(),
177 sk_tools::getMaxResidentSetSizeMB(),
178 fLoops,
179 HUMANIZE(stats.min),
180 HUMANIZE(stats.median),
181 HUMANIZE(stats.mean),
182 HUMANIZE(stats.max),
183 stdDevPercent,
184 shortName);
185 }
186 }
187
188 bool VisualBench::advanceRecordIfNecessary(SkCanvas* canvas) {
189 if (fBenchmark) {
190 return true;
191 }
192
193 fBenchmark.reset(fBenchmarkStream->next());
194 if (!fBenchmark) {
195 return false;
196 }
197
198 canvas->clear(0xffffffff);
199 fBenchmark->preDraw();
200 fRecords.push_back();
201
202 // Log bench name
203 fResults->bench(fBenchmark->getUniqueName(), fBenchmark->getSize().fX,
204 fBenchmark->getSize().fY);
205 return true;
206 }
207
208 inline void VisualBench::nextState(State nextState) {
209 fState = nextState;
210 }
211
212 void VisualBench::perCanvasPreDraw(SkCanvas* canvas, State nextState) {
213 fBenchmark->perCanvasPreDraw(canvas);
214 fCurrentFrame = 0;
215 this->nextState(nextState);
216 }
217
218 void VisualBench::preWarm(State nextState) {
219 if (fCurrentFrame >= FLAGS_gpuFrameLag) {
220 // we currently time across all frames to make sure we capture all GPU w ork
221 this->nextState(nextState);
222 fCurrentFrame = 0;
223 fTimer.start();
224 } else {
225 fCurrentFrame++;
226 }
227 }
228
229 void VisualBench::draw(SkCanvas* canvas) { 94 void VisualBench::draw(SkCanvas* canvas) {
230 if (!this->advanceRecordIfNecessary(canvas)) { 95 fModule->draw(canvas);
231 SkDebugf("Exiting VisualBench successfully\n");
232 this->closeWindow();
233 return;
234 }
235 this->renderFrame(canvas);
236 switch (fState) {
237 case kPreWarmLoopsPerCanvasPreDraw_State: {
238 this->perCanvasPreDraw(canvas, kPreWarmLoops_State);
239 break;
240 }
241 case kPreWarmLoops_State: {
242 this->preWarm(kTuneLoops_State);
243 break;
244 }
245 case kTuneLoops_State: {
246 this->tuneLoops();
247 break;
248 }
249 case kPreWarmTimingPerCanvasPreDraw_State: {
250 this->perCanvasPreDraw(canvas, kPreWarmTiming_State);
251 break;
252 }
253 case kPreWarmTiming_State: {
254 this->preWarm(kTiming_State);
255 break;
256 }
257 case kTiming_State: {
258 this->timing(canvas);
259 break;
260 }
261 }
262 96
263 // Invalidate the window to force a redraw. Poor man's animation mechanism. 97 // Invalidate the window to force a redraw. Poor man's animation mechanism.
264 this->inval(nullptr); 98 this->inval(nullptr);
265 } 99 }
266 100
267 inline double VisualBench::elapsed() {
268 fTimer.end();
269 return fTimer.fWall;
270 }
271
272 void VisualBench::resetTimingState() {
273 fCurrentFrame = 0;
274 fTimer = WallTimer();
275 this->resetContext();
276 }
277
278 void VisualBench::scaleLoops(double elapsedMs) {
279 // Scale back the number of loops
280 fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsedMs);
281 }
282
283 inline void VisualBench::tuneLoops() {
284 if (1 << 30 == fLoops) {
285 // We're about to wrap. Something's wrong with the bench.
286 SkDebugf("InnerLoops wrapped\n");
287 fLoops = 0;
288 } else {
289 double elapsedMs = this->elapsed();
290 if (elapsedMs > FLAGS_loopMs) {
291 this->scaleLoops(elapsedMs);
292 this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
293 } else {
294 fLoops *= 2;
295 this->nextState(kPreWarmLoops_State);
296 }
297 this->resetTimingState();
298 }
299 }
300
301 void VisualBench::recordMeasurement() {
302 double measurement = this->elapsed() / (FLAGS_frames * fLoops);
303 fRecords.back().fMeasurements.push_back(measurement);
304 }
305
306 void VisualBench::postDraw(SkCanvas* canvas) {
307 fBenchmark->perCanvasPostDraw(canvas);
308 fBenchmark.reset(nullptr);
309 fCurrentSample = 0;
310 fLoops = 1;
311 }
312
313 inline void VisualBench::timing(SkCanvas* canvas) {
314 if (fCurrentFrame >= FLAGS_frames) {
315 this->recordMeasurement();
316 if (fCurrentSample++ >= FLAGS_samples) {
317 this->printStats();
318 this->postDraw(canvas);
319 this->nextState(kPreWarmLoopsPerCanvasPreDraw_State);
320 } else {
321 this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
322 }
323 this->resetTimingState();
324 } else {
325 fCurrentFrame++;
326 }
327 }
328
329 void VisualBench::onSizeChange() { 101 void VisualBench::onSizeChange() {
330 this->setupRenderTarget(); 102 this->setupRenderTarget();
331 } 103 }
332 104
333 bool VisualBench::onHandleChar(SkUnichar unichar) { 105 bool VisualBench::onHandleChar(SkUnichar unichar) {
334 return true; 106 return true;
335 } 107 }
336 108
337 // Externally declared entry points 109 // Externally declared entry points
338 void application_init() { 110 void application_init() {
339 SkGraphics::Init(); 111 SkGraphics::Init();
340 SkEvent::Init(); 112 SkEvent::Init();
341 } 113 }
342 114
343 void application_term() { 115 void application_term() {
344 SkEvent::Term(); 116 SkEvent::Term();
345 SkGraphics::Term(); 117 SkGraphics::Term();
346 } 118 }
347 119
348 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 120 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
349 return new VisualBench(hwnd, argc, argv); 121 return new VisualBench(hwnd, argc, argv);
350 } 122 }
351 123
OLDNEW
« no previous file with comments | « tools/VisualBench/VisualBench.h ('k') | tools/VisualBench/VisualFlags.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698