blob: d1117164e90c2340e391e9f7079681317aaef974 [file] [log] [blame]
reed@google.com006db0f2012-06-27 19:33:29 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "BenchTimer.h"
keyar@chromium.org163b5672012-08-01 17:53:29 +00009#include "PictureBenchmark.h"
scroggo@google.com9a412522012-09-07 15:21:18 +000010#include "SkBenchLogger.h"
reed@google.com006db0f2012-06-27 19:33:29 +000011#include "SkCanvas.h"
scroggo@google.com0a36f432012-09-10 20:29:13 +000012#include "SkGraphics.h"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000013#include "SkMath.h"
reed@google.com006db0f2012-06-27 19:33:29 +000014#include "SkOSFile.h"
15#include "SkPicture.h"
16#include "SkStream.h"
17#include "SkTArray.h"
18#include "picture_utils.h"
19
20const int DEFAULT_REPEATS = 100;
reed@google.com006db0f2012-06-27 19:33:29 +000021
22static void usage(const char* argv0) {
23 SkDebugf("SkPicture benchmarking tool\n");
24 SkDebugf("\n"
25"Usage: \n"
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000026" %s <inputDir>...\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000027" [--logFile filename]\n"
keyar@chromium.org795cd472012-08-02 18:57:53 +000028" [--repeat] \n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000029" [--mode pow2tile minWidth height[] (multi) | record | simple\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000030" | tile width[] height[] (multi) | playbackCreation]\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000031" [--pipe]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000032" [--device bitmap"
33#if SK_SUPPORT_GPU
34" | gpu"
35#endif
36"]"
reed@google.com006db0f2012-06-27 19:33:29 +000037, argv0);
38 SkDebugf("\n\n");
39 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000040" inputDir: A list of directories and files to use as input. Files are\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000041" expected to have the .skp extension.\n\n"
42" --logFile filename : destination for writing log output, in addition to stdout.\n");
reed@google.com006db0f2012-06-27 19:33:29 +000043 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000044" --mode pow2tile minWidht height[] (multi) | record | simple\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000045" | tile width[] height[] (multi) | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000046" Run in the corresponding mode.\n"
47" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +000048 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000049" pow2tile minWidth height[], Creates tiles with widths\n"
50" that are all a power of two\n"
51" such that they minimize the\n"
52" amount of wasted tile space.\n"
53" minWidth is the minimum width\n"
54" of these tiles and must be a\n"
55" power of two. Simple\n"
56" rendering using these tiles\n"
57" is benchmarked.\n"
58" Append \"multi\" for multithreaded\n"
59" drawing.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000060 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000061" record, Benchmark picture to picture recording.\n");
62 SkDebugf(
63" simple, Benchmark a simple rendering.\n");
64 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000065" tile width[] height[], Benchmark simple rendering using\n"
66" tiles with the given dimensions.\n"
67" Append \"multi\" for multithreaded\n"
68" drawing.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +000069 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +000070" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +000071 SkDebugf("\n");
72 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000073" --pipe: Benchmark SkGPipe rendering. Compatible with tiled, multithreaded rendering.\n");
74 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000075" --device bitmap"
76#if SK_SUPPORT_GPU
77" | gpu"
78#endif
79": Use the corresponding device. Default is bitmap.\n");
80 SkDebugf(
81" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000082#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +000083 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000084" gpu, Render to the GPU.\n");
85#endif
86 SkDebugf("\n");
87 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000088" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +000089"Set the number of times to repeat each test."
90" Default is %i.\n", DEFAULT_REPEATS);
reed@google.com006db0f2012-06-27 19:33:29 +000091}
92
scroggo@google.com9a412522012-09-07 15:21:18 +000093SkBenchLogger gLogger;
94
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000095static void run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +000096 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +000097 SkFILEStream inputStream;
98
reed@google.com006db0f2012-06-27 19:33:29 +000099 inputStream.setPath(inputPath.c_str());
100 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000101 SkString err;
102 err.printf("Could not open file %s\n", inputPath.c_str());
103 gLogger.logError(err);
reed@google.com006db0f2012-06-27 19:33:29 +0000104 return;
105 }
106
107 SkPicture picture(&inputStream);
reed@google.com006db0f2012-06-27 19:33:29 +0000108
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000109 SkString filename;
110 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000111
112 SkString result;
113 result.printf("running bench [%i %i] %s ", picture.width(), picture.height(),
114 filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000115 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000116
keyar@chromium.org163b5672012-08-01 17:53:29 +0000117 benchmark.run(&picture);
keyar@chromium.org0665f252012-07-10 18:30:18 +0000118}
119
keyar@chromium.org163b5672012-08-01 17:53:29 +0000120static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
121 sk_tools::PictureBenchmark*& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000122 const char* argv0 = argv[0];
123 char* const* stop = argv + argc;
124
keyar@chromium.org163b5672012-08-01 17:53:29 +0000125 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000126 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
127 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000128
scroggo@google.com9a412522012-09-07 15:21:18 +0000129 // Create a string to show our current settings.
130 // TODO: Make it prettier. Currently it just repeats the command line.
131 SkString commandLine("bench_pictures:");
132 for (int i = 1; i < argc; i++) {
133 commandLine.appendf(" %s", *(argv+i));
134 }
135 commandLine.append("\n");
136
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000137 bool usePipe = false;
138 bool multiThreaded = false;
139 bool useTiles = false;
140 const char* widthString = NULL;
141 const char* heightString = NULL;
142 bool isPowerOf2Mode = false;
143 const char* mode = NULL;
reed@google.com006db0f2012-06-27 19:33:29 +0000144 for (++argv; argv < stop; ++argv) {
145 if (0 == strcmp(*argv, "--repeat")) {
146 ++argv;
147 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000148 repeats = atoi(*argv);
149 if (repeats < 1) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000150 SkDELETE(benchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000151 gLogger.logError("--repeat must be given a value > 0\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000152 exit(-1);
153 }
154 } else {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000155 SkDELETE(benchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000156 gLogger.logError("Missing arg for --repeat\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000157 usage(argv0);
158 exit(-1);
159 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000160 } else if (0 == strcmp(*argv, "--pipe")) {
161 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000162 } else if (0 == strcmp(*argv, "--logFile")) {
163 argv++;
164 if (argv < stop) {
165 if (!gLogger.SetLogFile(*argv)) {
166 SkString str;
167 str.printf("Could not open %s for writing.", *argv);
168 gLogger.logError(str);
169 usage(argv0);
170 exit(-1);
171 }
172 } else {
173 gLogger.logError("Missing arg for --logFile\n");
174 usage(argv0);
175 exit(-1);
176 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000177 } else if (0 == strcmp(*argv, "--mode")) {
178 SkDELETE(benchmark);
179
reed@google.com006db0f2012-06-27 19:33:29 +0000180 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000181 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000182 gLogger.logError("Missing mode for --mode\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000183 usage(argv0);
184 exit(-1);
185 }
186
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000187 if (0 == strcmp(*argv, "record")) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000188 benchmark = SkNEW(sk_tools::RecordPictureBenchmark);
189 } else if (0 == strcmp(*argv, "simple")) {
190 benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000191 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000192 useTiles = true;
193 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000194
195 if (0 == strcmp(*argv, "pow2tile")) {
196 isPowerOf2Mode = true;
197 }
198
keyar@chromium.org795cd472012-08-02 18:57:53 +0000199 ++argv;
200 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000201 SkString err;
202 err.printf("Missing width for --mode %s\n", mode);
203 gLogger.logError(err);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000204 usage(argv0);
205 exit(-1);
206 }
207
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000208 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000209 ++argv;
210 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000211 gLogger.logError("Missing height for --mode tile\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000212 usage(argv0);
213 exit(-1);
214 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000215 heightString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000216
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000217 ++argv;
218 if (argv < stop && 0 == strcmp(*argv, "multi")) {
219 multiThreaded = true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000220 } else {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000221 --argv;
reed@google.com006db0f2012-06-27 19:33:29 +0000222 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000223 } else if (0 == strcmp(*argv, "playbackCreation")) {
224 benchmark = SkNEW(sk_tools::PlaybackCreationBenchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000225 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000226 SkString err;
227 err.printf("%s is not a valid mode for --mode\n", *argv);
228 gLogger.logError(err);
keyar@chromium.org0665f252012-07-10 18:30:18 +0000229 usage(argv0);
reed@google.com006db0f2012-06-27 19:33:29 +0000230 exit(-1);
231 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000232 } else if (0 == strcmp(*argv, "--device")) {
233 ++argv;
234 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000235 gLogger.logError("Missing mode for --deivce\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000236 usage(argv0);
237 exit(-1);
238 }
239
240 if (0 == strcmp(*argv, "bitmap")) {
241 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
242 }
243#if SK_SUPPORT_GPU
244 else if (0 == strcmp(*argv, "gpu")) {
245 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
246 }
247#endif
248 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000249 SkString err;
250 err.printf("%s is not a valid mode for --device\n", *argv);
251 gLogger.logError(err);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000252 usage(argv0);
253 exit(-1);
254 }
255
reed@google.com006db0f2012-06-27 19:33:29 +0000256 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000257 SkDELETE(benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000258 usage(argv0);
259 exit(0);
260 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000261 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000262 }
263 }
264
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000265 if (useTiles) {
266 sk_tools::TiledPictureBenchmark* tileBenchmark = SkNEW(sk_tools::TiledPictureBenchmark);
267 if (isPowerOf2Mode) {
268 int minWidth = atoi(widthString);
269 if (!SkIsPow2(minWidth) || minWidth < 0) {
270 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000271 SkString err;
272 err.printf("--mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000273 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000274 gLogger.logError(err);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000275 exit(-1);
276 }
277 tileBenchmark->setTileMinPowerOf2Width(minWidth);
278 } else if (sk_tools::is_percentage(widthString)) {
279 tileBenchmark->setTileWidthPercentage(atof(widthString));
280 if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
281 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000282 gLogger.logError("--mode tile must be given a width percentage > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000283 exit(-1);
284 }
285 } else {
286 tileBenchmark->setTileWidth(atoi(widthString));
287 if (!(tileBenchmark->getTileWidth() > 0)) {
288 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000289 gLogger.logError("--mode tile must be given a width > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000290 exit(-1);
291 }
292 }
293
294 if (sk_tools::is_percentage(heightString)) {
295 tileBenchmark->setTileHeightPercentage(atof(heightString));
296 if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
297 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000298 gLogger.logError("--mode tile must be given a height percentage > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000299 exit(-1);
300 }
301 } else {
302 tileBenchmark->setTileHeight(atoi(heightString));
303 if (!(tileBenchmark->getTileHeight() > 0)) {
304 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000305 gLogger.logError("--mode tile must be given a height > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000306 exit(-1);
307 }
308 }
309 tileBenchmark->setThreading(multiThreaded);
310 tileBenchmark->setUsePipe(usePipe);
311 benchmark = tileBenchmark;
312 } else if (usePipe) {
313 SkDELETE(benchmark);
314 benchmark = SkNEW(sk_tools::PipePictureBenchmark);
315 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000316 if (inputs->count() < 1) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000317 SkDELETE(benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000318 usage(argv0);
319 exit(-1);
320 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000321
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000322 if (NULL == benchmark) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000323 benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
324 }
325
326 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000327 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000328 benchmark->setLogger(&gLogger);
329 // Report current settings:
330 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000331}
reed@google.com006db0f2012-06-27 19:33:29 +0000332
keyar@chromium.org163b5672012-08-01 17:53:29 +0000333static void process_input(const SkString& input, sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000334 SkOSFile::Iter iter(input.c_str(), "skp");
335 SkString inputFilename;
336
337 if (iter.next(&inputFilename)) {
338 do {
339 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000340 sk_tools::make_filepath(&inputPath, input, inputFilename);
341 run_single_benchmark(inputPath, benchmark);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000342 } while(iter.next(&inputFilename));
343 } else {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000344 run_single_benchmark(input, benchmark);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000345 }
reed@google.com006db0f2012-06-27 19:33:29 +0000346}
347
348int main(int argc, char* const argv[]) {
scroggo@google.com0a36f432012-09-10 20:29:13 +0000349 SkAutoGraphics ag;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000350 SkTArray<SkString> inputs;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000351 sk_tools::PictureBenchmark* benchmark = NULL;
reed@google.com006db0f2012-06-27 19:33:29 +0000352
keyar@chromium.org163b5672012-08-01 17:53:29 +0000353 parse_commandline(argc, argv, &inputs, benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000354
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000355 for (int i = 0; i < inputs.count(); ++i) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000356 process_input(inputs[i], *benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000357 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000358
359 SkDELETE(benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000360}