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

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

Powered by Google App Engine
This is Rietveld 408576698