blob: b51eaa20d17dcec02ee10d2d240d4ae0861202bc [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"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000012#include "SkMath.h"
reed@google.com006db0f2012-06-27 19:33:29 +000013#include "SkOSFile.h"
14#include "SkPicture.h"
15#include "SkStream.h"
16#include "SkTArray.h"
17#include "picture_utils.h"
18
19const int DEFAULT_REPEATS = 100;
reed@google.com006db0f2012-06-27 19:33:29 +000020
21static void usage(const char* argv0) {
22 SkDebugf("SkPicture benchmarking tool\n");
23 SkDebugf("\n"
24"Usage: \n"
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000025" %s <inputDir>...\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000026" [--logFile filename]\n"
keyar@chromium.org795cd472012-08-02 18:57:53 +000027" [--repeat] \n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000028" [--mode pow2tile minWidth height[] (multi) | record | simple\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000029" | tile width[] height[] (multi) | playbackCreation]\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000030" [--pipe]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000031" [--device bitmap"
32#if SK_SUPPORT_GPU
33" | gpu"
34#endif
35"]"
reed@google.com006db0f2012-06-27 19:33:29 +000036, argv0);
37 SkDebugf("\n\n");
38 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000039" inputDir: A list of directories and files to use as input. Files are\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000040" expected to have the .skp extension.\n\n"
41" --logFile filename : destination for writing log output, in addition to stdout.\n");
reed@google.com006db0f2012-06-27 19:33:29 +000042 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000043" --mode pow2tile minWidht height[] (multi) | record | simple\n"
scroggo@google.com9a412522012-09-07 15:21:18 +000044" | tile width[] height[] (multi) | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000045" Run in the corresponding mode.\n"
46" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +000047 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000048" pow2tile minWidth height[], Creates tiles with widths\n"
49" that are all a power of two\n"
50" such that they minimize the\n"
51" amount of wasted tile space.\n"
52" minWidth is the minimum width\n"
53" of these tiles and must be a\n"
54" power of two. Simple\n"
55" rendering using these tiles\n"
56" is benchmarked.\n"
57" Append \"multi\" for multithreaded\n"
58" drawing.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000059 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000060" record, Benchmark picture to picture recording.\n");
61 SkDebugf(
62" simple, Benchmark a simple rendering.\n");
63 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000064" tile width[] height[], Benchmark simple rendering using\n"
65" tiles with the given dimensions.\n"
66" Append \"multi\" for multithreaded\n"
67" drawing.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +000068 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +000069" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +000070 SkDebugf("\n");
71 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +000072" --pipe: Benchmark SkGPipe rendering. Compatible with tiled, multithreaded rendering.\n");
73 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000074" --device bitmap"
75#if SK_SUPPORT_GPU
76" | gpu"
77#endif
78": Use the corresponding device. Default is bitmap.\n");
79 SkDebugf(
80" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000081#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +000082 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000083" gpu, Render to the GPU.\n");
84#endif
85 SkDebugf("\n");
86 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000087" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +000088"Set the number of times to repeat each test."
89" Default is %i.\n", DEFAULT_REPEATS);
reed@google.com006db0f2012-06-27 19:33:29 +000090}
91
scroggo@google.com9a412522012-09-07 15:21:18 +000092SkBenchLogger gLogger;
93
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000094static void run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +000095 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +000096 SkFILEStream inputStream;
97
reed@google.com006db0f2012-06-27 19:33:29 +000098 inputStream.setPath(inputPath.c_str());
99 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000100 SkString err;
101 err.printf("Could not open file %s\n", inputPath.c_str());
102 gLogger.logError(err);
reed@google.com006db0f2012-06-27 19:33:29 +0000103 return;
104 }
105
106 SkPicture picture(&inputStream);
reed@google.com006db0f2012-06-27 19:33:29 +0000107
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000108 SkString filename;
109 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000110
111 SkString result;
112 result.printf("running bench [%i %i] %s ", picture.width(), picture.height(),
113 filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000114 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000115
keyar@chromium.org163b5672012-08-01 17:53:29 +0000116 benchmark.run(&picture);
keyar@chromium.org0665f252012-07-10 18:30:18 +0000117}
118
keyar@chromium.org163b5672012-08-01 17:53:29 +0000119static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
120 sk_tools::PictureBenchmark*& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000121 const char* argv0 = argv[0];
122 char* const* stop = argv + argc;
123
keyar@chromium.org163b5672012-08-01 17:53:29 +0000124 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000125 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
126 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000127
scroggo@google.com9a412522012-09-07 15:21:18 +0000128 // Create a string to show our current settings.
129 // TODO: Make it prettier. Currently it just repeats the command line.
130 SkString commandLine("bench_pictures:");
131 for (int i = 1; i < argc; i++) {
132 commandLine.appendf(" %s", *(argv+i));
133 }
134 commandLine.append("\n");
135
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000136 bool usePipe = false;
137 bool multiThreaded = false;
138 bool useTiles = false;
139 const char* widthString = NULL;
140 const char* heightString = NULL;
141 bool isPowerOf2Mode = false;
142 const char* mode = NULL;
reed@google.com006db0f2012-06-27 19:33:29 +0000143 for (++argv; argv < stop; ++argv) {
144 if (0 == strcmp(*argv, "--repeat")) {
145 ++argv;
146 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000147 repeats = atoi(*argv);
148 if (repeats < 1) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000149 SkDELETE(benchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000150 gLogger.logError("--repeat must be given a value > 0\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000151 exit(-1);
152 }
153 } else {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000154 SkDELETE(benchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000155 gLogger.logError("Missing arg for --repeat\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000156 usage(argv0);
157 exit(-1);
158 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000159 } else if (0 == strcmp(*argv, "--pipe")) {
160 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000161 } else if (0 == strcmp(*argv, "--logFile")) {
162 argv++;
163 if (argv < stop) {
164 if (!gLogger.SetLogFile(*argv)) {
165 SkString str;
166 str.printf("Could not open %s for writing.", *argv);
167 gLogger.logError(str);
168 usage(argv0);
169 exit(-1);
170 }
171 } else {
172 gLogger.logError("Missing arg for --logFile\n");
173 usage(argv0);
174 exit(-1);
175 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000176 } else if (0 == strcmp(*argv, "--mode")) {
177 SkDELETE(benchmark);
178
reed@google.com006db0f2012-06-27 19:33:29 +0000179 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000180 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000181 gLogger.logError("Missing mode for --mode\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000182 usage(argv0);
183 exit(-1);
184 }
185
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000186 if (0 == strcmp(*argv, "record")) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000187 benchmark = SkNEW(sk_tools::RecordPictureBenchmark);
188 } else if (0 == strcmp(*argv, "simple")) {
189 benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000190 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000191 useTiles = true;
192 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000193
194 if (0 == strcmp(*argv, "pow2tile")) {
195 isPowerOf2Mode = true;
196 }
197
keyar@chromium.org795cd472012-08-02 18:57:53 +0000198 ++argv;
199 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000200 SkString err;
201 err.printf("Missing width for --mode %s\n", mode);
202 gLogger.logError(err);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000203 usage(argv0);
204 exit(-1);
205 }
206
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000207 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000208 ++argv;
209 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000210 gLogger.logError("Missing height for --mode tile\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000211 usage(argv0);
212 exit(-1);
213 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000214 heightString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000215
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000216 ++argv;
217 if (argv < stop && 0 == strcmp(*argv, "multi")) {
218 multiThreaded = true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000219 } else {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000220 --argv;
reed@google.com006db0f2012-06-27 19:33:29 +0000221 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000222 } else if (0 == strcmp(*argv, "playbackCreation")) {
223 benchmark = SkNEW(sk_tools::PlaybackCreationBenchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000224 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000225 SkString err;
226 err.printf("%s is not a valid mode for --mode\n", *argv);
227 gLogger.logError(err);
keyar@chromium.org0665f252012-07-10 18:30:18 +0000228 usage(argv0);
reed@google.com006db0f2012-06-27 19:33:29 +0000229 exit(-1);
230 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000231 } else if (0 == strcmp(*argv, "--device")) {
232 ++argv;
233 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000234 gLogger.logError("Missing mode for --deivce\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000235 usage(argv0);
236 exit(-1);
237 }
238
239 if (0 == strcmp(*argv, "bitmap")) {
240 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
241 }
242#if SK_SUPPORT_GPU
243 else if (0 == strcmp(*argv, "gpu")) {
244 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
245 }
246#endif
247 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000248 SkString err;
249 err.printf("%s is not a valid mode for --device\n", *argv);
250 gLogger.logError(err);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000251 usage(argv0);
252 exit(-1);
253 }
254
reed@google.com006db0f2012-06-27 19:33:29 +0000255 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000256 SkDELETE(benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000257 usage(argv0);
258 exit(0);
259 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000260 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000261 }
262 }
263
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000264 if (useTiles) {
265 sk_tools::TiledPictureBenchmark* tileBenchmark = SkNEW(sk_tools::TiledPictureBenchmark);
266 if (isPowerOf2Mode) {
267 int minWidth = atoi(widthString);
268 if (!SkIsPow2(minWidth) || minWidth < 0) {
269 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000270 SkString err;
271 err.printf("--mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000272 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000273 gLogger.logError(err);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000274 exit(-1);
275 }
276 tileBenchmark->setTileMinPowerOf2Width(minWidth);
277 } else if (sk_tools::is_percentage(widthString)) {
278 tileBenchmark->setTileWidthPercentage(atof(widthString));
279 if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
280 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000281 gLogger.logError("--mode tile must be given a width percentage > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000282 exit(-1);
283 }
284 } else {
285 tileBenchmark->setTileWidth(atoi(widthString));
286 if (!(tileBenchmark->getTileWidth() > 0)) {
287 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000288 gLogger.logError("--mode tile must be given a width > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000289 exit(-1);
290 }
291 }
292
293 if (sk_tools::is_percentage(heightString)) {
294 tileBenchmark->setTileHeightPercentage(atof(heightString));
295 if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
296 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000297 gLogger.logError("--mode tile must be given a height percentage > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000298 exit(-1);
299 }
300 } else {
301 tileBenchmark->setTileHeight(atoi(heightString));
302 if (!(tileBenchmark->getTileHeight() > 0)) {
303 SkDELETE(tileBenchmark);
scroggo@google.com9a412522012-09-07 15:21:18 +0000304 gLogger.logError("--mode tile must be given a height > 0\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000305 exit(-1);
306 }
307 }
308 tileBenchmark->setThreading(multiThreaded);
309 tileBenchmark->setUsePipe(usePipe);
310 benchmark = tileBenchmark;
311 } else if (usePipe) {
312 SkDELETE(benchmark);
313 benchmark = SkNEW(sk_tools::PipePictureBenchmark);
314 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000315 if (inputs->count() < 1) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000316 SkDELETE(benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000317 usage(argv0);
318 exit(-1);
319 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000320
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000321 if (NULL == benchmark) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000322 benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
323 }
324
325 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000326 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000327 benchmark->setLogger(&gLogger);
328 // Report current settings:
329 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000330}
reed@google.com006db0f2012-06-27 19:33:29 +0000331
keyar@chromium.org163b5672012-08-01 17:53:29 +0000332static void process_input(const SkString& input, sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000333 SkOSFile::Iter iter(input.c_str(), "skp");
334 SkString inputFilename;
335
336 if (iter.next(&inputFilename)) {
337 do {
338 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000339 sk_tools::make_filepath(&inputPath, input, inputFilename);
340 run_single_benchmark(inputPath, benchmark);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000341 } while(iter.next(&inputFilename));
342 } else {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000343 run_single_benchmark(input, benchmark);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000344 }
reed@google.com006db0f2012-06-27 19:33:29 +0000345}
346
347int main(int argc, char* const argv[]) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000348 SkTArray<SkString> inputs;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000349 sk_tools::PictureBenchmark* benchmark = NULL;
reed@google.com006db0f2012-06-27 19:33:29 +0000350
keyar@chromium.org163b5672012-08-01 17:53:29 +0000351 parse_commandline(argc, argv, &inputs, benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000352
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000353 for (int i = 0; i < inputs.count(); ++i) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000354 process_input(inputs[i], *benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000355 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000356
357 SkDELETE(benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000358}