Chromium Code Reviews| 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* frameLag) const override { |
|
bsalomon
2015/06/23 14:09:20
Wondering if this param should be named maxFrameLa
Chris Dalton
2015/06/23 19:34:11
Done.
| |
| 148 if (!this->gl->getGpuFrameLag(frameLag)) { | |
| 149 // Frame lag is unknown. | |
| 150 *frameLag = 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 gpuFrameLag) { | |
| 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 < gpuFrameLag; i++) { |
| 326 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 337 time(loops, bench, target); |
| 327 elapsed = time(loops, bench, target); | |
| 328 } | 338 } |
| 329 } while (elapsed < FLAGS_gpuMs); | 339 } while ((elapsed = time(loops, bench, target)) < 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 < gpuFrameLag; 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 |