blob: 742a6ed11d65d7450c07d5c22aa83a96a3845903 [file] [log] [blame]
mtkleinf3723212014-06-25 14:08:00 -07001/*
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
mtkleinbb6a0282014-07-01 08:43:42 -07008#include <ctype.h>
9
mtkleinf3723212014-06-25 14:08:00 -070010#include "Benchmark.h"
11#include "CrashHandler.h"
mtkleine714e752014-07-31 12:13:48 -070012#include "GMBench.h"
mtklein60317d0f2014-07-14 11:30:37 -070013#include "ResultsWriter.h"
mtkleinf3723212014-06-25 14:08:00 -070014#include "Stats.h"
15#include "Timer.h"
16
17#include "SkCanvas.h"
caryclark17f0b6d2014-07-22 10:15:34 -070018#include "SkCommonFlags.h"
mtkleinf3723212014-06-25 14:08:00 -070019#include "SkForceLinking.h"
20#include "SkGraphics.h"
21#include "SkString.h"
22#include "SkSurface.h"
23
mtkleinbb6a0282014-07-01 08:43:42 -070024#if SK_SUPPORT_GPU
jcgregoriobf5e5232014-07-17 13:14:16 -070025 #include "gl/GrGLDefines.h"
mtkleinbb6a0282014-07-01 08:43:42 -070026 #include "GrContextFactory.h"
27 GrContextFactory gGrFactory;
28#endif
29
mtkleinf3723212014-06-25 14:08:00 -070030__SK_FORCE_IMAGE_DECODER_LINKING;
31
mtkleina189ccd2014-07-14 12:28:47 -070032#if SK_DEBUG
33 DEFINE_bool(runOnce, true, "Run each benchmark just once?");
34#else
35 DEFINE_bool(runOnce, false, "Run each benchmark just once?");
36#endif
37
mtkleinf3723212014-06-25 14:08:00 -070038DEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
39DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
40DEFINE_double(overheadGoal, 0.0001,
41 "Loop until timer overhead is at most this fraction of our measurments.");
mtkleinbb6a0282014-07-01 08:43:42 -070042DEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
43DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag.");
mtkleinf3723212014-06-25 14:08:00 -070044
mtklein60317d0f2014-07-14 11:30:37 -070045DEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
mtklein55b0ffc2014-07-17 08:38:23 -070046DEFINE_int32(maxCalibrationAttempts, 3,
47 "Try up to this many times to guess loops for a bench, or skip the bench.");
48DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
jcgregoriobf5e5232014-07-17 13:14:16 -070049DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON.");
50DEFINE_string(gitHash, "", "Git hash to add to JSON.");
mtklein60317d0f2014-07-14 11:30:37 -070051
mtkleinf3723212014-06-25 14:08:00 -070052static SkString humanize(double ms) {
53 if (ms > 1e+3) return SkStringPrintf("%.3gs", ms/1e3);
54 if (ms < 1e-3) return SkStringPrintf("%.3gns", ms*1e6);
mtklein62386882014-07-15 10:30:31 -070055#ifdef SK_BUILD_FOR_WIN
56 if (ms < 1) return SkStringPrintf("%.3gus", ms*1e3);
57#else
mtkleinf3723212014-06-25 14:08:00 -070058 if (ms < 1) return SkStringPrintf("%.3gµs", ms*1e3);
mtklein62386882014-07-15 10:30:31 -070059#endif
mtkleinf3723212014-06-25 14:08:00 -070060 return SkStringPrintf("%.3gms", ms);
61}
mtklein55b0ffc2014-07-17 08:38:23 -070062#define HUMANIZE(ms) humanize(ms).c_str()
mtkleinf3723212014-06-25 14:08:00 -070063
mtkleinbb6a0282014-07-01 08:43:42 -070064static double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContextHelper* gl) {
65 WallTimer timer;
66 timer.start();
67 if (bench) {
68 bench->draw(loops, canvas);
69 }
70 if (canvas) {
71 canvas->flush();
72 }
73#if SK_SUPPORT_GPU
74 if (gl) {
75 SK_GL(*gl, Flush());
76 gl->swapBuffers();
77 }
78#endif
79 timer.end();
80 return timer.fWall;
81}
82
mtkleinf3723212014-06-25 14:08:00 -070083static double estimate_timer_overhead() {
84 double overhead = 0;
mtkleinf3723212014-06-25 14:08:00 -070085 for (int i = 0; i < FLAGS_overheadLoops; i++) {
mtkleinbb6a0282014-07-01 08:43:42 -070086 overhead += time(1, NULL, NULL, NULL);
mtkleinf3723212014-06-25 14:08:00 -070087 }
88 return overhead / FLAGS_overheadLoops;
89}
90
mtklein55b0ffc2014-07-17 08:38:23 -070091static int clamp_loops(int loops) {
92 if (loops < 1) {
93 SkDebugf("ERROR: clamping loops from %d to 1.\n", loops);
94 return 1;
95 }
96 if (loops > FLAGS_maxLoops) {
97 SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
98 return FLAGS_maxLoops;
99 }
100 return loops;
101}
102
mtkleinbb6a0282014-07-01 08:43:42 -0700103static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, double* samples) {
104 // First figure out approximately how many loops of bench it takes to make overhead negligible.
105 double bench_plus_overhead;
mtklein55b0ffc2014-07-17 08:38:23 -0700106 int round = 0;
mtkleinf3723212014-06-25 14:08:00 -0700107 do {
mtkleinbb6a0282014-07-01 08:43:42 -0700108 bench_plus_overhead = time(1, bench, canvas, NULL);
mtklein55b0ffc2014-07-17 08:38:23 -0700109 if (++round == FLAGS_maxCalibrationAttempts) {
110 SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
111 bench->getName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
112 return 0;
113 }
Mike Kleine3631362014-07-15 17:56:37 -0400114 } while (bench_plus_overhead < overhead);
mtkleinf3723212014-06-25 14:08:00 -0700115
mtkleinbb6a0282014-07-01 08:43:42 -0700116 // Later we'll just start and stop the timer once but loop N times.
mtkleinf3723212014-06-25 14:08:00 -0700117 // We'll pick N to make timer overhead negligible:
118 //
mtkleinbb6a0282014-07-01 08:43:42 -0700119 // overhead
120 // ------------------------- < FLAGS_overheadGoal
121 // overhead + N * Bench Time
mtkleinf3723212014-06-25 14:08:00 -0700122 //
mtkleinbb6a0282014-07-01 08:43:42 -0700123 // where bench_plus_overhead ≈ overhead + Bench Time.
mtkleinf3723212014-06-25 14:08:00 -0700124 //
125 // Doing some math, we get:
126 //
mtkleinbb6a0282014-07-01 08:43:42 -0700127 // (overhead / FLAGS_overheadGoal) - overhead
128 // ------------------------------------------ < N
129 // bench_plus_overhead - overhead)
mtkleinf3723212014-06-25 14:08:00 -0700130 //
131 // Luckily, this also works well in practice. :)
132 const double numer = overhead / FLAGS_overheadGoal - overhead;
mtkleinbb6a0282014-07-01 08:43:42 -0700133 const double denom = bench_plus_overhead - overhead;
mtklein55b0ffc2014-07-17 08:38:23 -0700134 const int loops = clamp_loops(FLAGS_runOnce ? 1 : (int)ceil(numer / denom));
mtkleinbb6a0282014-07-01 08:43:42 -0700135
136 for (int i = 0; i < FLAGS_samples; i++) {
137 samples[i] = time(loops, bench, canvas, NULL) / loops;
138 }
139 return loops;
mtkleinf3723212014-06-25 14:08:00 -0700140}
141
mtkleinbb6a0282014-07-01 08:43:42 -0700142#if SK_SUPPORT_GPU
143static int gpu_bench(SkGLContextHelper* gl,
144 Benchmark* bench,
145 SkCanvas* canvas,
146 double* samples) {
bsalomonc2553372014-07-22 13:09:05 -0700147 gl->makeCurrent();
mtkleinbb6a0282014-07-01 08:43:42 -0700148 // Make sure we're done with whatever came before.
mtklein9bc86ed2014-07-01 10:02:42 -0700149 SK_GL(*gl, Finish());
mtkleinbb6a0282014-07-01 08:43:42 -0700150
151 // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
152 int loops = 1;
mtkleina189ccd2014-07-14 12:28:47 -0700153 if (!FLAGS_runOnce) {
154 double elapsed = 0;
155 do {
156 loops *= 2;
157 // If the GPU lets frames lag at all, we need to make sure we're timing
158 // _this_ round, not still timing last round. We force this by looping
159 // more times than any reasonable GPU will allow frames to lag.
160 for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
161 elapsed = time(loops, bench, canvas, gl);
162 }
163 } while (elapsed < FLAGS_gpuMs);
mtkleinbb6a0282014-07-01 08:43:42 -0700164
mtkleina189ccd2014-07-14 12:28:47 -0700165 // We've overshot at least a little. Scale back linearly.
166 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
mtkleinbb6a0282014-07-01 08:43:42 -0700167
mtkleina189ccd2014-07-14 12:28:47 -0700168 // Might as well make sure we're not still timing our calibration.
169 SK_GL(*gl, Finish());
170 }
mtklein55b0ffc2014-07-17 08:38:23 -0700171 loops = clamp_loops(loops);
mtkleinbb6a0282014-07-01 08:43:42 -0700172
173 // Pretty much the same deal as the calibration: do some warmup to make
174 // sure we're timing steady-state pipelined frames.
175 for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
176 time(loops, bench, canvas, gl);
mtkleinf3723212014-06-25 14:08:00 -0700177 }
mtkleinbb6a0282014-07-01 08:43:42 -0700178
179 // Now, actually do the timing!
180 for (int i = 0; i < FLAGS_samples; i++) {
181 samples[i] = time(loops, bench, canvas, gl) / loops;
182 }
183 return loops;
184}
185#endif
186
187static SkString to_lower(const char* str) {
188 SkString lower(str);
189 for (size_t i = 0; i < lower.size(); i++) {
190 lower[i] = tolower(lower[i]);
191 }
192 return lower;
mtkleinf3723212014-06-25 14:08:00 -0700193}
194
bsalomonc2553372014-07-22 13:09:05 -0700195struct Config {
196 const char* name;
mtkleinbb6a0282014-07-01 08:43:42 -0700197 Benchmark::Backend backend;
bsalomonc2553372014-07-22 13:09:05 -0700198 SkColorType color;
199 SkAlphaType alpha;
200 int samples;
201#if SK_SUPPORT_GPU
202 GrContextFactory::GLContextType ctxType;
203#else
204 int bogusInt;
205#endif
206};
207
208struct Target {
209 explicit Target(const Config& c) : config(c) {}
210 const Config config;
mtkleinbb6a0282014-07-01 08:43:42 -0700211 SkAutoTDelete<SkSurface> surface;
212#if SK_SUPPORT_GPU
213 SkGLContextHelper* gl;
214#endif
215};
mtkleinf3723212014-06-25 14:08:00 -0700216
bsalomonc2553372014-07-22 13:09:05 -0700217static bool is_cpu_config_allowed(const char* name) {
mtkleinbb6a0282014-07-01 08:43:42 -0700218 for (int i = 0; i < FLAGS_config.count(); i++) {
bsalomonc2553372014-07-22 13:09:05 -0700219 if (to_lower(FLAGS_config[i]).equals(name)) {
220 return true;
mtkleinf3723212014-06-25 14:08:00 -0700221 }
222 }
bsalomonc2553372014-07-22 13:09:05 -0700223 return false;
mtkleinbb6a0282014-07-01 08:43:42 -0700224}
225
bsalomonc2553372014-07-22 13:09:05 -0700226#if SK_SUPPORT_GPU
227static bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
228 int sampleCnt) {
229 if (!is_cpu_config_allowed(name)) {
230 return false;
231 }
232 if (const GrContext* ctx = gGrFactory.get(ctxType)) {
233 return sampleCnt <= ctx->getMaxSampleCount();
234 }
235 return false;
236}
237#endif
mtkleinbb6a0282014-07-01 08:43:42 -0700238
bsalomonc2553372014-07-22 13:09:05 -0700239#if SK_SUPPORT_GPU
240#define kBogusGLContextType GrContextFactory::kNative_GLContextType
241#else
242#define kBogusGLContextType 0
mtkleine714e752014-07-31 12:13:48 -0700243#endif
bsalomonc2553372014-07-22 13:09:05 -0700244
245// Append all configs that are enabled and supported.
246static void create_configs(SkTDArray<Config>* configs) {
247 #define CPU_CONFIG(name, backend, color, alpha) \
248 if (is_cpu_config_allowed(#name)) { \
249 Config config = { #name, Benchmark::backend, color, alpha, 0, kBogusGLContextType }; \
250 configs->push(config); \
mtkleinbb6a0282014-07-01 08:43:42 -0700251 }
mtkleine714e752014-07-31 12:13:48 -0700252
mtklein40b32be2014-07-09 08:46:49 -0700253 if (FLAGS_cpu) {
bsalomonc2553372014-07-22 13:09:05 -0700254 CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
255 CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
256 CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
mtklein40b32be2014-07-09 08:46:49 -0700257 }
mtkleinbb6a0282014-07-01 08:43:42 -0700258
259#if SK_SUPPORT_GPU
bsalomonc2553372014-07-22 13:09:05 -0700260 #define GPU_CONFIG(name, ctxType, samples) \
261 if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) { \
262 Config config = { \
263 #name, \
264 Benchmark::kGPU_Backend, \
265 kN32_SkColorType, \
266 kPremul_SkAlphaType, \
267 samples, \
268 GrContextFactory::ctxType }; \
269 configs->push(config); \
mtkleinbb6a0282014-07-01 08:43:42 -0700270 }
mtkleine714e752014-07-31 12:13:48 -0700271
mtklein40b32be2014-07-09 08:46:49 -0700272 if (FLAGS_gpu) {
bsalomonc2553372014-07-22 13:09:05 -0700273 GPU_CONFIG(gpu, kNative_GLContextType, 0)
274 GPU_CONFIG(msaa4, kNative_GLContextType, 4)
275 GPU_CONFIG(msaa16, kNative_GLContextType, 16)
276 GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4)
277 GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16)
278 GPU_CONFIG(debug, kDebug_GLContextType, 0)
279 GPU_CONFIG(nullgpu, kNull_GLContextType, 0)
mtklein40b32be2014-07-09 08:46:49 -0700280 }
mtkleinbb6a0282014-07-01 08:43:42 -0700281#endif
mtkleinf3723212014-06-25 14:08:00 -0700282}
283
bsalomonc2553372014-07-22 13:09:05 -0700284// If bench is enabled for config, returns a Target* for it, otherwise NULL.
285static Target* is_enabled(Benchmark* bench, const Config& config) {
286 if (!bench->isSuitableFor(config.backend)) {
287 return NULL;
288 }
289
290 SkImageInfo info;
291 info.fAlphaType = config.alpha;
292 info.fColorType = config.color;
293 info.fWidth = bench->getSize().fX;
294 info.fHeight = bench->getSize().fY;
295
296 Target* target = new Target(config);
297
298 if (Benchmark::kRaster_Backend == config.backend) {
299 target->surface.reset(SkSurface::NewRaster(info));
300 }
301#if SK_SUPPORT_GPU
302 else if (Benchmark::kGPU_Backend == config.backend) {
303 target->surface.reset(SkSurface::NewRenderTarget(gGrFactory.get(config.ctxType), info,
304 config.samples));
305 target->gl = gGrFactory.getGLContext(config.ctxType);
306 }
307#endif
308
309 if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) {
310 delete target;
311 return NULL;
312 }
313 return target;
314}
315
316// Creates targets for a benchmark and a set of configs.
317static void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
318 const SkTDArray<Config>& configs) {
319 for (int i = 0; i < configs.count(); ++i) {
320 if (Target* t = is_enabled(b, configs[i])) {
321 targets->push(t);
322 }
mtkleine714e752014-07-31 12:13:48 -0700323
bsalomonc2553372014-07-22 13:09:05 -0700324 }
325}
326
mtklein60317d0f2014-07-14 11:30:37 -0700327static void fill_static_options(ResultsWriter* log) {
328#if defined(SK_BUILD_FOR_WIN32)
329 log->option("system", "WIN32");
330#elif defined(SK_BUILD_FOR_MAC)
331 log->option("system", "MAC");
332#elif defined(SK_BUILD_FOR_ANDROID)
333 log->option("system", "ANDROID");
334#elif defined(SK_BUILD_FOR_UNIX)
335 log->option("system", "UNIX");
336#else
337 log->option("system", "other");
338#endif
mtklein60317d0f2014-07-14 11:30:37 -0700339}
340
jcgregoriobf5e5232014-07-17 13:14:16 -0700341#if SK_SUPPORT_GPU
342static void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) {
jcgregorio05c45602014-07-17 13:54:36 -0700343 const GrGLubyte* version;
jcgregoriobf5e5232014-07-17 13:14:16 -0700344 SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION));
345 log->configOption("GL_VERSION", (const char*)(version));
346
347 SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER));
348 log->configOption("GL_RENDERER", (const char*) version);
349
350 SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR));
351 log->configOption("GL_VENDOR", (const char*) version);
352
353 SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
354 log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
355}
356#endif
357
mtkleine714e752014-07-31 12:13:48 -0700358class BenchmarkStream {
359public:
360 BenchmarkStream() : fBenches(BenchRegistry::Head()) , fGMs(skiagm::GMRegistry::Head()) {}
361
362 Benchmark* next(const char** sourceType) {
363 if (fBenches) {
364 Benchmark* bench = fBenches->factory()(NULL);
365 fBenches = fBenches->next();
366 *sourceType = "bench";
367 return bench;
368 }
369 while (fGMs) {
370 SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
371 fGMs = fGMs->next();
372 if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
373 *sourceType = "gm";
374 return SkNEW_ARGS(GMBench, (gm.detach()));
375 }
376 }
377 return NULL;
378 }
379private:
380 const BenchRegistry* fBenches;
381 const skiagm::GMRegistry* fGMs;
382};
383
caryclark17f0b6d2014-07-22 10:15:34 -0700384int nanobench_main();
385int nanobench_main() {
mtkleinf3723212014-06-25 14:08:00 -0700386 SetupCrashHandler();
387 SkAutoGraphics ag;
mtkleinf3723212014-06-25 14:08:00 -0700388
mtkleina189ccd2014-07-14 12:28:47 -0700389 if (FLAGS_runOnce) {
390 FLAGS_samples = 1;
391 FLAGS_gpuFrameLag = 0;
392 }
393
mtklein60317d0f2014-07-14 11:30:37 -0700394 MultiResultsWriter log;
jcgregoriobf5e5232014-07-17 13:14:16 -0700395 SkAutoTDelete<NanoJSONResultsWriter> json;
mtklein60317d0f2014-07-14 11:30:37 -0700396 if (!FLAGS_outResultsFile.isEmpty()) {
jcgregoriobf5e5232014-07-17 13:14:16 -0700397 const char* gitHash = FLAGS_gitHash.isEmpty() ? "unknown-revision" : FLAGS_gitHash[0];
398 json.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0], gitHash)));
mtklein60317d0f2014-07-14 11:30:37 -0700399 log.add(json.get());
400 }
401 CallEnd<MultiResultsWriter> ender(log);
jcgregoriobf5e5232014-07-17 13:14:16 -0700402
403 if (1 == FLAGS_key.count() % 2) {
404 SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
405 return 1;
406 }
407 for (int i = 1; i < FLAGS_key.count(); i += 2) {
408 log.key(FLAGS_key[i-1], FLAGS_key[i]);
409 }
mtklein60317d0f2014-07-14 11:30:37 -0700410 fill_static_options(&log);
411
mtkleinf3723212014-06-25 14:08:00 -0700412 const double overhead = estimate_timer_overhead();
mtklein55b0ffc2014-07-17 08:38:23 -0700413 SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
Mike Klein91294772014-07-16 19:59:32 -0400414
mtkleinbb6a0282014-07-01 08:43:42 -0700415 SkAutoTMalloc<double> samples(FLAGS_samples);
416
mtkleina189ccd2014-07-14 12:28:47 -0700417 if (FLAGS_runOnce) {
418 SkDebugf("--runOnce is true; times would only be misleading so we won't print them.\n");
419 } else if (FLAGS_verbose) {
mtkleinf3723212014-06-25 14:08:00 -0700420 // No header.
421 } else if (FLAGS_quiet) {
mtklein40b32be2014-07-09 08:46:49 -0700422 SkDebugf("median\tbench\tconfig\n");
mtkleinf3723212014-06-25 14:08:00 -0700423 } else {
mtklein5d9d10e2014-07-11 11:57:07 -0700424 SkDebugf("loops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\n");
mtkleinf3723212014-06-25 14:08:00 -0700425 }
426
bsalomonc2553372014-07-22 13:09:05 -0700427 SkTDArray<Config> configs;
428 create_configs(&configs);
429
mtkleine714e752014-07-31 12:13:48 -0700430 BenchmarkStream benches;
431 const char* sourceType;
432 while (Benchmark* b = benches.next(&sourceType)) {
433 SkAutoTDelete<Benchmark> bench(b);
mtkleinf3723212014-06-25 14:08:00 -0700434 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
435 continue;
436 }
437
mtkleinbb6a0282014-07-01 08:43:42 -0700438 SkTDArray<Target*> targets;
bsalomonc2553372014-07-22 13:09:05 -0700439 create_targets(&targets, bench.get(), configs);
mtkleinf3723212014-06-25 14:08:00 -0700440
jcgregoriobf5e5232014-07-17 13:14:16 -0700441 if (!targets.isEmpty()) {
442 log.bench(bench->getName(), bench->getSize().fX, bench->getSize().fY);
443 bench->preDraw();
444 }
mtkleinbb6a0282014-07-01 08:43:42 -0700445 for (int j = 0; j < targets.count(); j++) {
446 SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL;
bsalomonc2553372014-07-22 13:09:05 -0700447 const char* config = targets[j]->config.name;
mtkleinf3723212014-06-25 14:08:00 -0700448
mtkleinbb6a0282014-07-01 08:43:42 -0700449 const int loops =
450#if SK_SUPPORT_GPU
bsalomonc2553372014-07-22 13:09:05 -0700451 Benchmark::kGPU_Backend == targets[j]->config.backend
mtkleinbb6a0282014-07-01 08:43:42 -0700452 ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get())
453 :
454#endif
455 cpu_bench( overhead, bench.get(), canvas, samples.get());
mtkleinf3723212014-06-25 14:08:00 -0700456
Mike Kleine3631362014-07-15 17:56:37 -0400457 if (loops == 0) {
mtklein04d53a52014-07-17 11:23:07 -0700458 SkDebugf("Unable to time %s\t%s (overhead %s)\n",
459 bench->getName(), config, HUMANIZE(overhead));
Mike Kleine3631362014-07-15 17:56:37 -0400460 continue;
461 }
462
mtkleinf3723212014-06-25 14:08:00 -0700463 Stats stats(samples.get(), FLAGS_samples);
mtklein60317d0f2014-07-14 11:30:37 -0700464 log.config(config);
mtkleine714e752014-07-31 12:13:48 -0700465 log.configOption("source_type", sourceType);
jcgregoriobf5e5232014-07-17 13:14:16 -0700466#if SK_SUPPORT_GPU
bsalomonc2553372014-07-22 13:09:05 -0700467 if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
jcgregoriobf5e5232014-07-17 13:14:16 -0700468 fill_gpu_options(&log, targets[j]->gl);
469 }
470#endif
mtklein60317d0f2014-07-14 11:30:37 -0700471 log.timer("min_ms", stats.min);
472 log.timer("median_ms", stats.median);
473 log.timer("mean_ms", stats.mean);
474 log.timer("max_ms", stats.max);
475 log.timer("stddev_ms", sqrt(stats.var));
476
mtkleina189ccd2014-07-14 12:28:47 -0700477 if (FLAGS_runOnce) {
478 if (targets.count() == 1) {
479 config = ""; // Only print the config if we run the same bench on more than one.
480 }
481 SkDebugf("%s\t%s\n", bench->getName(), config);
482 } else if (FLAGS_verbose) {
mtkleinf3723212014-06-25 14:08:00 -0700483 for (int i = 0; i < FLAGS_samples; i++) {
mtklein55b0ffc2014-07-17 08:38:23 -0700484 SkDebugf("%s ", HUMANIZE(samples[i]));
mtkleinf3723212014-06-25 14:08:00 -0700485 }
486 SkDebugf("%s\n", bench->getName());
487 } else if (FLAGS_quiet) {
mtkleinbb6a0282014-07-01 08:43:42 -0700488 if (targets.count() == 1) {
mtkleinf3723212014-06-25 14:08:00 -0700489 config = ""; // Only print the config if we run the same bench on more than one.
490 }
mtklein55b0ffc2014-07-17 08:38:23 -0700491 SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getName(), config);
mtkleinf3723212014-06-25 14:08:00 -0700492 } else {
493 const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
mtklein5d9d10e2014-07-11 11:57:07 -0700494 SkDebugf("%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
mtkleinf3723212014-06-25 14:08:00 -0700495 , loops
mtklein55b0ffc2014-07-17 08:38:23 -0700496 , HUMANIZE(stats.min)
497 , HUMANIZE(stats.median)
498 , HUMANIZE(stats.mean)
499 , HUMANIZE(stats.max)
mtkleinf3723212014-06-25 14:08:00 -0700500 , stddev_percent
mtklein5d9d10e2014-07-11 11:57:07 -0700501 , stats.plot.c_str()
mtkleinf3723212014-06-25 14:08:00 -0700502 , config
mtkleinbb6a0282014-07-01 08:43:42 -0700503 , bench->getName()
mtkleinf3723212014-06-25 14:08:00 -0700504 );
505 }
506 }
mtkleinbb6a0282014-07-01 08:43:42 -0700507 targets.deleteAll();
Mike Klein3944a1d2014-07-15 13:40:19 -0400508
509 #if SK_SUPPORT_GPU
bsalomon2354f842014-07-28 13:48:36 -0700510 if (FLAGS_abandonGpuContext) {
511 gGrFactory.abandonContexts();
512 }
513 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
Mike Klein3944a1d2014-07-15 13:40:19 -0400514 gGrFactory.destroyContexts();
515 }
516 #endif
mtkleinf3723212014-06-25 14:08:00 -0700517 }
518
519 return 0;
520}
521
522#if !defined SK_BUILD_FOR_IOS
caryclark17f0b6d2014-07-22 10:15:34 -0700523int main(int argc, char** argv) {
524 SkCommandLineFlags::Parse(argc, argv);
525 return nanobench_main();
mtkleinf3723212014-06-25 14:08:00 -0700526}
527#endif