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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 if (kGPU_Backend == config.backend) { | 558 if (kGPU_Backend == config.backend) { |
559 contextHelper = gContextFactory.getGLContext(config.contextType)
; | 559 contextHelper = gContextFactory.getGLContext(config.contextType)
; |
560 } | 560 } |
561 BenchTimer timer(contextHelper); | 561 BenchTimer timer(contextHelper); |
562 #else | 562 #else |
563 BenchTimer timer; | 563 BenchTimer timer; |
564 #endif | 564 #endif |
565 | 565 |
566 double previous = std::numeric_limits<double>::infinity(); | 566 double previous = std::numeric_limits<double>::infinity(); |
567 bool converged = false; | 567 bool converged = false; |
568 bench->setLoops(0); | 568 |
| 569 // variables used to compute loopsPerFrame |
| 570 double frameIntervalTime = 0.0f; |
| 571 int frameIntervalTotalLoops = 0; |
| 572 |
| 573 bool frameIntervalComputed = false; |
| 574 int loopsPerFrame = 0; |
| 575 int loopsPerIter = 0; |
569 if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.na
me); } | 576 if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.na
me); } |
570 do { | 577 do { |
571 // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion. | 578 // Ramp up 1 -> 2 -> 4 -> 8 -> 16 -> ... -> ~1 billion. |
572 const int loops = bench->getLoops(); | 579 loopsPerIter = (loopsPerIter == 0) ? 1 : loopsPerIter * 2; |
573 if (loops >= (1<<30) || timer.fWall > FLAGS_maxMs) { | 580 if (loopsPerIter >= (1<<30) || timer.fWall > FLAGS_maxMs) { |
574 // If you find it takes more than a billion loops to get up
to 20ms of runtime, | 581 // If you find it takes more than a billion loops to get up
to 20ms of runtime, |
575 // you've got a computer clocked at several THz or have a br
oken benchmark. ;) | 582 // you've got a computer clocked at several THz or have a br
oken benchmark. ;) |
576 // "1B ought to be enough for anybody." | 583 // "1B ought to be enough for anybody." |
577 logger.logError(SkStringPrintf( | 584 logger.logError(SkStringPrintf( |
578 "Can't get %s %s to converge in %dms.\n", | 585 "\nCan't get %s %s to converge in %dms (%d loops)", |
579 bench->getName(), config.name, FLAGS_maxMs)); | 586 bench->getName(), config.name, FLAGS_maxMs, loopsPerIte
r)); |
580 break; | 587 break; |
581 } | 588 } |
582 bench->setLoops(loops == 0 ? 1 : loops * 2); | |
583 | 589 |
584 if ((benchMode == kRecord_BenchMode || benchMode == kPictureReco
rd_BenchMode)) { | 590 if ((benchMode == kRecord_BenchMode || benchMode == kPictureReco
rd_BenchMode)) { |
585 // Clear the recorded commands so that they do not accumulat
e. | 591 // Clear the recorded commands so that they do not accumulat
e. |
586 canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecord
Flags)); | 592 canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecord
Flags)); |
587 } | 593 } |
588 | 594 |
589 timer.start(); | 595 timer.start(); |
590 if (NULL != canvas) { | 596 if (NULL != canvas) { |
591 canvas->save(); | 597 canvas->save(); |
592 } | 598 } |
593 if (benchMode == kPictureRecord_BenchMode) { | |
594 recordFrom.draw(canvas); | |
595 } else { | |
596 bench->draw(canvas); | |
597 } | |
598 | 599 |
599 if (kDeferredSilent_BenchMode == benchMode) { | 600 // Inner loop that allows us to break the run into smaller |
600 static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush(); | 601 // chunks (e.g. frames). This is especially useful for the GPU |
601 } else if (NULL != canvas) { | 602 // as we can flush and/or swap buffers to keep the GPU from |
602 canvas->flush(); | 603 // queuing up too much work. |
| 604 for (int loopCount = loopsPerIter; loopCount > 0; ) { |
| 605 if (frameIntervalComputed && loopCount > loopsPerFrame) { |
| 606 bench->setLoops(loopsPerFrame); |
| 607 loopCount -= loopsPerFrame; |
| 608 } else { |
| 609 bench->setLoops(loopCount); |
| 610 loopCount = 0; |
| 611 } |
| 612 |
| 613 if (benchMode == kPictureRecord_BenchMode) { |
| 614 recordFrom.draw(canvas); |
| 615 } else { |
| 616 bench->draw(canvas); |
| 617 } |
| 618 |
| 619 if (kDeferredSilent_BenchMode == benchMode) { |
| 620 static_cast<SkDeferredCanvas*>(canvas.get())->silentFlus
h(); |
| 621 } else if (NULL != canvas) { |
| 622 canvas->flush(); |
| 623 } |
| 624 |
| 625 #if SK_SUPPORT_GPU |
| 626 // swap drawing buffers on each frame to prevent the GPU |
| 627 // from queuing up too much work |
| 628 if (NULL != glContext) { |
| 629 glContext->swapBuffers(); |
| 630 } |
| 631 #endif |
603 } | 632 } |
604 | 633 |
605 if (NULL != canvas) { | 634 if (NULL != canvas) { |
606 canvas->restore(); | 635 canvas->restore(); |
607 } | 636 } |
608 | 637 |
609 | 638 |
610 // Stop truncated timers before GL calls complete, and stop the
full timers after. | 639 // Stop truncated timers before GL calls complete, and stop the
full timers after. |
611 timer.truncatedEnd(); | 640 timer.truncatedEnd(); |
612 #if SK_SUPPORT_GPU | 641 #if SK_SUPPORT_GPU |
613 if (NULL != glContext) { | 642 if (NULL != glContext) { |
614 context->flush(); | 643 context->flush(); |
615 SK_GL(*glContext, Finish()); | 644 SK_GL(*glContext, Finish()); |
616 } | 645 } |
617 #endif | 646 #endif |
618 timer.end(); | 647 timer.end(); |
619 const double current = timer.fWall / bench->getLoops(); | 648 |
| 649 #if SK_SUPPORT_GPU |
| 650 // currently we only setup the frame interval for the GPU |
| 651 if (!frameIntervalComputed && NULL != glContext) { |
| 652 frameIntervalTime += timer.fWall; |
| 653 frameIntervalTotalLoops += loopsPerIter; |
| 654 if (frameIntervalTime >= FLAGS_minMs) { |
| 655 frameIntervalComputed = true; |
| 656 loopsPerFrame = |
| 657 ((double)frameIntervalTotalLoops / frameIntervalTime
) * FLAGS_minMs; |
| 658 if (loopsPerFrame < 1) { |
| 659 loopsPerFrame = 1; |
| 660 } |
| 661 // SkDebugf(" %s has %d loops in %f ms (normalized to %d
)\n", |
| 662 // bench->getName(), frameIntervalTotalLoops, |
| 663 // timer.fWall, loopsPerFrame); |
| 664 } |
| 665 } |
| 666 #endif |
| 667 const double current = timer.fWall / loopsPerIter; |
620 if (FLAGS_verbose && current > previous) { SkDebugf("↑"); } | 668 if (FLAGS_verbose && current > previous) { SkDebugf("↑"); } |
621 if (FLAGS_verbose) { SkDebugf("%.3g ", current); } | 669 if (FLAGS_verbose) { SkDebugf("%.3g ", current); } |
622 converged = HasConverged(previous, current, timer.fWall); | 670 converged = HasConverged(previous, current, timer.fWall); |
623 previous = current; | 671 previous = current; |
624 } while (!kIsDebug && !converged); | 672 } while (!kIsDebug && !converged); |
625 if (FLAGS_verbose) { SkDebugf("\n"); } | 673 if (FLAGS_verbose) { SkDebugf("\n"); } |
626 | 674 |
627 if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend)
{ | 675 if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend)
{ |
628 saveFile(bench->getName(), | 676 saveFile(bench->getName(), |
629 config.name, | 677 config.name, |
630 FLAGS_outDir[0], | 678 FLAGS_outDir[0], |
631 device->accessBitmap(false)); | 679 device->accessBitmap(false)); |
632 } | 680 } |
633 | 681 |
634 if (kIsDebug) { | 682 if (kIsDebug) { |
635 // Let's not mislead ourselves by looking at Debug build bench t
imes! | 683 // Let's not mislead ourselves by looking at Debug build bench t
imes! |
636 continue; | 684 continue; |
637 } | 685 } |
638 | 686 |
639 // Normalize to ms per 1000 iterations. | 687 // Normalize to ms per 1000 iterations. |
640 const double normalize = 1000.0 / bench->getLoops(); | 688 const double normalize = 1000.0 / loopsPerIter; |
641 const struct { char shortName; const char* longName; double ms; } ti
mes[] = { | 689 const struct { char shortName; const char* longName; double ms; } ti
mes[] = { |
642 {'w', "msecs", normalize * timer.fWall}, | 690 {'w', "msecs", normalize * timer.fWall}, |
643 {'W', "Wmsecs", normalize * timer.fTruncatedWall}, | 691 {'W', "Wmsecs", normalize * timer.fTruncatedWall}, |
644 {'c', "cmsecs", normalize * timer.fCpu}, | 692 {'c', "cmsecs", normalize * timer.fCpu}, |
645 {'C', "Cmsecs", normalize * timer.fTruncatedCpu}, | 693 {'C', "Cmsecs", normalize * timer.fTruncatedCpu}, |
646 {'g', "gmsecs", normalize * timer.fGpu}, | 694 {'g', "gmsecs", normalize * timer.fGpu}, |
647 }; | 695 }; |
648 | 696 |
649 SkString result; | 697 SkString result; |
650 result.appendf(" %s:", config.name); | 698 result.appendf(" %s:", config.name); |
(...skipping 13 matching lines...) Expand all Loading... |
664 gContextFactory.destroyContexts(); | 712 gContextFactory.destroyContexts(); |
665 #endif | 713 #endif |
666 return 0; | 714 return 0; |
667 } | 715 } |
668 | 716 |
669 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 717 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
670 int main(int argc, char * const argv[]) { | 718 int main(int argc, char * const argv[]) { |
671 return tool_main(argc, (char**) argv); | 719 return tool_main(argc, (char**) argv); |
672 } | 720 } |
673 #endif | 721 #endif |
OLD | NEW |