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 | |
mtklein
2013/10/10 15:01:05
Any particular reason? Just to keep the CL focuse
| |
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 |