OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 #include <ctype.h> | 8 #include <ctype.h> |
9 | 9 |
10 #include "nanobench.h" | 10 #include "nanobench.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 return help; | 72 return help; |
73 } | 73 } |
74 | 74 |
75 DEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str()); | 75 DEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str()); |
76 | 76 |
77 DEFINE_int32(samples, 10, "Number of samples to measure for each bench."); | 77 DEFINE_int32(samples, 10, "Number of samples to measure for each bench."); |
78 DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead."); | 78 DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead."); |
79 DEFINE_double(overheadGoal, 0.0001, | 79 DEFINE_double(overheadGoal, 0.0001, |
80 "Loop until timer overhead is at most this fraction of our measurm
ents."); | 80 "Loop until timer overhead is at most this fraction of our measurm
ents."); |
81 DEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU."); | 81 DEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU."); |
82 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allow
s to lag."); | 82 DEFINE_int32(gpuFrameLag, 5, "If unknown, estimated maximum number of frames GPU
allows to lag."); |
83 DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling
back to " | 83 DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling
back to " |
84 "software path rendering."); | 84 "software path rendering."); |
85 | 85 |
86 DEFINE_string(outResultsFile, "", "If given, write results here as JSON."); | 86 DEFINE_string(outResultsFile, "", "If given, write results here as JSON."); |
87 DEFINE_int32(maxCalibrationAttempts, 3, | 87 DEFINE_int32(maxCalibrationAttempts, 3, |
88 "Try up to this many times to guess loops for a bench, or skip the
bench."); | 88 "Try up to this many times to guess loops for a bench, or skip the
bench."); |
89 DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this."); | 89 DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this."); |
90 DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs."); | 90 DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs."); |
91 DEFINE_string(scales, "1.0", "Space-separated scales for SKPs."); | 91 DEFINE_string(scales, "1.0", "Space-separated scales for SKPs."); |
92 DEFINE_string(zoom, "1.0,1", "Comma-separated scale,step zoom factors for SKPs."
); | 92 DEFINE_string(zoom, "1.0,1", "Comma-separated scale,step zoom factors for SKPs."
); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 void endTiming() override { | 137 void endTiming() override { |
138 if (this->gl) { | 138 if (this->gl) { |
139 SK_GL(*this->gl, Flush()); | 139 SK_GL(*this->gl, Flush()); |
140 this->gl->swapBuffers(); | 140 this->gl->swapBuffers(); |
141 } | 141 } |
142 } | 142 } |
143 void fence() override { | 143 void fence() override { |
144 SK_GL(*this->gl, Finish()); | 144 SK_GL(*this->gl, Finish()); |
145 } | 145 } |
146 | 146 |
147 bool needsFrameTiming() const override { return true; } | 147 bool needsFrameTiming(int* maxFrameLag) const override { |
| 148 if (!this->gl->getMaxGpuFrameLag(maxFrameLag)) { |
| 149 // Frame lag is unknown. |
| 150 *maxFrameLag = FLAGS_gpuFrameLag; |
| 151 } |
| 152 return true; |
| 153 } |
148 bool init(SkImageInfo info, Benchmark* bench) override { | 154 bool init(SkImageInfo info, Benchmark* bench) override { |
149 uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDistanceFi
eldFonts_Flag : 0; | 155 uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDistanceFi
eldFonts_Flag : 0; |
150 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | 156 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
151 this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->con
fig.ctxType), | 157 this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->con
fig.ctxType), |
152 SkSurface::kNo_Budgeted
, info, | 158 SkSurface::kNo_Budgeted
, info, |
153 this->config.samples, &
props)); | 159 this->config.samples, &
props)); |
154 this->gl = gGrFactory->getGLContext(this->config.ctxType); | 160 this->gl = gGrFactory->getGLContext(this->config.ctxType); |
155 if (!this->surface.get()) { | 161 if (!this->surface.get()) { |
156 return false; | 162 return false; |
157 } | 163 } |
| 164 if (!this->gl->fenceSyncSupport()) { |
| 165 SkDebugf("WARNING: GL context for config \"%s\" does not support fen
ce sync. " |
| 166 "Timings might not be accurate.\n", this->config.name); |
| 167 } |
158 return true; | 168 return true; |
159 } | 169 } |
160 void fillOptions(ResultsWriter* log) override { | 170 void fillOptions(ResultsWriter* log) override { |
161 const GrGLubyte* version; | 171 const GrGLubyte* version; |
162 SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION)); | 172 SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION)); |
163 log->configOption("GL_VERSION", (const char*)(version)); | 173 log->configOption("GL_VERSION", (const char*)(version)); |
164 | 174 |
165 SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER)); | 175 SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER)); |
166 log->configOption("GL_RENDERER", (const char*) version); | 176 log->configOption("GL_RENDERER", (const char*) version); |
167 | 177 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 } | 310 } |
301 | 311 |
302 for (int i = 0; i < FLAGS_samples; i++) { | 312 for (int i = 0; i < FLAGS_samples; i++) { |
303 samples[i] = time(loops, bench, target) / loops; | 313 samples[i] = time(loops, bench, target) / loops; |
304 } | 314 } |
305 return loops; | 315 return loops; |
306 } | 316 } |
307 | 317 |
308 static int gpu_bench(Target* target, | 318 static int gpu_bench(Target* target, |
309 Benchmark* bench, | 319 Benchmark* bench, |
310 double* samples) { | 320 double* samples, |
| 321 int maxGpuFrameLag) { |
311 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. | 322 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. |
312 int loops = FLAGS_loops; | 323 int loops = FLAGS_loops; |
313 if (kAutoTuneLoops == loops) { | 324 if (kAutoTuneLoops == loops) { |
314 loops = 1; | 325 loops = 1; |
315 double elapsed = 0; | 326 double elapsed = 0; |
316 do { | 327 do { |
317 if (1<<30 == loops) { | 328 if (1<<30 == loops) { |
318 // We're about to wrap. Something's wrong with the bench. | 329 // We're about to wrap. Something's wrong with the bench. |
319 loops = 0; | 330 loops = 0; |
320 break; | 331 break; |
321 } | 332 } |
322 loops *= 2; | 333 loops *= 2; |
323 // If the GPU lets frames lag at all, we need to make sure we're tim
ing | 334 // If the GPU lets frames lag at all, we need to make sure we're tim
ing |
324 // _this_ round, not still timing last round. We force this by loop
ing | 335 // _this_ round, not still timing last round. |
325 // more times than any reasonable GPU will allow frames to lag. | 336 for (int i = 0; i < maxGpuFrameLag; i++) { |
326 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | |
327 elapsed = time(loops, bench, target); | 337 elapsed = time(loops, bench, target); |
328 } | 338 } |
329 } while (elapsed < FLAGS_gpuMs); | 339 } while (elapsed < FLAGS_gpuMs); |
330 | 340 |
331 // We've overshot at least a little. Scale back linearly. | 341 // We've overshot at least a little. Scale back linearly. |
332 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); | 342 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); |
333 loops = clamp_loops(loops); | 343 loops = clamp_loops(loops); |
334 | 344 |
335 // Make sure we're not still timing our calibration. | 345 // Make sure we're not still timing our calibration. |
336 target->fence(); | 346 target->fence(); |
337 } else { | 347 } else { |
338 loops = detect_forever_loops(loops); | 348 loops = detect_forever_loops(loops); |
339 } | 349 } |
340 | 350 |
341 // Pretty much the same deal as the calibration: do some warmup to make | 351 // Pretty much the same deal as the calibration: do some warmup to make |
342 // sure we're timing steady-state pipelined frames. | 352 // sure we're timing steady-state pipelined frames. |
343 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 353 for (int i = 0; i < maxGpuFrameLag - 1; i++) { |
344 time(loops, bench, target); | 354 time(loops, bench, target); |
345 } | 355 } |
346 | 356 |
347 // Now, actually do the timing! | 357 // Now, actually do the timing! |
348 for (int i = 0; i < FLAGS_samples; i++) { | 358 for (int i = 0; i < FLAGS_samples; i++) { |
349 samples[i] = time(loops, bench, target) / loops; | 359 samples[i] = time(loops, bench, target) / loops; |
350 } | 360 } |
351 | 361 |
352 return loops; | 362 return loops; |
353 } | 363 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 GPU_CONFIG(msaa4, kNative_GLContextType, 4, false) | 432 GPU_CONFIG(msaa4, kNative_GLContextType, 4, false) |
423 GPU_CONFIG(msaa16, kNative_GLContextType, 16, false) | 433 GPU_CONFIG(msaa16, kNative_GLContextType, 16, false) |
424 GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false) | 434 GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false) |
425 GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false) | 435 GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false) |
426 GPU_CONFIG(gpudft, kNative_GLContextType, 0, true) | 436 GPU_CONFIG(gpudft, kNative_GLContextType, 0, true) |
427 GPU_CONFIG(debug, kDebug_GLContextType, 0, false) | 437 GPU_CONFIG(debug, kDebug_GLContextType, 0, false) |
428 GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false) | 438 GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false) |
429 #ifdef SK_ANGLE | 439 #ifdef SK_ANGLE |
430 GPU_CONFIG(angle, kANGLE_GLContextType, 0, false) | 440 GPU_CONFIG(angle, kANGLE_GLContextType, 0, false) |
431 #endif | 441 #endif |
| 442 #if SK_MESA |
| 443 GPU_CONFIG(mesa, kMESA_GLContextType, 0, false) |
| 444 #endif |
432 } | 445 } |
433 #endif | 446 #endif |
434 | 447 |
435 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 448 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
436 if (is_cpu_config_allowed("hwui")) { | 449 if (is_cpu_config_allowed("hwui")) { |
437 Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorTy
pe, | 450 Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorTy
pe, |
438 kPremul_SkAlphaType, 0, kBogusGLContextType, false }; | 451 kPremul_SkAlphaType, 0, kBogusGLContextType, false }; |
439 configs->push(config); | 452 configs->push(config); |
440 } | 453 } |
441 #endif | 454 #endif |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 bench->preDraw(); | 1014 bench->preDraw(); |
1002 } | 1015 } |
1003 for (int j = 0; j < targets.count(); j++) { | 1016 for (int j = 0; j < targets.count(); j++) { |
1004 // During HWUI output this canvas may be NULL. | 1017 // During HWUI output this canvas may be NULL. |
1005 SkCanvas* canvas = targets[j]->getCanvas(); | 1018 SkCanvas* canvas = targets[j]->getCanvas(); |
1006 const char* config = targets[j]->config.name; | 1019 const char* config = targets[j]->config.name; |
1007 | 1020 |
1008 targets[j]->setup(); | 1021 targets[j]->setup(); |
1009 bench->perCanvasPreDraw(canvas); | 1022 bench->perCanvasPreDraw(canvas); |
1010 | 1023 |
| 1024 int frameLag; |
1011 const int loops = | 1025 const int loops = |
1012 targets[j]->needsFrameTiming() | 1026 targets[j]->needsFrameTiming(&frameLag) |
1013 ? gpu_bench(targets[j], bench.get(), samples.get()) | 1027 ? gpu_bench(targets[j], bench.get(), samples.get(), frameLag) |
1014 : cpu_bench(overhead, targets[j], bench.get(), samples.get()); | 1028 : cpu_bench(overhead, targets[j], bench.get(), samples.get()); |
1015 | 1029 |
1016 bench->perCanvasPostDraw(canvas); | 1030 bench->perCanvasPostDraw(canvas); |
1017 | 1031 |
1018 if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &
& | 1032 if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &
& |
1019 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { | 1033 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { |
1020 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); | 1034 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); |
1021 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); | 1035 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); |
1022 pngFilename.append(".png"); | 1036 pngFilename.append(".png"); |
1023 write_canvas_png(targets[j], pngFilename); | 1037 write_canvas_png(targets[j], pngFilename); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 | 1119 |
1106 return 0; | 1120 return 0; |
1107 } | 1121 } |
1108 | 1122 |
1109 #if !defined SK_BUILD_FOR_IOS | 1123 #if !defined SK_BUILD_FOR_IOS |
1110 int main(int argc, char** argv) { | 1124 int main(int argc, char** argv) { |
1111 SkCommandLineFlags::Parse(argc, argv); | 1125 SkCommandLineFlags::Parse(argc, argv); |
1112 return nanobench_main(); | 1126 return nanobench_main(); |
1113 } | 1127 } |
1114 #endif | 1128 #endif |
OLD | NEW |