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