Home | History | Annotate | Download | only in tools
      1 /*
      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 "SkBenchLogger.h"
      9 #include "BenchTimer.h"
     10 #include "PictureBenchmark.h"
     11 #include "SkCanvas.h"
     12 #include "SkPicture.h"
     13 #include "SkString.h"
     14 #include "picture_utils.h"
     15 #include "TimerData.h"
     16 
     17 namespace sk_tools {
     18 
     19 PictureBenchmark::PictureBenchmark()
     20 : fRepeats(1)
     21 , fLogger(NULL)
     22 , fRenderer(NULL)
     23 , fLogPerIter(false)
     24 , fPrintMin(false)
     25 , fShowWallTime(false)
     26 , fShowTruncatedWallTime(false)
     27 , fShowCpuTime(true)
     28 , fShowTruncatedCpuTime(false)
     29 , fShowGpuTime(false)
     30 , fTimeIndividualTiles(false)
     31 {}
     32 
     33 PictureBenchmark::~PictureBenchmark() {
     34     SkSafeUnref(fRenderer);
     35 }
     36 
     37 BenchTimer* PictureBenchmark::setupTimer() {
     38 #if SK_SUPPORT_GPU
     39     if (fRenderer != NULL && fRenderer->isUsingGpuDevice()) {
     40         return SkNEW_ARGS(BenchTimer, (fRenderer->getGLContext()));
     41     }
     42 #endif
     43     return SkNEW_ARGS(BenchTimer, (NULL));
     44 }
     45 
     46 void PictureBenchmark::logProgress(const char msg[]) {
     47     if (fLogger != NULL) {
     48         fLogger->logProgress(msg);
     49     }
     50 }
     51 
     52 PictureRenderer* PictureBenchmark::setRenderer(sk_tools::PictureRenderer* renderer) {
     53     SkRefCnt_SafeAssign(fRenderer, renderer);
     54     return renderer;
     55 }
     56 
     57 void PictureBenchmark::run(SkPicture* pict) {
     58     SkASSERT(pict);
     59     if (NULL == pict) {
     60         return;
     61     }
     62 
     63     SkASSERT(fRenderer != NULL);
     64     if (NULL == fRenderer) {
     65         return;
     66     }
     67 
     68     fRenderer->init(pict);
     69 
     70     // We throw this away to remove first time effects (such as paging in this program)
     71     fRenderer->setup();
     72     fRenderer->render(NULL);
     73     fRenderer->resetState(true);
     74 
     75     bool usingGpu = false;
     76 #if SK_SUPPORT_GPU
     77     usingGpu = fRenderer->isUsingGpuDevice();
     78 #endif
     79 
     80     if (fTimeIndividualTiles) {
     81         TiledPictureRenderer* tiledRenderer = fRenderer->getTiledRenderer();
     82         SkASSERT(tiledRenderer);
     83         if (NULL == tiledRenderer) {
     84             return;
     85         }
     86         int xTiles, yTiles;
     87         if (!tiledRenderer->tileDimensions(xTiles, yTiles)) {
     88             return;
     89         }
     90 
     91         // Insert a newline so that each tile is reported on its own line (separate from the line
     92         // that describes the skp being run).
     93         this->logProgress("\n");
     94 
     95         int x, y;
     96         while (tiledRenderer->nextTile(x, y)) {
     97             // There are two timers, which will behave slightly differently:
     98             // 1) longRunningTimer, along with perTileTimerData, will time how long it takes to draw
     99             // one tile fRepeats times, and take the average. As such, it will not respect the
    100             // logPerIter or printMin options, since it does not know the time per iteration. It
    101             // will also be unable to call flush() for each tile.
    102             // The goal of this timer is to make up for a system timer that is not precise enough to
    103             // measure the small amount of time it takes to draw one tile once.
    104             //
    105             // 2) perTileTimer, along with perTileTimerData, will record each run separately, and
    106             // then take the average. As such, it supports logPerIter and printMin options.
    107             SkAutoTDelete<BenchTimer> longRunningTimer(this->setupTimer());
    108             TimerData longRunningTimerData(tiledRenderer->getPerIterTimeFormat(),
    109                                            tiledRenderer->getNormalTimeFormat());
    110             SkAutoTDelete<BenchTimer> perTileTimer(this->setupTimer());
    111             TimerData perTileTimerData(tiledRenderer->getPerIterTimeFormat(),
    112                                        tiledRenderer->getNormalTimeFormat());
    113             longRunningTimer->start();
    114             for (int i = 0; i < fRepeats; ++i) {
    115                 perTileTimer->start();
    116                 tiledRenderer->drawCurrentTile();
    117                 perTileTimer->truncatedEnd();
    118                 tiledRenderer->resetState(false);
    119                 perTileTimer->end();
    120                 perTileTimerData.appendTimes(perTileTimer.get(), fRepeats - 1 == i);
    121             }
    122             longRunningTimer->truncatedEnd();
    123             tiledRenderer->resetState(true);
    124             longRunningTimer->end();
    125             longRunningTimerData.appendTimes(longRunningTimer.get(), true);
    126 
    127             SkString configName = tiledRenderer->getConfigName();
    128             configName.appendf(": tile [%i,%i] out of [%i,%i]", x, y, xTiles, yTiles);
    129             SkString result = perTileTimerData.getResult(fLogPerIter, fPrintMin, fRepeats,
    130                                                          configName.c_str(), fShowWallTime,
    131                                                          fShowTruncatedWallTime, fShowCpuTime,
    132                                                          fShowTruncatedCpuTime,
    133                                                          usingGpu && fShowGpuTime);
    134             result.append("\n");
    135             this->logProgress(result.c_str());
    136 
    137             configName.append(" <averaged>");
    138             SkString longRunningResult = longRunningTimerData.getResult(false, false, fRepeats,
    139                     configName.c_str(), fShowWallTime, fShowTruncatedWallTime,
    140                     fShowCpuTime, fShowTruncatedCpuTime, usingGpu && fShowGpuTime);
    141             longRunningResult.append("\n");
    142             this->logProgress(longRunningResult.c_str());
    143         }
    144     } else {
    145         SkAutoTDelete<BenchTimer> timer(this->setupTimer());
    146         TimerData timerData(fRenderer->getPerIterTimeFormat(), fRenderer->getNormalTimeFormat());
    147         for (int i = 0; i < fRepeats; ++i) {
    148             fRenderer->setup();
    149 
    150             timer->start();
    151             fRenderer->render(NULL);
    152             timer->truncatedEnd();
    153 
    154             // Finishes gl context
    155             fRenderer->resetState(true);
    156             timer->end();
    157 
    158             timerData.appendTimes(timer.get(), fRepeats - 1 == i);
    159         }
    160 
    161         SkString configName = fRenderer->getConfigName();
    162         SkString result = timerData.getResult(fLogPerIter, fPrintMin, fRepeats,
    163                                               configName.c_str(), fShowWallTime,
    164                                               fShowTruncatedWallTime, fShowCpuTime,
    165                                               fShowTruncatedCpuTime, usingGpu && fShowGpuTime);
    166         result.append("\n");
    167         this->logProgress(result.c_str());
    168     }
    169 
    170     fRenderer->end();
    171 }
    172 
    173 }
    174