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