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