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

Side by Side Diff: tools/VisualBench.cpp

Issue 1201003002: add autotuning to visualbench (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: feedback inc Created 5 years, 6 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.h ('k') | 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
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 "SkCommonFlags.h" 15 #include "SkCommonFlags.h"
16 #include "SkForceLinking.h" 16 #include "SkForceLinking.h"
17 #include "SkGraphics.h" 17 #include "SkGraphics.h"
18 #include "SkGr.h" 18 #include "SkGr.h"
19 #include "SkImageDecoder.h" 19 #include "SkImageDecoder.h"
20 #include "SkOSFile.h" 20 #include "SkOSFile.h"
21 #include "SkStream.h" 21 #include "SkStream.h"
22 #include "Stats.h" 22 #include "Stats.h"
23 #include "gl/GrGLInterface.h" 23 #include "gl/GrGLInterface.h"
24 24
25 __SK_FORCE_IMAGE_DECODER_LINKING; 25 __SK_FORCE_IMAGE_DECODER_LINKING;
26 26
27 // Between samples we reset context
28 // Between frames we swap buffers
29 // Between flushes we call flush on GrContext
30
27 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allow s to lag."); 31 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allow s to lag.");
28 DEFINE_int32(samples, 10, "Number of times to render each skp."); 32 DEFINE_int32(samples, 10, "Number of times to time each skp.");
29 DEFINE_int32(loops, 5, "Number of times to time."); 33 DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample.");
34 DEFINE_double(flushMs, 20, "Target flush time in millseconds.");
35 DEFINE_double(loopMs, 5, "Target loop time in millseconds.");
30 DEFINE_int32(msaa, 0, "Number of msaa samples."); 36 DEFINE_int32(msaa, 0, "Number of msaa samples.");
31 DEFINE_bool2(fullscreen, f, true, "Run fullscreen."); 37 DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
32 38
33 static SkString humanize(double ms) { 39 static SkString humanize(double ms) {
34 if (FLAGS_verbose) { 40 if (FLAGS_verbose) {
35 return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); 41 return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
36 } 42 }
37 return HumanizeMs(ms); 43 return HumanizeMs(ms);
38 } 44 }
39 45
40 #define HUMANIZE(time) humanize(time).c_str() 46 #define HUMANIZE(time) humanize(time).c_str()
41 47
42 VisualBench::VisualBench(void* hwnd, int argc, char** argv) 48 VisualBench::VisualBench(void* hwnd, int argc, char** argv)
43 : INHERITED(hwnd) 49 : INHERITED(hwnd)
44 , fLoop(0)
45 , fCurrentPictureIdx(-1) 50 , fCurrentPictureIdx(-1)
46 , fCurrentSample(0) 51 , fCurrentSample(0)
47 , fState(kPreWarm_State) { 52 , fCurrentFrame(0)
53 , fFlushes(1)
54 , fLoops(1)
55 , fState(kPreWarmLoops_State) {
48 SkCommandLineFlags::Parse(argc, argv); 56 SkCommandLineFlags::Parse(argc, argv);
49 57
50 // read all the skp file names. 58 // read all the skp file names.
51 for (int i = 0; i < FLAGS_skps.count(); i++) { 59 for (int i = 0; i < FLAGS_skps.count(); i++) {
52 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { 60 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
53 fRecords.push_back().fFilename = FLAGS_skps[i]; 61 fRecords.push_back().fFilename = FLAGS_skps[i];
54 } else { 62 } else {
55 SkOSFile::Iter it(FLAGS_skps[i], ".skp"); 63 SkOSFile::Iter it(FLAGS_skps[i], ".skp");
56 SkString path; 64 SkString path;
57 while (it.next(&path)) { 65 while (it.next(&path)) {
58 fRecords.push_back().fFilename = SkOSPath::Join(FLAGS_skps[i], p ath.c_str());; 66 fRecords.push_back().fFilename = SkOSPath::Join(FLAGS_skps[i], p ath.c_str());;
59 } 67 }
60 } 68 }
61 } 69 }
62 70
63 if (fRecords.empty()) { 71 if (fRecords.empty()) {
64 SkDebugf("no valid skps found\n"); 72 SkDebugf("no valid skps found\n");
65 } 73 }
66 74
67 this->setTitle(); 75 this->setTitle();
68 this->setupBackend(); 76 this->setupBackend();
77
78 // Print header
79 SkDebugf("curr/maxrss\tloops\tflushes\tmin\tmedian\tmean\tmax\tstddev\tbench \n");
69 } 80 }
70 81
71 VisualBench::~VisualBench() { 82 VisualBench::~VisualBench() {
72 INHERITED::detach(); 83 INHERITED::detach();
73 } 84 }
74 85
75 void VisualBench::setTitle() { 86 void VisualBench::setTitle() {
76 SkString title("VisualBench"); 87 SkString title("VisualBench");
77 INHERITED::setTitle(title.c_str()); 88 INHERITED::setTitle(title.c_str());
78 } 89 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 this->setupRenderTarget(); 126 this->setupRenderTarget();
116 } 127 }
117 128
118 void VisualBench::setupRenderTarget() { 129 void VisualBench::setupRenderTarget() {
119 if (fContext) { 130 if (fContext) {
120 fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fCon text)); 131 fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fCon text));
121 } 132 }
122 } 133 }
123 134
124 inline void VisualBench::renderFrame(SkCanvas* canvas) { 135 inline void VisualBench::renderFrame(SkCanvas* canvas) {
125 canvas->drawPicture(fPicture); 136 for (int flush = 0; flush < fFlushes; flush++) {
126 canvas->flush(); 137 for (int loop = 0; loop < fLoops; loop++) {
138 canvas->drawPicture(fPicture);
139 }
140 canvas->flush();
141 }
127 INHERITED::present(); 142 INHERITED::present();
128 } 143 }
129 144
130 void VisualBench::printStats() { 145 void VisualBench::printStats() {
131 const SkTArray<double>& measurements = fRecords[fCurrentPictureIdx].fMeasure ments; 146 const SkTArray<double>& measurements = fRecords[fCurrentPictureIdx].fMeasure ments;
132 SkString shortName = SkOSPath::Basename(fRecords[fCurrentPictureIdx].fFilena me.c_str()); 147 SkString shortName = SkOSPath::Basename(fRecords[fCurrentPictureIdx].fFilena me.c_str());
133 if (FLAGS_verbose) { 148 if (FLAGS_verbose) {
134 for (int i = 0; i < measurements.count(); i++) { 149 for (int i = 0; i < measurements.count(); i++) {
135 SkDebugf("%s ", HUMANIZE(measurements[i])); 150 SkDebugf("%s ", HUMANIZE(measurements[i]));
136 } 151 }
137 SkDebugf("%s\n", shortName.c_str()); 152 SkDebugf("%s\n", shortName.c_str());
138 } else { 153 } else {
139 SkASSERT(measurements.count()); 154 SkASSERT(measurements.count());
140 Stats stats(measurements.begin(), measurements.count()); 155 Stats stats(measurements.begin(), measurements.count());
141 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean; 156 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean;
142 SkDebugf("%4d/%-4dMB\t%s\t%s\t%s\t%s\t%.0f%%\t%s\n", 157 SkDebugf("%4d/%-4dMB\t%d\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\n",
143 sk_tools::getCurrResidentSetSizeMB(), 158 sk_tools::getCurrResidentSetSizeMB(),
144 sk_tools::getMaxResidentSetSizeMB(), 159 sk_tools::getMaxResidentSetSizeMB(),
160 fLoops,
161 fFlushes,
145 HUMANIZE(stats.min), 162 HUMANIZE(stats.min),
146 HUMANIZE(stats.median), 163 HUMANIZE(stats.median),
147 HUMANIZE(stats.mean), 164 HUMANIZE(stats.mean),
148 HUMANIZE(stats.max), 165 HUMANIZE(stats.max),
149 stdDevPercent, 166 stdDevPercent,
150 shortName.c_str()); 167 shortName.c_str());
151 } 168 }
152 } 169 }
153 170
154 bool VisualBench::advanceRecordIfNecessary() { 171 bool VisualBench::advanceRecordIfNecessary() {
(...skipping 18 matching lines...) Expand all
173 if (stream.isValid()) { 190 if (stream.isValid()) {
174 fPicture.reset(SkPicture::CreateFromStream(&stream)); 191 fPicture.reset(SkPicture::CreateFromStream(&stream));
175 if (SkToBool(fPicture)) { 192 if (SkToBool(fPicture)) {
176 return true; 193 return true;
177 } 194 }
178 } 195 }
179 SkDebugf("couldn't load picture at \"%s\"\n", fileName); 196 SkDebugf("couldn't load picture at \"%s\"\n", fileName);
180 return false; 197 return false;
181 } 198 }
182 199
200 void VisualBench::preWarm(State nextState) {
201 if (fCurrentFrame >= FLAGS_gpuFrameLag) {
202 // we currently time across all frames to make sure we capture all GPU w ork
203 fState = nextState;
204 fCurrentFrame = 0;
205 fTimer.start();
206 } else {
207 fCurrentFrame++;
208 }
209 }
210
183 void VisualBench::draw(SkCanvas* canvas) { 211 void VisualBench::draw(SkCanvas* canvas) {
184 if (!this->advanceRecordIfNecessary()) { 212 if (!this->advanceRecordIfNecessary()) {
185 this->closeWindow(); 213 this->closeWindow();
186 return; 214 return;
187 } 215 }
188 this->renderFrame(canvas); 216 this->renderFrame(canvas);
189 switch (fState) { 217 switch (fState) {
190 case kPreWarm_State: { 218 case kPreWarmLoops_State: {
191 if (fCurrentSample >= FLAGS_gpuFrameLag) { 219 this->preWarm(kTuneLoops_State);
192 // TODO we currently time across all frames to make sure we capt ure all GPU work 220 break;
193 // We should also rendering an empty SKP to get a baseline to su btract from 221 }
194 // our timing 222 case kTuneLoops_State: {
195 fState = kTiming_State; 223 if (1 << 30 == fLoops) {
196 fCurrentSample -= FLAGS_gpuFrameLag; 224 // We're about to wrap. Something's wrong with the bench.
197 fTimer.start(); 225 SkDebugf("InnerLoops wrapped\n");
226 fLoops = 0;
198 } else { 227 } else {
199 fCurrentSample++; 228 fTimer.end();
229 double elapsed = fTimer.fWall;
230 if (elapsed > FLAGS_loopMs) {
231 fState = kPreWarmTiming_State;
232
233 // Scale back the number of loops
234 fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsed);
235 fFlushes = (int)ceil(FLAGS_flushMs / elapsed);
236 } else {
237 fState = kPreWarmLoops_State;
238 fLoops *= 2;
239 }
240
241 fCurrentFrame = 0;
242 fTimer = WallTimer();
243 this->resetContext();
200 } 244 }
201 break; 245 break;
202 } 246 }
247 case kPreWarmTiming_State: {
248 this->preWarm(kTiming_State);
249 break;
250 }
203 case kTiming_State: { 251 case kTiming_State: {
204 if (fCurrentSample >= FLAGS_samples) { 252 if (fCurrentFrame >= FLAGS_frames) {
205 fTimer.end(); 253 fTimer.end();
206 fRecords[fCurrentPictureIdx].fMeasurements.push_back(fTimer.fWal l / FLAGS_samples); 254 fRecords[fCurrentPictureIdx].fMeasurements.push_back(
207 this->resetContext(); 255 fTimer.fWall / (FLAGS_frames * fLoops * fFlushes));
208 fTimer = WallTimer(); 256 if (fCurrentSample++ >= FLAGS_samples) {
209 fState = kPreWarm_State; 257 fState = kPreWarmLoops_State;
210 fCurrentSample = 0;
211 if (fLoop++ > FLAGS_loops) {
212 this->printStats(); 258 this->printStats();
213 fPicture.reset(NULL); 259 fPicture.reset(NULL);
214 fLoop = 0; 260 fCurrentSample = 0;
261 fFlushes = 1;
262 fLoops = 1;
263 } else {
264 fState = kPreWarmTiming_State;
215 } 265 }
266 fTimer = WallTimer();
267 this->resetContext();
268 fCurrentFrame = 0;
216 } else { 269 } else {
217 fCurrentSample++; 270 fCurrentFrame++;
218 } 271 }
219 break; 272 break;
220 } 273 }
221 } 274 }
222 275
223 // Invalidate the window to force a redraw. Poor man's animation mechanism. 276 // Invalidate the window to force a redraw. Poor man's animation mechanism.
224 this->inval(NULL); 277 this->inval(NULL);
225 } 278 }
226 279
227 void VisualBench::onSizeChange() { 280 void VisualBench::onSizeChange() {
(...skipping 12 matching lines...) Expand all
240 293
241 void application_term() { 294 void application_term() {
242 SkEvent::Term(); 295 SkEvent::Term();
243 SkGraphics::Term(); 296 SkGraphics::Term();
244 } 297 }
245 298
246 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 299 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
247 return new VisualBench(hwnd, argc, argv); 300 return new VisualBench(hwnd, argc, argv);
248 } 301 }
249 302
OLDNEW
« no previous file with comments | « tools/VisualBench.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698