nanobench.cpp revision 8247ec313d87afcdd4da59b1f2f0d24e0983e359
1f372321de3d4183de5b9ca436e677e471e358f31mtklein/*
2f372321de3d4183de5b9ca436e677e471e358f31mtklein * Copyright 2014 Google Inc.
3f372321de3d4183de5b9ca436e677e471e358f31mtklein *
4f372321de3d4183de5b9ca436e677e471e358f31mtklein * Use of this source code is governed by a BSD-style license that can be
5f372321de3d4183de5b9ca436e677e471e358f31mtklein * found in the LICENSE file.
6f372321de3d4183de5b9ca436e677e471e358f31mtklein */
7f372321de3d4183de5b9ca436e677e471e358f31mtklein
8bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#include <ctype.h>
9bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
10f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Benchmark.h"
11f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "CrashHandler.h"
12e714e75c725c987fe682a1f5473224fe3e80380dmtklein#include "GMBench.h"
13afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein#include "ProcStats.h"
1460317d0ffb5053df7b08a627d6decd11b684e80dmtklein#include "ResultsWriter.h"
1592007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SKPBench.h"
16f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Stats.h"
17f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Timer.h"
18f372321de3d4183de5b9ca436e677e471e358f31mtklein
192084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkBBHFactory.h"
20f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkCanvas.h"
2117f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
22f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkForceLinking.h"
23f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkGraphics.h"
242084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkOSFile.h"
252084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkPictureRecorder.h"
26f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkString.h"
27f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkSurface.h"
28f372321de3d4183de5b9ca436e677e471e358f31mtklein
29bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
30bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    #include "gl/GrGLDefines.h"
31bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    #include "GrContextFactory.h"
3269a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    SkAutoTDelete<GrContextFactory> gGrFactory;
33bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
34bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
35f372321de3d4183de5b9ca436e677e471e358f31mtklein__SK_FORCE_IMAGE_DECODER_LINKING;
36f372321de3d4183de5b9ca436e677e471e358f31mtklein
376eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic const int kAutoTuneLoops = -1;
386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
39b511042bb07a6a289b0d1146cb57f6e8b80580d6mtkleinstatic const int kDefaultLoops =
406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon#ifdef SK_DEBUG
416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    1;
42a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#else
436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    kAutoTuneLoops;
44a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#endif
45a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic SkString loops_help_txt() {
476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString help;
486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    help.printf("Number of times to run each bench. Set this to %d to auto-"
496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                "tune for each bench. Timings are only reported when auto-tuning.",
506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                kAutoTuneLoops);
516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return help;
526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonDEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str());
556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
56f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
57f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
58f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_double(overheadGoal, 0.0001,
59f372321de3d4183de5b9ca436e677e471e358f31mtklein              "Loop until timer overhead is at most this fraction of our measurments.");
60bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
61bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag.");
6212b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevskiDEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
6312b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski                                          "software path rendering.");
64f372321de3d4183de5b9ca436e677e471e358f31mtklein
6560317d0ffb5053df7b08a627d6decd11b684e80dmtkleinDEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
6655b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxCalibrationAttempts, 3,
6755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein             "Try up to this many times to guess loops for a bench, or skip the bench.");
6855b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
6992007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
7092007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
712084050a33ae139d0fe9bb680f7905f91139a39fmtkleinDEFINE_bool(bbh, true, "Build a BBH for SKPs?");
7292007583e43115998412ac8b0a06cc2780eb025cmtklein
73f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
74f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (ms > 1e+3) return SkStringPrintf("%.3gs",  ms/1e3);
75f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (ms < 1e-3) return SkStringPrintf("%.3gns", ms*1e6);
766238688af0d758660d344ec047243d4efefd6f4dmtklein#ifdef SK_BUILD_FOR_WIN
776238688af0d758660d344ec047243d4efefd6f4dmtklein    if (ms < 1)    return SkStringPrintf("%.3gus", ms*1e3);
786238688af0d758660d344ec047243d4efefd6f4dmtklein#else
79f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (ms < 1)    return SkStringPrintf("%.3gµs", ms*1e3);
806238688af0d758660d344ec047243d4efefd6f4dmtklein#endif
81f372321de3d4183de5b9ca436e677e471e358f31mtklein    return SkStringPrintf("%.3gms", ms);
82f372321de3d4183de5b9ca436e677e471e358f31mtklein}
8355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
84f372321de3d4183de5b9ca436e677e471e358f31mtklein
85bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContextHelper* gl) {
866eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
876eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
886eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
89f372321de3d4183de5b9ca436e677e471e358f31mtklein    WallTimer timer;
90bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.start();
91bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    if (bench) {
92bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        bench->draw(loops, canvas);
93f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
94f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
95f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
96f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
97bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
98bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    if (gl) {
99bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SK_GL(*gl, Flush());
100bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        gl->swapBuffers();
101bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
102bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
103bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.end();
104bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return timer.fWall;
105f372321de3d4183de5b9ca436e677e471e358f31mtklein}
106f372321de3d4183de5b9ca436e677e471e358f31mtklein
107bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
108bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
109bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
110bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        overhead += time(1, NULL, NULL, NULL);
111bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
112bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
113bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
114f372321de3d4183de5b9ca436e677e471e358f31mtklein
11555b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
11655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
11755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("ERROR: clamping loops from %d to 1.\n", loops);
11855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
11955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
12055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
12155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
12255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
12355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
12455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
12555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
12655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
1276eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic bool write_canvas_png(SkCanvas* canvas, const SkString& filename) {
1286eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
1296eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1306eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
131e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (kUnknown_SkColorType == canvas->imageInfo().colorType()) {
1326eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1336eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
1356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    bmp.setInfo(canvas->imageInfo());
1366eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!canvas->readPixels(&bmp, 0, 0)) {
1376eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't read canvas pixels.\n");
1386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
1416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
1426eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
1436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
1466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
1476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
1486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
1516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
1526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
1556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
1566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
1576eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
158bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, double* samples) {
159bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
1602069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
16155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
1626eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == FLAGS_loops) {
1636eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
1646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
1656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
1666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                         bench->getName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
1676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
1686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
1696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            bench_plus_overhead = time(1, bench, canvas, NULL);
17055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
1712069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
172f372321de3d4183de5b9ca436e677e471e358f31mtklein
173bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
174f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
175f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
176bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
177bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
178bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
179f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
180bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
181f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
182f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
183f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
184bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
185bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
186bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
187f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
188f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
1896eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
1906eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
1916eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
1926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
1936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
1946eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1956eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    loops = clamp_loops(loops);
196bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
197bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
198bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        samples[i] = time(loops, bench, canvas, NULL) / loops;
199bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
200bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
201f372321de3d4183de5b9ca436e677e471e358f31mtklein}
202f372321de3d4183de5b9ca436e677e471e358f31mtklein
203bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
204bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic int gpu_bench(SkGLContextHelper* gl,
205bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     Benchmark* bench,
206bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     SkCanvas* canvas,
207bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     double* samples) {
208c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    gl->makeCurrent();
209bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Make sure we're done with whatever came before.
2109bc86ed0523e154f6f4329f43c15012f930e06d7mtklein    SK_GL(*gl, Finish());
211bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
212bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
2136eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
2146eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
2156eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
216a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
217a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
218a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
219a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
220a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // _this_ round, not still timing last round.  We force this by looping
221a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // more times than any reasonable GPU will allow frames to lag.
222a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
223a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                elapsed = time(loops, bench, canvas, gl);
224a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
225a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
226a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
227a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
228a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
229a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
230a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // Might as well make sure we're not still timing our calibration.
231a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        SK_GL(*gl, Finish());
232a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
23355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    loops = clamp_loops(loops);
234bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
235bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
236bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
237bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
238bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        time(loops, bench, canvas, gl);
239f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
240bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
241bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Now, actually do the timing!
242bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
243bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        samples[i] = time(loops, bench, canvas, gl) / loops;
244bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
245bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
246f372321de3d4183de5b9ca436e677e471e358f31mtklein}
247bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
248bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
249bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic SkString to_lower(const char* str) {
250bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkString lower(str);
251bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (size_t i = 0; i < lower.size(); i++) {
252bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        lower[i] = tolower(lower[i]);
253bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
254bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return lower;
255bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
256bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
257c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstruct Config {
258c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    const char* name;
259bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    Benchmark::Backend backend;
260c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkColorType color;
261c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkAlphaType alpha;
262c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    int samples;
263c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
264c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    GrContextFactory::GLContextType ctxType;
265c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
266c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    int bogusInt;
267c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
268c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon};
269c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
270c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstruct Target {
271c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    explicit Target(const Config& c) : config(c) {}
272c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    const Config config;
273bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTDelete<SkSurface> surface;
274bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
275bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkGLContextHelper* gl;
276bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
277bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein};
278f372321de3d4183de5b9ca436e677e471e358f31mtklein
279c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_cpu_config_allowed(const char* name) {
280bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
281c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (to_lower(FLAGS_config[i]).equals(name)) {
282c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            return true;
283bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        }
284f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
285c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
286bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
287f372321de3d4183de5b9ca436e677e471e358f31mtklein
288c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
289c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
290c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                  int sampleCnt) {
291c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!is_cpu_config_allowed(name)) {
292c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return false;
293c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
29469a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    if (const GrContext* ctx = gGrFactory->get(ctxType)) {
295c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return sampleCnt <= ctx->getMaxSampleCount();
296c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
297c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
298c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
299c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
300c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
301c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
302c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
303c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
304c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
305e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
306c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
307c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Append all configs that are enabled and supported.
308c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_configs(SkTDArray<Config>* configs) {
309c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    #define CPU_CONFIG(name, backend, color, alpha)                                               \
310c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_cpu_config_allowed(#name)) {                                                       \
311c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = { #name, Benchmark::backend, color, alpha, 0, kBogusGLContextType };  \
312c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                                                \
313f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
314e714e75c725c987fe682a1f5473224fe3e80380dmtklein
31540b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
316c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
317c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
318c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
31940b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
320f372321de3d4183de5b9ca436e677e471e358f31mtklein
321bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
322c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    #define GPU_CONFIG(name, ctxType, samples)                                   \
323c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \
324c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = {                                                    \
325c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                #name,                                                           \
326c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend,                                         \
327c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kN32_SkColorType,                                                \
328c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kPremul_SkAlphaType,                                             \
329c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                samples,                                                         \
330c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                GrContextFactory::ctxType };                                     \
331c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                               \
332f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
333e714e75c725c987fe682a1f5473224fe3e80380dmtklein
33440b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_gpu) {
335c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(gpu, kNative_GLContextType, 0)
336c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(msaa4, kNative_GLContextType, 4)
337c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(msaa16, kNative_GLContextType, 16)
338c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4)
339c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16)
340c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(debug, kDebug_GLContextType, 0)
341c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nullgpu, kNull_GLContextType, 0)
3423b4d077fba1ad037536db198608a940c47d91888bsalomon#ifdef SK_ANGLE
3433b4d077fba1ad037536db198608a940c47d91888bsalomon        GPU_CONFIG(angle, kANGLE_GLContextType, 0)
3443b4d077fba1ad037536db198608a940c47d91888bsalomon#endif
34540b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
346bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
347f372321de3d4183de5b9ca436e677e471e358f31mtklein}
348f372321de3d4183de5b9ca436e677e471e358f31mtklein
349c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// If bench is enabled for config, returns a Target* for it, otherwise NULL.
350c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
351c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
352c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
353c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
354c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
355e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
356e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                         config.color, config.alpha);
357c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
358c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    Target* target = new Target(config);
359c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
360c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (Benchmark::kRaster_Backend == config.backend) {
361c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        target->surface.reset(SkSurface::NewRaster(info));
362c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
363c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
364c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    else if (Benchmark::kGPU_Backend == config.backend) {
36569a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski        target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType), info,
366c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                                         config.samples));
36769a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski        target->gl = gGrFactory->getGLContext(config.ctxType);
368c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
369c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
370c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
371c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) {
372c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
373c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
374c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
375c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
376c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
377c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
378c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Creates targets for a benchmark and a set of configs.
379c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
380c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                           const SkTDArray<Config>& configs) {
381c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    for (int i = 0; i < configs.count(); ++i) {
382c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (Target* t = is_enabled(b, configs[i])) {
383c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            targets->push(t);
384c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        }
385e714e75c725c987fe682a1f5473224fe3e80380dmtklein
386c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
387c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
389bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#if SK_SUPPORT_GPU
390bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregoriostatic void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) {
39105c4560ab36447895d510655f927fcf123330497jcgregorio    const GrGLubyte* version;
392bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION));
393bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_VERSION", (const char*)(version));
394bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
395bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER));
396bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_RENDERER", (const char*) version);
397bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
398bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR));
399bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_VENDOR", (const char*) version);
400bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
401bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
402bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
403bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio}
404bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#endif
405bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
406e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
407e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
40892007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
40992007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
41092007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
41192007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentSKP(0) {
41292007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
41392007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
41492007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
41592007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
41692007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
41792007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
41892007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
41992007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
42092007583e43115998412ac8b0a06cc2780eb025cmtklein                }
42192007583e43115998412ac8b0a06cc2780eb025cmtklein            }
42292007583e43115998412ac8b0a06cc2780eb025cmtklein        }
42392007583e43115998412ac8b0a06cc2780eb025cmtklein
42492007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
42592007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
42692007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
42792007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
42892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
42992007583e43115998412ac8b0a06cc2780eb025cmtklein
43092007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
43192007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
43292007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
43392007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
43492007583e43115998412ac8b0a06cc2780eb025cmtklein            }
43592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
43692007583e43115998412ac8b0a06cc2780eb025cmtklein    }
437e714e75c725c987fe682a1f5473224fe3e80380dmtklein
43892007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
439e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
440e714e75c725c987fe682a1f5473224fe3e80380dmtklein            Benchmark* bench = fBenches->factory()(NULL);
441e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
44292007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
443e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
444e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
44592007583e43115998412ac8b0a06cc2780eb025cmtklein
446e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
447e714e75c725c987fe682a1f5473224fe3e80380dmtklein            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
448e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
449e714e75c725c987fe682a1f5473224fe3e80380dmtklein            if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
45092007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
451e714e75c725c987fe682a1f5473224fe3e80380dmtklein                return SkNEW_ARGS(GMBench, (gm.detach()));
452e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
453e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
45492007583e43115998412ac8b0a06cc2780eb025cmtklein
45592007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
45692007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
45792007583e43115998412ac8b0a06cc2780eb025cmtklein                const SkString& path = fSKPs[fCurrentSKP++];
45892007583e43115998412ac8b0a06cc2780eb025cmtklein
45992007583e43115998412ac8b0a06cc2780eb025cmtklein                // Not strictly necessary, as it will be checked again later,
46092007583e43115998412ac8b0a06cc2780eb025cmtklein                // but helps to avoid a lot of pointless work if we're going to skip it.
46192007583e43115998412ac8b0a06cc2780eb025cmtklein                if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) {
46292007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
46392007583e43115998412ac8b0a06cc2780eb025cmtklein                }
46492007583e43115998412ac8b0a06cc2780eb025cmtklein
46592007583e43115998412ac8b0a06cc2780eb025cmtklein                SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path.c_str()));
46692007583e43115998412ac8b0a06cc2780eb025cmtklein                if (stream.get() == NULL) {
46792007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkDebugf("Could not read %s.\n", path.c_str());
46892007583e43115998412ac8b0a06cc2780eb025cmtklein                    exit(1);
46992007583e43115998412ac8b0a06cc2780eb025cmtklein                }
47092007583e43115998412ac8b0a06cc2780eb025cmtklein
47192007583e43115998412ac8b0a06cc2780eb025cmtklein                SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get()));
47292007583e43115998412ac8b0a06cc2780eb025cmtklein                if (pic.get() == NULL) {
47392007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkDebugf("Could not read %s as an SkPicture.\n", path.c_str());
47492007583e43115998412ac8b0a06cc2780eb025cmtklein                    exit(1);
47592007583e43115998412ac8b0a06cc2780eb025cmtklein                }
47692007583e43115998412ac8b0a06cc2780eb025cmtklein
47792007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString name = SkOSPath::Basename(path.c_str());
47892007583e43115998412ac8b0a06cc2780eb025cmtklein
4792084050a33ae139d0fe9bb680f7905f91139a39fmtklein                if (FLAGS_bbh) {
4802084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
4812084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    // Here we use an SkTileGrid with parameters optimized for FLAGS_clip.
4822084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    const SkTileGridFactory::TileGridInfo info = {
4832084050a33ae139d0fe9bb680f7905f91139a39fmtklein                        SkISize::Make(fClip.width(), fClip.height()),  // tile interval
4842084050a33ae139d0fe9bb680f7905f91139a39fmtklein                        SkISize::Make(0,0),                            // margin
4852084050a33ae139d0fe9bb680f7905f91139a39fmtklein                        SkIPoint::Make(fClip.left(), fClip.top()),     // offset
4862084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    };
4872084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    SkTileGridFactory factory(info);
4882084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    SkPictureRecorder recorder;
489c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips                    pic->playback(recorder.beginRecording(pic->cullRect().width(),
490ea65bfa8ded918b908287e3e3474aaf5cbd12feamtklein                                                          pic->cullRect().height(),
491c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips                                                          &factory));
4922084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    pic.reset(recorder.endRecording());
4932084050a33ae139d0fe9bb680f7905f91139a39fmtklein                }
4942084050a33ae139d0fe9bb680f7905f91139a39fmtklein
49592007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "skp";
49692007583e43115998412ac8b0a06cc2780eb025cmtklein                return SkNEW_ARGS(SKPBench,
49792007583e43115998412ac8b0a06cc2780eb025cmtklein                        (name.c_str(), pic.get(), fClip, fScales[fCurrentScale]));
49892007583e43115998412ac8b0a06cc2780eb025cmtklein            }
49992007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
50092007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
50192007583e43115998412ac8b0a06cc2780eb025cmtklein        }
50292007583e43115998412ac8b0a06cc2780eb025cmtklein
503e714e75c725c987fe682a1f5473224fe3e80380dmtklein        return NULL;
504e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
50592007583e43115998412ac8b0a06cc2780eb025cmtklein
50692007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
50792007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
50892007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
50992007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
51092007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
51192007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
51292007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
51392007583e43115998412ac8b0a06cc2780eb025cmtklein        }
51492007583e43115998412ac8b0a06cc2780eb025cmtklein    }
51592007583e43115998412ac8b0a06cc2780eb025cmtklein
516e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
517e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
518e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
51992007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
52092007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
52192007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
52292007583e43115998412ac8b0a06cc2780eb025cmtklein
52392007583e43115998412ac8b0a06cc2780eb025cmtklein    const char* fSourceType;
52492007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
52592007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
526e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
527e714e75c725c987fe682a1f5473224fe3e80380dmtklein
52817f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main();
52917f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
530f372321de3d4183de5b9ca436e677e471e358f31mtklein    SetupCrashHandler();
531f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
532f372321de3d4183de5b9ca436e677e471e358f31mtklein
53369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
53412b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    GrContext::Options grContextOpts;
53512b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
53612b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    gGrFactory.reset(SkNEW_ARGS(GrContextFactory, (grContextOpts)));
53769a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
53869a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
5396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
540a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
541a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
542a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
543a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
5446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
5456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
5466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
5476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
5486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            FLAGS_writePath.set(0, NULL);
5496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
5506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
5516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
5521915b62637bea20e1471a8a358b22e9e47a4a385mtklein    SkAutoTDelete<ResultsWriter> log(SkNEW(ResultsWriter));
55360317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
5541915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0])));
55560317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
556bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
5571915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_properties.count() % 2) {
5581915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
559bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
560bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
5611915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_properties.count(); i += 2) {
5621915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
563bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
56494e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
5651915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_key.count() % 2) {
5661915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
56794e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
56894e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
5691915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_key.count(); i += 2) {
5701915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->key(FLAGS_key[i-1], FLAGS_key[i]);
57194e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
57260317d0ffb5053df7b08a627d6decd11b684e80dmtklein
573f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
57455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
575912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
576bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTMalloc<double> samples(FLAGS_samples);
577bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
5786eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
5796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
580a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    } else if (FLAGS_verbose) {
581f372321de3d4183de5b9ca436e677e471e358f31mtklein        // No header.
582f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
58340b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkDebugf("median\tbench\tconfig\n");
584f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
5858247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao        SkDebugf("maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n",
5868247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao                 FLAGS_samples, "samples");
587f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
588f372321de3d4183de5b9ca436e677e471e358f31mtklein
589c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkTDArray<Config> configs;
590c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
591c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
59292007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
59392007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
594e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
595f372321de3d4183de5b9ca436e677e471e358f31mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
596f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
597f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
598f372321de3d4183de5b9ca436e677e471e358f31mtklein
599bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SkTDArray<Target*> targets;
600c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        create_targets(&targets, bench.get(), configs);
601f372321de3d4183de5b9ca436e677e471e358f31mtklein
602bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        if (!targets.isEmpty()) {
6031915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->bench(bench->getName(), bench->getSize().fX, bench->getSize().fY);
604bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            bench->preDraw();
605bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
606bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        for (int j = 0; j < targets.count(); j++) {
607bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL;
608c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            const char* config = targets[j]->config.name;
609bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
610bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            const int loops =
611bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
612c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend == targets[j]->config.backend
613bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get())
614bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                :
615bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
616bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                 cpu_bench(       overhead, bench.get(), canvas, samples.get());
617f372321de3d4183de5b9ca436e677e471e358f31mtklein
61849f085dddff10473b6ebf832a974288300224e60bsalomon            if (canvas && !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
6196eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
6206eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getName());
6216eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
6226eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                write_canvas_png(canvas, pngFilename);
6236eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
6246eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
6256eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
6262069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
627e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
628e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
62960317d0ffb5053df7b08a627d6decd11b684e80dmtklein
630e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            Stats stats(samples.get(), FLAGS_samples);
6311915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->config(config);
6321915b62637bea20e1471a8a358b22e9e47a4a385mtklein            benchStream.fillCurrentOptions(log.get());
633bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#if SK_SUPPORT_GPU
634c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
6351915b62637bea20e1471a8a358b22e9e47a4a385mtklein                fill_gpu_options(log.get(), targets[j]->gl);
636bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            }
637bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#endif
6381915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("min_ms",    stats.min);
6391915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("median_ms", stats.median);
6401915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("mean_ms",   stats.mean);
6411915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("max_ms",    stats.max);
6421915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("stddev_ms", sqrt(stats.var));
64360317d0ffb5053df7b08a627d6decd11b684e80dmtklein
6446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
645a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                if (targets.count() == 1) {
646a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
647a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
648a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                SkDebugf("%s\t%s\n", bench->getName(), config);
649a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            } else if (FLAGS_verbose) {
650f372321de3d4183de5b9ca436e677e471e358f31mtklein                for (int i = 0; i < FLAGS_samples; i++) {
65155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                    SkDebugf("%s  ", HUMANIZE(samples[i]));
652f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
653f372321de3d4183de5b9ca436e677e471e358f31mtklein                SkDebugf("%s\n", bench->getName());
654f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
655bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                if (targets.count() == 1) {
656f372321de3d4183de5b9ca436e677e471e358f31mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
657f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
65855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getName(), config);
659f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
660f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
661afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein                SkDebugf("%4dM\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
662afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein                        , sk_tools::getMaxResidentSetSizeMB()
663f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
66455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
66555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
66655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
66755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
668f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
6695d9d10e8217d2138b5514a4d4216f95373240942mtklein                        , stats.plot.c_str()
670f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
671bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                        , bench->getName()
672f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
673f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
674f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
675bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        targets.deleteAll();
6763944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein
6773944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein    #if SK_SUPPORT_GPU
6782354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_abandonGpuContext) {
67969a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->abandonContexts();
6802354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        }
6812354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
68269a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->destroyContexts();
6833944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein        }
6843944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein    #endif
685f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
686f372321de3d4183de5b9ca436e677e471e358f31mtklein
687f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
688f372321de3d4183de5b9ca436e677e471e358f31mtklein}
689f372321de3d4183de5b9ca436e677e471e358f31mtklein
690f372321de3d4183de5b9ca436e677e471e358f31mtklein#if !defined SK_BUILD_FOR_IOS
69117f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint main(int argc, char** argv) {
69217f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark    SkCommandLineFlags::Parse(argc, argv);
69317f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark    return nanobench_main();
694f372321de3d4183de5b9ca436e677e471e358f31mtklein}
695f372321de3d4183de5b9ca436e677e471e358f31mtklein#endif
696