OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #if SK_SUPPORT_GPU | 9 #if SK_SUPPORT_GPU |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include "SkPicture.h" | 30 #include "SkPicture.h" |
31 #include "SkString.h" | 31 #include "SkString.h" |
32 | 32 |
33 enum BenchMode { | 33 enum BenchMode { |
34 kNormal_BenchMode, | 34 kNormal_BenchMode, |
35 kDeferred_BenchMode, | 35 kDeferred_BenchMode, |
36 kDeferredSilent_BenchMode, | 36 kDeferredSilent_BenchMode, |
37 kRecord_BenchMode, | 37 kRecord_BenchMode, |
38 kPictureRecord_BenchMode | 38 kPictureRecord_BenchMode |
39 }; | 39 }; |
40 const char* BenchMode_Name[] = { "normal", "deferred", "deferredSilent", "record ", "picturerecord" }; | 40 const char* BenchMode_Name[] = { |
41 "normal", "deferred", "deferredSilent", "record", "picturerecord" | |
42 }; | |
41 | 43 |
42 /////////////////////////////////////////////////////////////////////////////// | 44 /////////////////////////////////////////////////////////////////////////////// |
43 | 45 |
44 static void erase(SkBitmap& bm) { | 46 static void erase(SkBitmap& bm) { |
45 if (bm.config() == SkBitmap::kA8_Config) { | 47 if (bm.config() == SkBitmap::kA8_Config) { |
46 bm.eraseColor(SK_ColorTRANSPARENT); | 48 bm.eraseColor(SK_ColorTRANSPARENT); |
47 } else { | 49 } else { |
48 bm.eraseColor(SK_ColorWHITE); | 50 bm.eraseColor(SK_ColorWHITE); |
49 } | 51 } |
50 } | 52 } |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 "If a test does not match any list entry,\n" | 266 "If a test does not match any list entry,\n" |
265 "it is skipped unless some list entry starts with ~\n" ); | 267 "it is skipped unless some list entry starts with ~\n" ); |
266 DEFINE_string(mode, "normal", | 268 DEFINE_string(mode, "normal", |
267 "normal: draw to a normal canvas;\n" | 269 "normal: draw to a normal canvas;\n" |
268 "deferred: draw to a deferred canvas;\n" | 270 "deferred: draw to a deferred canvas;\n" |
269 "deferredSilent: deferred with silent playback;\n" | 271 "deferredSilent: deferred with silent playback;\n" |
270 "record: draw to an SkPicture;\n" | 272 "record: draw to an SkPicture;\n" |
271 "picturerecord: draw from an SkPicture to an SkPicture.\n"); | 273 "picturerecord: draw from an SkPicture to an SkPicture.\n"); |
272 DEFINE_string(config, "", "Run configs given. If empty, runs the defaults set i n gConfigs."); | 274 DEFINE_string(config, "", "Run configs given. If empty, runs the defaults set i n gConfigs."); |
273 DEFINE_string(logFile, "", "Also write stdout here."); | 275 DEFINE_string(logFile, "", "Also write stdout here."); |
274 DEFINE_int32(benchMs, 20, "Target time in ms to run each benchmark config."); | 276 DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run."); |
277 DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run."); | |
278 DEFINE_double(error, 0.01, | |
279 "Ratio of subsequent bench measurements must drop within 1±error t o converge."); | |
275 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops."); | 280 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops."); |
281 DEFINE_bool2(verbose, v, false, "Print more."); | |
282 | |
283 // Has this bench converged? First arguments are milliseconds / loop iteration, | |
284 // last is overall runtime in milliseconds. | |
285 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) { | |
286 if (currRaw < FLAGS_minMs) { | |
287 return false; | |
288 } | |
289 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error; | |
290 const double ratio = currPerLoop / prevPerLoop; | |
291 return low < ratio && ratio < high; | |
292 } | |
276 | 293 |
277 int tool_main(int argc, char** argv); | 294 int tool_main(int argc, char** argv); |
278 int tool_main(int argc, char** argv) { | 295 int tool_main(int argc, char** argv) { |
279 #if SK_ENABLE_INST_COUNT | 296 #if SK_ENABLE_INST_COUNT |
280 gPrintInstCount = true; | 297 gPrintInstCount = true; |
281 #endif | 298 #endif |
282 SkAutoGraphics ag; | 299 SkAutoGraphics ag; |
283 SkCommandLineFlags::Parse(argc, argv); | 300 SkCommandLineFlags::Parse(argc, argv); |
284 | 301 |
285 // First, parse some flags. | 302 // First, parse some flags. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 } | 349 } |
333 } | 350 } |
334 } | 351 } |
335 #if SK_SUPPORT_GPU | 352 #if SK_SUPPORT_GPU |
336 for (int i = 0; i < configs.count(); ++i) { | 353 for (int i = 0; i < configs.count(); ++i) { |
337 const Config& config = gConfigs[configs[i]]; | 354 const Config& config = gConfigs[configs[i]]; |
338 | 355 |
339 if (kGPU_Backend == config.backend) { | 356 if (kGPU_Backend == config.backend) { |
340 GrContext* context = gContextFactory.get(config.contextType); | 357 GrContext* context = gContextFactory.get(config.contextType); |
341 if (NULL == context) { | 358 if (NULL == context) { |
342 SkString error; | 359 logger.logError(SkStringPrintf( |
343 error.printf("Error creating GrContext for config %s. Config wil l be skipped.\n", | 360 "Error creating GrContext for config %s. Config will be skip ped.\n", |
344 config.name); | 361 config.name)); |
345 logger.logError(error); | |
346 configs.remove(i); | 362 configs.remove(i); |
347 --i; | 363 --i; |
348 continue; | 364 continue; |
349 } | 365 } |
350 if (config.sampleCount > context->getMaxSampleCount()){ | 366 if (config.sampleCount > context->getMaxSampleCount()){ |
351 SkString error; | 367 logger.logError(SkStringPrintf( |
352 error.printf("Sample count (%d) for config %s is unsupported. " | 368 "Sample count (%d) for config %s is unsupported. Config will be skipped.\n", |
353 "Config will be skipped.\n", | 369 config.sampleCount, config.name)); |
354 config.sampleCount, config.name); | |
355 logger.logError(error); | |
356 configs.remove(i); | 370 configs.remove(i); |
357 --i; | 371 --i; |
358 continue; | 372 continue; |
359 } | 373 } |
360 } | 374 } |
361 } | 375 } |
362 #endif | 376 #endif |
363 | 377 |
364 // All flags should be parsed now. Report our settings. | 378 // All flags should be parsed now. Report our settings. |
365 if (kIsDebug) { | 379 if (kIsDebug) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
477 const SkPicture::RecordingFlags kRecordFlags = | 491 const SkPicture::RecordingFlags kRecordFlags = |
478 SkPicture::kUsePathBoundsForClip_RecordingFlag; | 492 SkPicture::kUsePathBoundsForClip_RecordingFlag; |
479 | 493 |
480 if (kNonRendering_Backend != config.backend) { | 494 if (kNonRendering_Backend != config.backend) { |
481 device.reset(make_device(config.config, | 495 device.reset(make_device(config.config, |
482 dim, | 496 dim, |
483 config.backend, | 497 config.backend, |
484 config.sampleCount, | 498 config.sampleCount, |
485 context)); | 499 context)); |
486 if (!device.get()) { | 500 if (!device.get()) { |
487 SkString error; | 501 logger.logError(SkStringPrintf( |
488 error.printf("Device creation failure for config %s. Will sk ip.\n", config.name); | 502 "Device creation failure for config %s. Will skip.\n", c onfig.name)); |
489 logger.logError(error); | |
490 continue; | 503 continue; |
491 } | 504 } |
492 | 505 |
493 switch(benchMode) { | 506 switch(benchMode) { |
494 case kDeferredSilent_BenchMode: | 507 case kDeferredSilent_BenchMode: |
495 case kDeferred_BenchMode: | 508 case kDeferred_BenchMode: |
496 canvas.reset(SkDeferredCanvas::Create(device.get())); | 509 canvas.reset(SkDeferredCanvas::Create(device.get())); |
497 break; | 510 break; |
498 case kRecord_BenchMode: | 511 case kRecord_BenchMode: |
499 canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.f Y, kRecordFlags))); | 512 canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.f Y, kRecordFlags))); |
(...skipping 28 matching lines...) Expand all Loading... | |
528 | 541 |
529 #if SK_SUPPORT_GPU | 542 #if SK_SUPPORT_GPU |
530 SkGLContextHelper* contextHelper = NULL; | 543 SkGLContextHelper* contextHelper = NULL; |
531 if (kGPU_Backend == config.backend) { | 544 if (kGPU_Backend == config.backend) { |
532 contextHelper = gContextFactory.getGLContext(config.contextType) ; | 545 contextHelper = gContextFactory.getGLContext(config.contextType) ; |
533 } | 546 } |
534 BenchTimer timer(contextHelper); | 547 BenchTimer timer(contextHelper); |
535 #else | 548 #else |
536 BenchTimer timer; | 549 BenchTimer timer; |
537 #endif | 550 #endif |
538 | 551 |
robertphillips
2013/09/13 20:00:59
You're sure about this?
mtklein
2013/09/13 20:07:46
Yep. Shortest way I know to write a double +inf.
| |
552 double previous = 1.0/0.0; | |
553 bool converged = false; | |
539 bench->setLoops(0); | 554 bench->setLoops(0); |
robertphillips
2013/09/13 20:00:59
if () {
}
mtklein
2013/09/13 20:07:46
Done.
| |
555 if (FLAGS_verbose) SkDebugf("%s %s: ", bench->getName(), config.name ); | |
540 do { | 556 do { |
541 // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion. | 557 // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion. |
542 const int loops = bench->getLoops(); | 558 const int loops = bench->getLoops(); |
543 if (loops >= (1<<30)) { | 559 if (loops >= (1<<30) || timer.fWall > FLAGS_maxMs) { |
544 // If you find it takes more than a billion loops to get up to 20ms of runtime, | 560 // If you find it takes more than a billion loops to get up to 20ms of runtime, |
545 // you've got a computer clocked at several THz or have a br oken benchmark. ;) | 561 // you've got a computer clocked at several THz or have a br oken benchmark. ;) |
546 // "1B ought to be enough for anybody." | 562 // "1B ought to be enough for anybody." |
547 SkString str; | 563 logger.logError(SkStringPrintf( |
548 str.printf("Can't ramp %s to %dms.\n", bench->getName(), FLA GS_benchMs); | 564 "Can't get %s %s to converge in %dms.\n", |
549 logger.logError(str); | 565 bench->getName(), config.name, FLAGS_maxMs)); |
550 break; | 566 break; |
551 } | 567 } |
552 bench->setLoops(loops == 0 ? 1 : loops * 4); | 568 bench->setLoops(loops == 0 ? 1 : loops * 2); |
553 | 569 |
554 if ((benchMode == kRecord_BenchMode || benchMode == kPictureReco rd_BenchMode)) { | 570 if ((benchMode == kRecord_BenchMode || benchMode == kPictureReco rd_BenchMode)) { |
555 // Clear the recorded commands so that they do not accumulat e. | 571 // Clear the recorded commands so that they do not accumulat e. |
556 canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecord Flags)); | 572 canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecord Flags)); |
557 } | 573 } |
558 | 574 |
559 timer.start(); | 575 timer.start(); |
560 if (NULL != canvas) { | 576 if (NULL != canvas) { |
561 canvas->save(); | 577 canvas->save(); |
562 } | 578 } |
(...skipping 16 matching lines...) Expand all Loading... | |
579 | 595 |
580 // Stop truncated timers before GL calls complete, and stop the full timers after. | 596 // Stop truncated timers before GL calls complete, and stop the full timers after. |
581 timer.truncatedEnd(); | 597 timer.truncatedEnd(); |
582 #if SK_SUPPORT_GPU | 598 #if SK_SUPPORT_GPU |
583 if (NULL != glContext) { | 599 if (NULL != glContext) { |
584 context->flush(); | 600 context->flush(); |
585 SK_GL(*glContext, Finish()); | 601 SK_GL(*glContext, Finish()); |
586 } | 602 } |
587 #endif | 603 #endif |
588 timer.end(); | 604 timer.end(); |
589 } while (!kIsDebug && timer.fWall < FLAGS_benchMs); // One loop onl y in debug mode. | 605 const double current = timer.fWall / bench->getLoops(); |
robertphillips
2013/09/13 20:00:59
if () {
}
mtklein
2013/09/13 20:07:46
Done.
| |
606 if (FLAGS_verbose && current > previous) SkDebugf("↑"); | |
robertphillips
2013/09/13 20:00:59
same here
mtklein
2013/09/13 20:07:46
Done.
| |
607 if (FLAGS_verbose) SkDebugf("%.3g ", current); | |
608 converged = HasConverged(previous, current, timer.fWall); | |
609 previous = current; | |
610 } while (!kIsDebug && !converged); | |
robertphillips
2013/09/13 20:00:59
and here
mtklein
2013/09/13 20:07:46
Done.
| |
611 if (FLAGS_verbose) SkDebugf("\n"); | |
590 | 612 |
591 if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend) { | 613 if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend) { |
592 saveFile(bench->getName(), | 614 saveFile(bench->getName(), |
593 config.name, | 615 config.name, |
594 FLAGS_outDir[0], | 616 FLAGS_outDir[0], |
595 device->accessBitmap(false)); | 617 device->accessBitmap(false)); |
596 } | 618 } |
597 | 619 |
598 if (kIsDebug) { | 620 if (kIsDebug) { |
599 // Let's not mislead ourselves by looking at Debug build bench t imes! | 621 // Let's not mislead ourselves by looking at Debug build bench t imes! |
(...skipping 28 matching lines...) Expand all Loading... | |
628 gContextFactory.destroyContexts(); | 650 gContextFactory.destroyContexts(); |
629 #endif | 651 #endif |
630 return 0; | 652 return 0; |
631 } | 653 } |
632 | 654 |
633 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 655 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
634 int main(int argc, char * const argv[]) { | 656 int main(int argc, char * const argv[]) { |
635 return tool_main(argc, (char**) argv); | 657 return tool_main(argc, (char**) argv); |
636 } | 658 } |
637 #endif | 659 #endif |
OLD | NEW |