| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 2014 Google Inc. | 
|  | 3 | * | 
|  | 4 | * Use of this source code is governed by a BSD-style license that can be | 
|  | 5 | * found in the LICENSE file. | 
|  | 6 | */ | 
|  | 7 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 8 | #include <ctype.h> | 
|  | 9 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 10 | #include "Benchmark.h" | 
|  | 11 | #include "CrashHandler.h" | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 12 | #include "GMBench.h" | 
| mtklein | afb4379 | 2014-08-19 15:55:55 -0700 | [diff] [blame] | 13 | #include "ProcStats.h" | 
| mtklein | 60317d0f | 2014-07-14 11:30:37 -0700 | [diff] [blame] | 14 | #include "ResultsWriter.h" | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 15 | #include "RecordingBench.h" | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 16 | #include "SKPBench.h" | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 17 | #include "Stats.h" | 
|  | 18 | #include "Timer.h" | 
|  | 19 |  | 
| mtklein | 6838d85 | 2014-10-29 14:15:10 -0700 | [diff] [blame] | 20 | #include "SkBBoxHierarchy.h" | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 21 | #include "SkCanvas.h" | 
| caryclark | 17f0b6d | 2014-07-22 10:15:34 -0700 | [diff] [blame] | 22 | #include "SkCommonFlags.h" | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 23 | #include "SkForceLinking.h" | 
|  | 24 | #include "SkGraphics.h" | 
| mtklein | 2084050 | 2014-08-21 15:51:22 -0700 | [diff] [blame] | 25 | #include "SkOSFile.h" | 
|  | 26 | #include "SkPictureRecorder.h" | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 27 | #include "SkString.h" | 
|  | 28 | #include "SkSurface.h" | 
|  | 29 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 30 | #if SK_SUPPORT_GPU | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 31 | #include "gl/GrGLDefines.h" | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 32 | #include "GrContextFactory.h" | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 33 | SkAutoTDelete<GrContextFactory> gGrFactory; | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 34 | #endif | 
|  | 35 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 36 | __SK_FORCE_IMAGE_DECODER_LINKING; | 
|  | 37 |  | 
| reed | 5324978 | 2014-10-10 09:09:52 -0700 | [diff] [blame] | 38 | static const int kAutoTuneLoops = 0; | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 39 |  | 
| mtklein | b511042 | 2014-08-07 15:20:02 -0700 | [diff] [blame] | 40 | static const int kDefaultLoops = | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 41 | #ifdef SK_DEBUG | 
|  | 42 | 1; | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 43 | #else | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 44 | kAutoTuneLoops; | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 45 | #endif | 
|  | 46 |  | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 47 | static SkString loops_help_txt() { | 
|  | 48 | SkString help; | 
|  | 49 | help.printf("Number of times to run each bench. Set this to %d to auto-" | 
|  | 50 | "tune for each bench. Timings are only reported when auto-tuning.", | 
|  | 51 | kAutoTuneLoops); | 
|  | 52 | return help; | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | DEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str()); | 
|  | 56 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 57 | DEFINE_int32(samples, 10, "Number of samples to measure for each bench."); | 
|  | 58 | DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead."); | 
|  | 59 | DEFINE_double(overheadGoal, 0.0001, | 
|  | 60 | "Loop until timer overhead is at most this fraction of our measurments."); | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 61 | DEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU."); | 
|  | 62 | DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag."); | 
| krajcevski | 12b3544 | 2014-08-13 12:06:26 -0700 | [diff] [blame] | 63 | DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to " | 
|  | 64 | "software path rendering."); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 65 |  | 
| mtklein | 60317d0f | 2014-07-14 11:30:37 -0700 | [diff] [blame] | 66 | DEFINE_string(outResultsFile, "", "If given, write results here as JSON."); | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 67 | DEFINE_int32(maxCalibrationAttempts, 3, | 
|  | 68 | "Try up to this many times to guess loops for a bench, or skip the bench."); | 
|  | 69 | DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this."); | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 70 | DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs."); | 
|  | 71 | DEFINE_string(scales, "1.0", "Space-separated scales for SKPs."); | 
| mtklein | 2084050 | 2014-08-21 15:51:22 -0700 | [diff] [blame] | 72 | DEFINE_bool(bbh, true, "Build a BBH for SKPs?"); | 
| mtklein | e070c2b | 2014-10-14 08:40:43 -0700 | [diff] [blame] | 73 | DEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run."); | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 74 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 75 | static SkString humanize(double ms) { | 
| mtklein | dc5bbab | 2014-09-24 06:34:09 -0700 | [diff] [blame] | 76 | if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); | 
|  | 77 | if (ms > 1e+3)     return SkStringPrintf("%.3gs",  ms/1e3); | 
|  | 78 | if (ms < 1e-3)     return SkStringPrintf("%.3gns", ms*1e6); | 
| mtklein | 6238688 | 2014-07-15 10:30:31 -0700 | [diff] [blame] | 79 | #ifdef SK_BUILD_FOR_WIN | 
| mtklein | dc5bbab | 2014-09-24 06:34:09 -0700 | [diff] [blame] | 80 | if (ms < 1)        return SkStringPrintf("%.3gus", ms*1e3); | 
| mtklein | 6238688 | 2014-07-15 10:30:31 -0700 | [diff] [blame] | 81 | #else | 
| mtklein | dc5bbab | 2014-09-24 06:34:09 -0700 | [diff] [blame] | 82 | if (ms < 1)        return SkStringPrintf("%.3gµs", ms*1e3); | 
| mtklein | 6238688 | 2014-07-15 10:30:31 -0700 | [diff] [blame] | 83 | #endif | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 84 | return SkStringPrintf("%.3gms", ms); | 
|  | 85 | } | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 86 | #define HUMANIZE(ms) humanize(ms).c_str() | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 87 |  | 
| kkinnunen | 9e61bb7 | 2014-10-09 05:24:15 -0700 | [diff] [blame] | 88 | static double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContext* gl) { | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 89 | if (canvas) { | 
|  | 90 | canvas->clear(SK_ColorWHITE); | 
|  | 91 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 92 | WallTimer timer; | 
|  | 93 | timer.start(); | 
|  | 94 | if (bench) { | 
|  | 95 | bench->draw(loops, canvas); | 
|  | 96 | } | 
|  | 97 | if (canvas) { | 
|  | 98 | canvas->flush(); | 
|  | 99 | } | 
|  | 100 | #if SK_SUPPORT_GPU | 
|  | 101 | if (gl) { | 
|  | 102 | SK_GL(*gl, Flush()); | 
|  | 103 | gl->swapBuffers(); | 
|  | 104 | } | 
|  | 105 | #endif | 
|  | 106 | timer.end(); | 
|  | 107 | return timer.fWall; | 
|  | 108 | } | 
|  | 109 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 110 | static double estimate_timer_overhead() { | 
|  | 111 | double overhead = 0; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 112 | for (int i = 0; i < FLAGS_overheadLoops; i++) { | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 113 | overhead += time(1, NULL, NULL, NULL); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 114 | } | 
|  | 115 | return overhead / FLAGS_overheadLoops; | 
|  | 116 | } | 
|  | 117 |  | 
| reed | 5324978 | 2014-10-10 09:09:52 -0700 | [diff] [blame] | 118 | static int detect_forever_loops(int loops) { | 
|  | 119 | // look for a magic run-forever value | 
|  | 120 | if (loops < 0) { | 
|  | 121 | loops = SK_MaxS32; | 
|  | 122 | } | 
|  | 123 | return loops; | 
|  | 124 | } | 
|  | 125 |  | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 126 | static int clamp_loops(int loops) { | 
|  | 127 | if (loops < 1) { | 
| mtklein | 527930f | 2014-11-06 08:04:34 -0800 | [diff] [blame] | 128 | SkDebugf("ERROR: clamping loops from %d to 1. " | 
|  | 129 | "There's probably something wrong with the bench.\n", loops); | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 130 | return 1; | 
|  | 131 | } | 
|  | 132 | if (loops > FLAGS_maxLoops) { | 
|  | 133 | SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops); | 
|  | 134 | return FLAGS_maxLoops; | 
|  | 135 | } | 
|  | 136 | return loops; | 
|  | 137 | } | 
|  | 138 |  | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 139 | static bool write_canvas_png(SkCanvas* canvas, const SkString& filename) { | 
|  | 140 | if (filename.isEmpty()) { | 
|  | 141 | return false; | 
|  | 142 | } | 
| reed | e5ea500 | 2014-09-03 11:54:58 -0700 | [diff] [blame] | 143 | if (kUnknown_SkColorType == canvas->imageInfo().colorType()) { | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 144 | return false; | 
|  | 145 | } | 
|  | 146 | SkBitmap bmp; | 
|  | 147 | bmp.setInfo(canvas->imageInfo()); | 
|  | 148 | if (!canvas->readPixels(&bmp, 0, 0)) { | 
|  | 149 | SkDebugf("Can't read canvas pixels.\n"); | 
|  | 150 | return false; | 
|  | 151 | } | 
|  | 152 | SkString dir = SkOSPath::Dirname(filename.c_str()); | 
|  | 153 | if (!sk_mkdir(dir.c_str())) { | 
|  | 154 | SkDebugf("Can't make dir %s.\n", dir.c_str()); | 
|  | 155 | return false; | 
|  | 156 | } | 
|  | 157 | SkFILEWStream stream(filename.c_str()); | 
|  | 158 | if (!stream.isValid()) { | 
|  | 159 | SkDebugf("Can't write %s.\n", filename.c_str()); | 
|  | 160 | return false; | 
|  | 161 | } | 
|  | 162 | if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) { | 
|  | 163 | SkDebugf("Can't encode a PNG.\n"); | 
|  | 164 | return false; | 
|  | 165 | } | 
|  | 166 | return true; | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | static int kFailedLoops = -2; | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 170 | static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, double* samples) { | 
|  | 171 | // First figure out approximately how many loops of bench it takes to make overhead negligible. | 
| mtklein | 2069e22 | 2014-08-04 13:57:39 -0700 | [diff] [blame] | 172 | double bench_plus_overhead = 0.0; | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 173 | int round = 0; | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 174 | if (kAutoTuneLoops == FLAGS_loops) { | 
|  | 175 | while (bench_plus_overhead < overhead) { | 
|  | 176 | if (round++ == FLAGS_maxCalibrationAttempts) { | 
|  | 177 | SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n", | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 178 | bench->getUniqueName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead)); | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 179 | return kFailedLoops; | 
|  | 180 | } | 
|  | 181 | bench_plus_overhead = time(1, bench, canvas, NULL); | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 182 | } | 
| mtklein | 2069e22 | 2014-08-04 13:57:39 -0700 | [diff] [blame] | 183 | } | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 184 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 185 | // Later we'll just start and stop the timer once but loop N times. | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 186 | // We'll pick N to make timer overhead negligible: | 
|  | 187 | // | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 188 | //          overhead | 
|  | 189 | //  -------------------------  < FLAGS_overheadGoal | 
|  | 190 | //  overhead + N * Bench Time | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 191 | // | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 192 | // where bench_plus_overhead ≈ overhead + Bench Time. | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 193 | // | 
|  | 194 | // Doing some math, we get: | 
|  | 195 | // | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 196 | //  (overhead / FLAGS_overheadGoal) - overhead | 
|  | 197 | //  ------------------------------------------  < N | 
|  | 198 | //       bench_plus_overhead - overhead) | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 199 | // | 
|  | 200 | // Luckily, this also works well in practice. :) | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 201 | int loops = FLAGS_loops; | 
|  | 202 | if (kAutoTuneLoops == loops) { | 
|  | 203 | const double numer = overhead / FLAGS_overheadGoal - overhead; | 
|  | 204 | const double denom = bench_plus_overhead - overhead; | 
|  | 205 | loops = (int)ceil(numer / denom); | 
| reed | 5324978 | 2014-10-10 09:09:52 -0700 | [diff] [blame] | 206 | loops = clamp_loops(loops); | 
|  | 207 | } else { | 
|  | 208 | loops = detect_forever_loops(loops); | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 209 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 210 |  | 
|  | 211 | for (int i = 0; i < FLAGS_samples; i++) { | 
|  | 212 | samples[i] = time(loops, bench, canvas, NULL) / loops; | 
|  | 213 | } | 
|  | 214 | return loops; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 215 | } | 
|  | 216 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 217 | #if SK_SUPPORT_GPU | 
| kkinnunen | 9e61bb7 | 2014-10-09 05:24:15 -0700 | [diff] [blame] | 218 | static int gpu_bench(SkGLContext* gl, | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 219 | Benchmark* bench, | 
|  | 220 | SkCanvas* canvas, | 
|  | 221 | double* samples) { | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 222 | gl->makeCurrent(); | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 223 | // Make sure we're done with whatever came before. | 
| mtklein | 9bc86ed | 2014-07-01 10:02:42 -0700 | [diff] [blame] | 224 | SK_GL(*gl, Finish()); | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 225 |  | 
|  | 226 | // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs. | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 227 | int loops = FLAGS_loops; | 
|  | 228 | if (kAutoTuneLoops == loops) { | 
|  | 229 | loops = 1; | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 230 | double elapsed = 0; | 
|  | 231 | do { | 
| mtklein | 527930f | 2014-11-06 08:04:34 -0800 | [diff] [blame] | 232 | if (1<<30 == loops) { | 
|  | 233 | // We're about to wrap.  Something's wrong with the bench. | 
|  | 234 | loops = 0; | 
|  | 235 | break; | 
|  | 236 | } | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 237 | loops *= 2; | 
|  | 238 | // If the GPU lets frames lag at all, we need to make sure we're timing | 
|  | 239 | // _this_ round, not still timing last round.  We force this by looping | 
|  | 240 | // more times than any reasonable GPU will allow frames to lag. | 
|  | 241 | for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 
|  | 242 | elapsed = time(loops, bench, canvas, gl); | 
|  | 243 | } | 
|  | 244 | } while (elapsed < FLAGS_gpuMs); | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 245 |  | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 246 | // We've overshot at least a little.  Scale back linearly. | 
|  | 247 | loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); | 
| reed | 5324978 | 2014-10-10 09:09:52 -0700 | [diff] [blame] | 248 | loops = clamp_loops(loops); | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 249 |  | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 250 | // Might as well make sure we're not still timing our calibration. | 
|  | 251 | SK_GL(*gl, Finish()); | 
| reed | 5324978 | 2014-10-10 09:09:52 -0700 | [diff] [blame] | 252 | } else { | 
|  | 253 | loops = detect_forever_loops(loops); | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 254 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 255 |  | 
|  | 256 | // Pretty much the same deal as the calibration: do some warmup to make | 
|  | 257 | // sure we're timing steady-state pipelined frames. | 
|  | 258 | for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 
|  | 259 | time(loops, bench, canvas, gl); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 260 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 261 |  | 
|  | 262 | // Now, actually do the timing! | 
|  | 263 | for (int i = 0; i < FLAGS_samples; i++) { | 
|  | 264 | samples[i] = time(loops, bench, canvas, gl) / loops; | 
|  | 265 | } | 
|  | 266 | return loops; | 
|  | 267 | } | 
|  | 268 | #endif | 
|  | 269 |  | 
|  | 270 | static SkString to_lower(const char* str) { | 
|  | 271 | SkString lower(str); | 
|  | 272 | for (size_t i = 0; i < lower.size(); i++) { | 
|  | 273 | lower[i] = tolower(lower[i]); | 
|  | 274 | } | 
|  | 275 | return lower; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 276 | } | 
|  | 277 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 278 | struct Config { | 
|  | 279 | const char* name; | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 280 | Benchmark::Backend backend; | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 281 | SkColorType color; | 
|  | 282 | SkAlphaType alpha; | 
|  | 283 | int samples; | 
|  | 284 | #if SK_SUPPORT_GPU | 
|  | 285 | GrContextFactory::GLContextType ctxType; | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 286 | bool useDFText; | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 287 | #else | 
|  | 288 | int bogusInt; | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 289 | bool bogusBool; | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 290 | #endif | 
|  | 291 | }; | 
|  | 292 |  | 
|  | 293 | struct Target { | 
|  | 294 | explicit Target(const Config& c) : config(c) {} | 
|  | 295 | const Config config; | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 296 | SkAutoTDelete<SkSurface> surface; | 
|  | 297 | #if SK_SUPPORT_GPU | 
| kkinnunen | 9e61bb7 | 2014-10-09 05:24:15 -0700 | [diff] [blame] | 298 | SkGLContext* gl; | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 299 | #endif | 
|  | 300 | }; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 301 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 302 | static bool is_cpu_config_allowed(const char* name) { | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 303 | for (int i = 0; i < FLAGS_config.count(); i++) { | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 304 | if (to_lower(FLAGS_config[i]).equals(name)) { | 
|  | 305 | return true; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 306 | } | 
|  | 307 | } | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 308 | return false; | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 309 | } | 
|  | 310 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 311 | #if SK_SUPPORT_GPU | 
|  | 312 | static bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType, | 
|  | 313 | int sampleCnt) { | 
|  | 314 | if (!is_cpu_config_allowed(name)) { | 
|  | 315 | return false; | 
|  | 316 | } | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 317 | if (const GrContext* ctx = gGrFactory->get(ctxType)) { | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 318 | return sampleCnt <= ctx->getMaxSampleCount(); | 
|  | 319 | } | 
|  | 320 | return false; | 
|  | 321 | } | 
|  | 322 | #endif | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 323 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 324 | #if SK_SUPPORT_GPU | 
|  | 325 | #define kBogusGLContextType GrContextFactory::kNative_GLContextType | 
|  | 326 | #else | 
|  | 327 | #define kBogusGLContextType 0 | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 328 | #endif | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 329 |  | 
|  | 330 | // Append all configs that are enabled and supported. | 
|  | 331 | static void create_configs(SkTDArray<Config>* configs) { | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 332 | #define CPU_CONFIG(name, backend, color, alpha)                       \ | 
|  | 333 | if (is_cpu_config_allowed(#name)) {                               \ | 
|  | 334 | Config config = { #name, Benchmark::backend, color, alpha, 0, \ | 
|  | 335 | kBogusGLContextType, false };               \ | 
|  | 336 | configs->push(config);                                        \ | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 337 | } | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 338 |  | 
| mtklein | 40b32be | 2014-07-09 08:46:49 -0700 | [diff] [blame] | 339 | if (FLAGS_cpu) { | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 340 | CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType) | 
|  | 341 | CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType) | 
|  | 342 | CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType) | 
| mtklein | 40b32be | 2014-07-09 08:46:49 -0700 | [diff] [blame] | 343 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 344 |  | 
|  | 345 | #if SK_SUPPORT_GPU | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 346 | #define GPU_CONFIG(name, ctxType, samples, useDFText)                        \ | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 347 | if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \ | 
|  | 348 | Config config = {                                                    \ | 
|  | 349 | #name,                                                           \ | 
|  | 350 | Benchmark::kGPU_Backend,                                         \ | 
|  | 351 | kN32_SkColorType,                                                \ | 
|  | 352 | kPremul_SkAlphaType,                                             \ | 
|  | 353 | samples,                                                         \ | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 354 | GrContextFactory::ctxType,                                       \ | 
|  | 355 | useDFText };                                                     \ | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 356 | configs->push(config);                                               \ | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 357 | } | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 358 |  | 
| mtklein | 40b32be | 2014-07-09 08:46:49 -0700 | [diff] [blame] | 359 | if (FLAGS_gpu) { | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 360 | GPU_CONFIG(gpu, kNative_GLContextType, 0, false) | 
|  | 361 | GPU_CONFIG(msaa4, kNative_GLContextType, 4, false) | 
|  | 362 | GPU_CONFIG(msaa16, kNative_GLContextType, 16, false) | 
|  | 363 | GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false) | 
|  | 364 | GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false) | 
|  | 365 | GPU_CONFIG(gpudft, kNative_GLContextType, 0, true) | 
|  | 366 | GPU_CONFIG(debug, kDebug_GLContextType, 0, false) | 
|  | 367 | GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false) | 
| bsalomon | 3b4d077 | 2014-08-06 10:52:33 -0700 | [diff] [blame] | 368 | #ifdef SK_ANGLE | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 369 | GPU_CONFIG(angle, kANGLE_GLContextType, 0, false) | 
| bsalomon | 3b4d077 | 2014-08-06 10:52:33 -0700 | [diff] [blame] | 370 | #endif | 
| mtklein | 40b32be | 2014-07-09 08:46:49 -0700 | [diff] [blame] | 371 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 372 | #endif | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 373 | } | 
|  | 374 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 375 | // If bench is enabled for config, returns a Target* for it, otherwise NULL. | 
|  | 376 | static Target* is_enabled(Benchmark* bench, const Config& config) { | 
|  | 377 | if (!bench->isSuitableFor(config.backend)) { | 
|  | 378 | return NULL; | 
|  | 379 | } | 
|  | 380 |  | 
| reed | e5ea500 | 2014-09-03 11:54:58 -0700 | [diff] [blame] | 381 | SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY, | 
|  | 382 | config.color, config.alpha); | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 383 |  | 
|  | 384 | Target* target = new Target(config); | 
|  | 385 |  | 
|  | 386 | if (Benchmark::kRaster_Backend == config.backend) { | 
|  | 387 | target->surface.reset(SkSurface::NewRaster(info)); | 
|  | 388 | } | 
|  | 389 | #if SK_SUPPORT_GPU | 
|  | 390 | else if (Benchmark::kGPU_Backend == config.backend) { | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 391 | uint32_t flags = config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0; | 
|  | 392 | SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 393 | target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType), info, | 
| jvanverth | 4736e14 | 2014-11-07 07:12:46 -0800 | [diff] [blame] | 394 | config.samples, &props)); | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 395 | target->gl = gGrFactory->getGLContext(config.ctxType); | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 396 | } | 
|  | 397 | #endif | 
|  | 398 |  | 
|  | 399 | if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) { | 
|  | 400 | delete target; | 
|  | 401 | return NULL; | 
|  | 402 | } | 
|  | 403 | return target; | 
|  | 404 | } | 
|  | 405 |  | 
|  | 406 | // Creates targets for a benchmark and a set of configs. | 
|  | 407 | static void create_targets(SkTDArray<Target*>* targets, Benchmark* b, | 
|  | 408 | const SkTDArray<Config>& configs) { | 
|  | 409 | for (int i = 0; i < configs.count(); ++i) { | 
|  | 410 | if (Target* t = is_enabled(b, configs[i])) { | 
|  | 411 | targets->push(t); | 
|  | 412 | } | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 413 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 414 | } | 
|  | 415 | } | 
|  | 416 |  | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 417 | #if SK_SUPPORT_GPU | 
| kkinnunen | 9e61bb7 | 2014-10-09 05:24:15 -0700 | [diff] [blame] | 418 | static void fill_gpu_options(ResultsWriter* log, SkGLContext* ctx) { | 
| jcgregorio | 05c4560 | 2014-07-17 13:54:36 -0700 | [diff] [blame] | 419 | const GrGLubyte* version; | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 420 | SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION)); | 
|  | 421 | log->configOption("GL_VERSION", (const char*)(version)); | 
|  | 422 |  | 
|  | 423 | SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER)); | 
|  | 424 | log->configOption("GL_RENDERER", (const char*) version); | 
|  | 425 |  | 
|  | 426 | SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR)); | 
|  | 427 | log->configOption("GL_VENDOR", (const char*) version); | 
|  | 428 |  | 
|  | 429 | SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); | 
|  | 430 | log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); | 
|  | 431 | } | 
|  | 432 | #endif | 
|  | 433 |  | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 434 | class BenchmarkStream { | 
|  | 435 | public: | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 436 | BenchmarkStream() : fBenches(BenchRegistry::Head()) | 
|  | 437 | , fGMs(skiagm::GMRegistry::Head()) | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 438 | , fCurrentRecording(0) | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 439 | , fCurrentScale(0) | 
|  | 440 | , fCurrentSKP(0) { | 
|  | 441 | for (int i = 0; i < FLAGS_skps.count(); i++) { | 
|  | 442 | if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { | 
|  | 443 | fSKPs.push_back() = FLAGS_skps[i]; | 
|  | 444 | } else { | 
|  | 445 | SkOSFile::Iter it(FLAGS_skps[i], ".skp"); | 
|  | 446 | SkString path; | 
|  | 447 | while (it.next(&path)) { | 
|  | 448 | fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str()); | 
|  | 449 | } | 
|  | 450 | } | 
|  | 451 | } | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 452 |  | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 453 | if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d", | 
|  | 454 | &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) { | 
|  | 455 | SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]); | 
|  | 456 | exit(1); | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 | for (int i = 0; i < FLAGS_scales.count(); i++) { | 
|  | 460 | if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) { | 
|  | 461 | SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]); | 
|  | 462 | exit(1); | 
|  | 463 | } | 
|  | 464 | } | 
|  | 465 | } | 
|  | 466 |  | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 467 | static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) { | 
|  | 468 | // Not strictly necessary, as it will be checked again later, | 
|  | 469 | // but helps to avoid a lot of pointless work if we're going to skip it. | 
|  | 470 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) { | 
|  | 471 | return false; | 
|  | 472 | } | 
|  | 473 |  | 
|  | 474 | SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | 
|  | 475 | if (stream.get() == NULL) { | 
|  | 476 | SkDebugf("Could not read %s.\n", path); | 
|  | 477 | return false; | 
|  | 478 | } | 
|  | 479 |  | 
| mtklein | 963504b | 2014-09-17 06:58:39 -0700 | [diff] [blame] | 480 | pic->reset(SkPicture::CreateFromStream(stream.get())); | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 481 | if (pic->get() == NULL) { | 
|  | 482 | SkDebugf("Could not read %s as an SkPicture.\n", path); | 
|  | 483 | return false; | 
|  | 484 | } | 
|  | 485 | return true; | 
|  | 486 | } | 
|  | 487 |  | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 488 | Benchmark* next() { | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 489 | if (fBenches) { | 
|  | 490 | Benchmark* bench = fBenches->factory()(NULL); | 
|  | 491 | fBenches = fBenches->next(); | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 492 | fSourceType = "bench"; | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 493 | fBenchType  = "micro"; | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 494 | return bench; | 
|  | 495 | } | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 496 |  | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 497 | while (fGMs) { | 
|  | 498 | SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL)); | 
|  | 499 | fGMs = fGMs->next(); | 
|  | 500 | if (gm->getFlags() & skiagm::GM::kAsBench_Flag) { | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 501 | fSourceType = "gm"; | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 502 | fBenchType  = "micro"; | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 503 | return SkNEW_ARGS(GMBench, (gm.detach())); | 
|  | 504 | } | 
|  | 505 | } | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 506 |  | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 507 | // First add all .skps as RecordingBenches. | 
|  | 508 | while (fCurrentRecording < fSKPs.count()) { | 
|  | 509 | const SkString& path = fSKPs[fCurrentRecording++]; | 
|  | 510 | SkAutoTUnref<SkPicture> pic; | 
|  | 511 | if (!ReadPicture(path.c_str(), &pic)) { | 
|  | 512 | continue; | 
|  | 513 | } | 
|  | 514 | SkString name = SkOSPath::Basename(path.c_str()); | 
|  | 515 | fSourceType = "skp"; | 
|  | 516 | fBenchType  = "recording"; | 
|  | 517 | return SkNEW_ARGS(RecordingBench, (name.c_str(), pic.get(), FLAGS_bbh)); | 
|  | 518 | } | 
|  | 519 |  | 
|  | 520 | // Then once each for each scale as SKPBenches (playback). | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 521 | while (fCurrentScale < fScales.count()) { | 
|  | 522 | while (fCurrentSKP < fSKPs.count()) { | 
|  | 523 | const SkString& path = fSKPs[fCurrentSKP++]; | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 524 | SkAutoTUnref<SkPicture> pic; | 
|  | 525 | if (!ReadPicture(path.c_str(), &pic)) { | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 526 | continue; | 
|  | 527 | } | 
| mtklein | 2084050 | 2014-08-21 15:51:22 -0700 | [diff] [blame] | 528 | if (FLAGS_bbh) { | 
|  | 529 | // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one. | 
| mtklein | 6838d85 | 2014-10-29 14:15:10 -0700 | [diff] [blame] | 530 | SkRTreeFactory factory; | 
| mtklein | 2084050 | 2014-08-21 15:51:22 -0700 | [diff] [blame] | 531 | SkPictureRecorder recorder; | 
| robertphillips | c5ba71d | 2014-09-04 08:42:50 -0700 | [diff] [blame] | 532 | pic->playback(recorder.beginRecording(pic->cullRect().width(), | 
| mtklein | ea65bfa | 2014-09-09 07:59:46 -0700 | [diff] [blame] | 533 | pic->cullRect().height(), | 
| robertphillips | c5ba71d | 2014-09-04 08:42:50 -0700 | [diff] [blame] | 534 | &factory)); | 
| mtklein | 2084050 | 2014-08-21 15:51:22 -0700 | [diff] [blame] | 535 | pic.reset(recorder.endRecording()); | 
|  | 536 | } | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 537 | SkString name = SkOSPath::Basename(path.c_str()); | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 538 | fSourceType = "skp"; | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 539 | fBenchType  = "playback"; | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 540 | return SkNEW_ARGS(SKPBench, | 
|  | 541 | (name.c_str(), pic.get(), fClip, fScales[fCurrentScale])); | 
|  | 542 | } | 
|  | 543 | fCurrentSKP = 0; | 
|  | 544 | fCurrentScale++; | 
|  | 545 | } | 
|  | 546 |  | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 547 | return NULL; | 
|  | 548 | } | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 549 |  | 
|  | 550 | void fillCurrentOptions(ResultsWriter* log) const { | 
|  | 551 | log->configOption("source_type", fSourceType); | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 552 | log->configOption("bench_type",  fBenchType); | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 553 | if (0 == strcmp(fSourceType, "skp")) { | 
|  | 554 | log->configOption("clip", | 
|  | 555 | SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop, | 
|  | 556 | fClip.fRight, fClip.fBottom).c_str()); | 
|  | 557 | log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str()); | 
|  | 558 | } | 
|  | 559 | } | 
|  | 560 |  | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 561 | private: | 
|  | 562 | const BenchRegistry* fBenches; | 
|  | 563 | const skiagm::GMRegistry* fGMs; | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 564 | SkIRect            fClip; | 
|  | 565 | SkTArray<SkScalar> fScales; | 
|  | 566 | SkTArray<SkString> fSKPs; | 
|  | 567 |  | 
| mtklein | fd731ce | 2014-09-10 12:19:30 -0700 | [diff] [blame] | 568 | const char* fSourceType;  // What we're benching: bench, GM, SKP, ... | 
|  | 569 | const char* fBenchType;   // How we bench it: micro, recording, playback, ... | 
|  | 570 | int fCurrentRecording; | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 571 | int fCurrentScale; | 
|  | 572 | int fCurrentSKP; | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 573 | }; | 
|  | 574 |  | 
| jcgregorio | 3b27ade | 2014-11-13 08:06:40 -0800 | [diff] [blame] | 575 | int nanobench_main(); | 
| caryclark | 17f0b6d | 2014-07-22 10:15:34 -0700 | [diff] [blame] | 576 | int nanobench_main() { | 
| jcgregorio | 3b27ade | 2014-11-13 08:06:40 -0800 | [diff] [blame] | 577 | SetupCrashHandler(); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 578 | SkAutoGraphics ag; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 579 |  | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 580 | #if SK_SUPPORT_GPU | 
| krajcevski | 12b3544 | 2014-08-13 12:06:26 -0700 | [diff] [blame] | 581 | GrContext::Options grContextOpts; | 
|  | 582 | grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks; | 
|  | 583 | gGrFactory.reset(SkNEW_ARGS(GrContextFactory, (grContextOpts))); | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 584 | #endif | 
|  | 585 |  | 
| bsalomon | 06cddec | 2014-10-24 10:40:50 -0700 | [diff] [blame] | 586 | if (FLAGS_veryVerbose) { | 
|  | 587 | FLAGS_verbose = true; | 
|  | 588 | } | 
|  | 589 |  | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 590 | if (kAutoTuneLoops != FLAGS_loops) { | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 591 | FLAGS_samples     = 1; | 
|  | 592 | FLAGS_gpuFrameLag = 0; | 
|  | 593 | } | 
|  | 594 |  | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 595 | if (!FLAGS_writePath.isEmpty()) { | 
|  | 596 | SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]); | 
|  | 597 | if (!sk_mkdir(FLAGS_writePath[0])) { | 
|  | 598 | SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]); | 
|  | 599 | FLAGS_writePath.set(0, NULL); | 
|  | 600 | } | 
|  | 601 | } | 
|  | 602 |  | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 603 | SkAutoTDelete<ResultsWriter> log(SkNEW(ResultsWriter)); | 
| mtklein | 60317d0f | 2014-07-14 11:30:37 -0700 | [diff] [blame] | 604 | if (!FLAGS_outResultsFile.isEmpty()) { | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 605 | log.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0]))); | 
| mtklein | 60317d0f | 2014-07-14 11:30:37 -0700 | [diff] [blame] | 606 | } | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 607 |  | 
|  | 608 | if (1 == FLAGS_properties.count() % 2) { | 
|  | 609 | SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n"); | 
|  | 610 | return 1; | 
|  | 611 | } | 
|  | 612 | for (int i = 1; i < FLAGS_properties.count(); i += 2) { | 
|  | 613 | log->property(FLAGS_properties[i-1], FLAGS_properties[i]); | 
|  | 614 | } | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 615 |  | 
|  | 616 | if (1 == FLAGS_key.count() % 2) { | 
|  | 617 | SkDebugf("ERROR: --key must be passed with an even number of arguments.\n"); | 
|  | 618 | return 1; | 
|  | 619 | } | 
|  | 620 | for (int i = 1; i < FLAGS_key.count(); i += 2) { | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 621 | log->key(FLAGS_key[i-1], FLAGS_key[i]); | 
| mtklein | 94e5156 | 2014-08-19 12:41:53 -0700 | [diff] [blame] | 622 | } | 
| mtklein | 60317d0f | 2014-07-14 11:30:37 -0700 | [diff] [blame] | 623 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 624 | const double overhead = estimate_timer_overhead(); | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 625 | SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead)); | 
| Mike Klein | 9129477 | 2014-07-16 19:59:32 -0400 | [diff] [blame] | 626 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 627 | SkAutoTMalloc<double> samples(FLAGS_samples); | 
|  | 628 |  | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 629 | if (kAutoTuneLoops != FLAGS_loops) { | 
|  | 630 | SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n"); | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 631 | } else if (FLAGS_verbose) { | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 632 | // No header. | 
|  | 633 | } else if (FLAGS_quiet) { | 
| mtklein | 40b32be | 2014-07-09 08:46:49 -0700 | [diff] [blame] | 634 | SkDebugf("median\tbench\tconfig\n"); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 635 | } else { | 
| qiankun.miao | 8247ec3 | 2014-09-09 19:24:36 -0700 | [diff] [blame] | 636 | SkDebugf("maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n", | 
|  | 637 | FLAGS_samples, "samples"); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 638 | } | 
|  | 639 |  | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 640 | SkTDArray<Config> configs; | 
|  | 641 | create_configs(&configs); | 
|  | 642 |  | 
| mtklein | e070c2b | 2014-10-14 08:40:43 -0700 | [diff] [blame] | 643 | int runs = 0; | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 644 | BenchmarkStream benchStream; | 
|  | 645 | while (Benchmark* b = benchStream.next()) { | 
| mtklein | e714e75 | 2014-07-31 12:13:48 -0700 | [diff] [blame] | 646 | SkAutoTDelete<Benchmark> bench(b); | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 647 | if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName())) { | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 648 | continue; | 
|  | 649 | } | 
|  | 650 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 651 | SkTDArray<Target*> targets; | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 652 | create_targets(&targets, bench.get(), configs); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 653 |  | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 654 | if (!targets.isEmpty()) { | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 655 | log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSize().fY); | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 656 | bench->preDraw(); | 
|  | 657 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 658 | for (int j = 0; j < targets.count(); j++) { | 
|  | 659 | SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL; | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 660 | const char* config = targets[j]->config.name; | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 661 |  | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 662 | const int loops = | 
|  | 663 | #if SK_SUPPORT_GPU | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 664 | Benchmark::kGPU_Backend == targets[j]->config.backend | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 665 | ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get()) | 
|  | 666 | : | 
|  | 667 | #endif | 
|  | 668 | cpu_bench(       overhead, bench.get(), canvas, samples.get()); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 669 |  | 
| bsalomon | 49f085d | 2014-09-05 13:34:00 -0700 | [diff] [blame] | 670 | if (canvas && !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 671 | SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config); | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 672 | pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName()); | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 673 | pngFilename.append(".png"); | 
|  | 674 | write_canvas_png(canvas, pngFilename); | 
|  | 675 | } | 
|  | 676 |  | 
|  | 677 | if (kFailedLoops == loops) { | 
| mtklein | 2069e22 | 2014-08-04 13:57:39 -0700 | [diff] [blame] | 678 | // Can't be timed.  A warning note has already been printed. | 
| Mike Klein | e363136 | 2014-07-15 17:56:37 -0400 | [diff] [blame] | 679 | continue; | 
|  | 680 | } | 
|  | 681 |  | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 682 | Stats stats(samples.get(), FLAGS_samples); | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 683 | log->config(config); | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 684 | log->configOption("name", bench->getName()); | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 685 | benchStream.fillCurrentOptions(log.get()); | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 686 | #if SK_SUPPORT_GPU | 
| bsalomon | c255337 | 2014-07-22 13:09:05 -0700 | [diff] [blame] | 687 | if (Benchmark::kGPU_Backend == targets[j]->config.backend) { | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 688 | fill_gpu_options(log.get(), targets[j]->gl); | 
| jcgregorio | bf5e523 | 2014-07-17 13:14:16 -0700 | [diff] [blame] | 689 | } | 
|  | 690 | #endif | 
| mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 691 | log->timer("min_ms",    stats.min); | 
|  | 692 | log->timer("median_ms", stats.median); | 
|  | 693 | log->timer("mean_ms",   stats.mean); | 
|  | 694 | log->timer("max_ms",    stats.max); | 
|  | 695 | log->timer("stddev_ms", sqrt(stats.var)); | 
| mtklein | e070c2b | 2014-10-14 08:40:43 -0700 | [diff] [blame] | 696 | if (runs++ % FLAGS_flushEvery == 0) { | 
|  | 697 | log->flush(); | 
|  | 698 | } | 
| mtklein | 60317d0f | 2014-07-14 11:30:37 -0700 | [diff] [blame] | 699 |  | 
| bsalomon | 6eb03cc | 2014-08-07 14:28:50 -0700 | [diff] [blame] | 700 | if (kAutoTuneLoops != FLAGS_loops) { | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 701 | if (targets.count() == 1) { | 
|  | 702 | config = ""; // Only print the config if we run the same bench on more than one. | 
|  | 703 | } | 
| mtklein | 53d2562 | 2014-09-18 07:39:42 -0700 | [diff] [blame] | 704 | SkDebugf("%4dM\t%s\t%s\n" | 
|  | 705 | , sk_tools::getMaxResidentSetSizeMB() | 
|  | 706 | , bench->getUniqueName() | 
|  | 707 | , config); | 
| mtklein | a189ccd | 2014-07-14 12:28:47 -0700 | [diff] [blame] | 708 | } else if (FLAGS_verbose) { | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 709 | for (int i = 0; i < FLAGS_samples; i++) { | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 710 | SkDebugf("%s  ", HUMANIZE(samples[i])); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 711 | } | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 712 | SkDebugf("%s\n", bench->getUniqueName()); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 713 | } else if (FLAGS_quiet) { | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 714 | if (targets.count() == 1) { | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 715 | config = ""; // Only print the config if we run the same bench on more than one. | 
|  | 716 | } | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 717 | SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getUniqueName(), config); | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 718 | } else { | 
|  | 719 | const double stddev_percent = 100 * sqrt(stats.var) / stats.mean; | 
| mtklein | afb4379 | 2014-08-19 15:55:55 -0700 | [diff] [blame] | 720 | SkDebugf("%4dM\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n" | 
|  | 721 | , sk_tools::getMaxResidentSetSizeMB() | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 722 | , loops | 
| mtklein | 55b0ffc | 2014-07-17 08:38:23 -0700 | [diff] [blame] | 723 | , HUMANIZE(stats.min) | 
|  | 724 | , HUMANIZE(stats.median) | 
|  | 725 | , HUMANIZE(stats.mean) | 
|  | 726 | , HUMANIZE(stats.max) | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 727 | , stddev_percent | 
| mtklein | 5d9d10e | 2014-07-11 11:57:07 -0700 | [diff] [blame] | 728 | , stats.plot.c_str() | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 729 | , config | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 730 | , bench->getUniqueName() | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 731 | ); | 
|  | 732 | } | 
| bsalomon | 06cddec | 2014-10-24 10:40:50 -0700 | [diff] [blame] | 733 | #if SK_SUPPORT_GPU && GR_CACHE_STATS | 
|  | 734 | if (FLAGS_veryVerbose && | 
|  | 735 | Benchmark::kGPU_Backend == targets[j]->config.backend) { | 
| mtklein | 6838d85 | 2014-10-29 14:15:10 -0700 | [diff] [blame] | 736 | gGrFactory->get(targets[j]->config.ctxType)->printCacheStats(); | 
| bsalomon | 06cddec | 2014-10-24 10:40:50 -0700 | [diff] [blame] | 737 | } | 
|  | 738 | #endif | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 739 | } | 
| mtklein | bb6a028 | 2014-07-01 08:43:42 -0700 | [diff] [blame] | 740 | targets.deleteAll(); | 
| Mike Klein | 3944a1d | 2014-07-15 13:40:19 -0400 | [diff] [blame] | 741 |  | 
| bsalomon | 06cddec | 2014-10-24 10:40:50 -0700 | [diff] [blame] | 742 | #if SK_SUPPORT_GPU | 
| bsalomon | 2354f84 | 2014-07-28 13:48:36 -0700 | [diff] [blame] | 743 | if (FLAGS_abandonGpuContext) { | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 744 | gGrFactory->abandonContexts(); | 
| bsalomon | 2354f84 | 2014-07-28 13:48:36 -0700 | [diff] [blame] | 745 | } | 
|  | 746 | if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) { | 
| krajcevski | 69a5560 | 2014-08-13 10:46:31 -0700 | [diff] [blame] | 747 | gGrFactory->destroyContexts(); | 
| Mike Klein | 3944a1d | 2014-07-15 13:40:19 -0400 | [diff] [blame] | 748 | } | 
| bsalomon | 06cddec | 2014-10-24 10:40:50 -0700 | [diff] [blame] | 749 | #endif | 
| mtklein | f372321 | 2014-06-25 14:08:00 -0700 | [diff] [blame] | 750 | } | 
|  | 751 |  | 
|  | 752 | return 0; | 
|  | 753 | } | 
|  | 754 |  | 
| jcgregorio | 3b27ade | 2014-11-13 08:06:40 -0800 | [diff] [blame] | 755 | #if !defined SK_BUILD_FOR_IOS | 
|  | 756 | int main(int argc, char** argv) { | 
|  | 757 | SkCommandLineFlags::Parse(argc, argv); | 
|  | 758 | return nanobench_main(); | 
|  | 759 | } | 
|  | 760 | #endif |