| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBenchLogger.h" | 8 #include "SkBenchLogger.h" |
| 9 #include "BenchTimer.h" | 9 #include "BenchTimer.h" |
| 10 #include "PictureBenchmark.h" | 10 #include "PictureBenchmark.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 SkASSERT(fRenderer != NULL); | 71 SkASSERT(fRenderer != NULL); |
| 72 if (NULL == fRenderer) { | 72 if (NULL == fRenderer) { |
| 73 return; | 73 return; |
| 74 } | 74 } |
| 75 | 75 |
| 76 fRenderer->init(pict); | 76 fRenderer->init(pict); |
| 77 | 77 |
| 78 // We throw this away to remove first time effects (such as paging in this p
rogram) | 78 // We throw this away to remove first time effects (such as paging in this p
rogram) |
| 79 fRenderer->setup(); | 79 fRenderer->setup(); |
| 80 fRenderer->render(NULL); | 80 fRenderer->render(NULL); |
| 81 fRenderer->resetState(true); | 81 fRenderer->resetState(true); // flush, swapBuffers and Finish |
| 82 | 82 |
| 83 if (fPurgeDecodedTex) { | 83 if (fPurgeDecodedTex) { |
| 84 fRenderer->purgeTextures(); | 84 fRenderer->purgeTextures(); |
| 85 } | 85 } |
| 86 | 86 |
| 87 bool usingGpu = false; | 87 bool usingGpu = false; |
| 88 #if SK_SUPPORT_GPU | 88 #if SK_SUPPORT_GPU |
| 89 usingGpu = fRenderer->isUsingGpuDevice(); | 89 usingGpu = fRenderer->isUsingGpuDevice(); |
| 90 #endif | 90 #endif |
| 91 | 91 |
| 92 uint32_t timerTypes = fTimerTypes; | 92 uint32_t timerTypes = fTimerTypes; |
| 93 if (!usingGpu) { | 93 if (!usingGpu) { |
| 94 timerTypes &= ~TimerData::kGpu_Flag; | 94 timerTypes &= ~TimerData::kGpu_Flag; |
| 95 } | 95 } |
| 96 | 96 |
| 97 SkString timeFormat; | 97 SkString timeFormat; |
| 98 if (TimerData::kPerIter_Result == fTimerResult) { | 98 if (TimerData::kPerIter_Result == fTimerResult) { |
| 99 timeFormat = fRenderer->getPerIterTimeFormat(); | 99 timeFormat = fRenderer->getPerIterTimeFormat(); |
| 100 } else { | 100 } else { |
| 101 timeFormat = fRenderer->getNormalTimeFormat(); | 101 timeFormat = fRenderer->getNormalTimeFormat(); |
| 102 } | 102 } |
| 103 | 103 |
| 104 static const int kNumInnerLoops = 5; |
| 105 int numOuterLoops = 1; |
| 106 int numInnerLoops = fRepeats; |
| 107 |
| 108 if (TimerData::kPerIter_Result == fTimerResult && fRepeats > 1) { |
| 109 // interpret this flag combination to mean: generate 'fRepeats' |
| 110 // numbers by averaging each rendering 'kNumInnerLoops' times |
| 111 numOuterLoops = fRepeats; |
| 112 numInnerLoops = kNumInnerLoops; |
| 113 } |
| 114 |
| 104 if (fTimeIndividualTiles) { | 115 if (fTimeIndividualTiles) { |
| 105 TiledPictureRenderer* tiledRenderer = fRenderer->getTiledRenderer(); | 116 TiledPictureRenderer* tiledRenderer = fRenderer->getTiledRenderer(); |
| 106 SkASSERT(tiledRenderer && tiledRenderer->supportsTimingIndividualTiles()
); | 117 SkASSERT(tiledRenderer && tiledRenderer->supportsTimingIndividualTiles()
); |
| 107 if (NULL == tiledRenderer || !tiledRenderer->supportsTimingIndividualTil
es()) { | 118 if (NULL == tiledRenderer || !tiledRenderer->supportsTimingIndividualTil
es()) { |
| 108 return; | 119 return; |
| 109 } | 120 } |
| 110 int xTiles, yTiles; | 121 int xTiles, yTiles; |
| 111 if (!tiledRenderer->tileDimensions(xTiles, yTiles)) { | 122 if (!tiledRenderer->tileDimensions(xTiles, yTiles)) { |
| 112 return; | 123 return; |
| 113 } | 124 } |
| 114 | 125 |
| 115 // Insert a newline so that each tile is reported on its own line (separ
ate from the line | 126 // Insert a newline so that each tile is reported on its own line (separ
ate from the line |
| 116 // that describes the skp being run). | 127 // that describes the skp being run). |
| 117 this->logProgress("\n"); | 128 this->logProgress("\n"); |
| 118 | 129 |
| 119 int x, y; | 130 int x, y; |
| 120 while (tiledRenderer->nextTile(x, y)) { | 131 while (tiledRenderer->nextTile(x, y)) { |
| 121 // There are two timers, which will behave slightly differently: | 132 // There are two timers, which will behave slightly differently: |
| 122 // 1) longRunningTimer, along with perTileTimerData, will time how l
ong it takes to draw | 133 // 1) longRunningTimer, along with perTileTimerData, will time how l
ong it takes to draw |
| 123 // one tile fRepeats times, and take the average. As such, it will n
ot respect thea | 134 // one tile fRepeats times, and take the average. As such, it will n
ot respect the |
| 124 // logPerIter or printMin options, since it does not know the time p
er iteration. It | 135 // logPerIter or printMin options, since it does not know the time p
er iteration. It |
| 125 // will also be unable to call flush() for each tile. | 136 // will also be unable to call flush() for each tile. |
| 126 // The goal of this timer is to make up for a system timer that is n
ot precise enough to | 137 // The goal of this timer is to make up for a system timer that is n
ot precise enough to |
| 127 // measure the small amount of time it takes to draw one tile once. | 138 // measure the small amount of time it takes to draw one tile once. |
| 128 // | 139 // |
| 129 // 2) perTileTimer, along with perTileTimerData, will record each ru
n separately, and | 140 // 2) perTileTimer, along with perTileTimerData, will record each ru
n separately, and |
| 130 // then take the average. As such, it supports logPerIter and printM
in options. | 141 // then take the average. As such, it supports logPerIter and printM
in options. |
| 131 // | 142 // |
| 132 // Although "legal", having two gpu timers running at the same time | 143 // Although "legal", having two gpu timers running at the same time |
| 133 // seems to cause problems (i.e., INVALID_OPERATIONs) on several | 144 // seems to cause problems (i.e., INVALID_OPERATIONs) on several |
| 134 // platforms. To work around this, we disable the gpu timer on the | 145 // platforms. To work around this, we disable the gpu timer on the |
| 135 // long running timer. | 146 // long running timer. |
| 136 SkAutoTDelete<BenchTimer> longRunningTimer(this->setupTimer()); | 147 SkAutoTDelete<BenchTimer> longRunningTimer(this->setupTimer()); |
| 137 TimerData longRunningTimerData(1); | 148 TimerData longRunningTimerData(numOuterLoops); |
| 138 SkAutoTDelete<BenchTimer> perTileTimer(this->setupTimer(false)); | |
| 139 TimerData perTileTimerData(fRepeats); | |
| 140 longRunningTimer->start(); | |
| 141 for (int i = 0; i < fRepeats; ++i) { | |
| 142 perTileTimer->start(); | |
| 143 tiledRenderer->drawCurrentTile(); | |
| 144 perTileTimer->truncatedEnd(); | |
| 145 tiledRenderer->resetState(false); | |
| 146 perTileTimer->end(); | |
| 147 SkAssertResult(perTileTimerData.appendTimes(perTileTimer.get()))
; | |
| 148 | 149 |
| 149 if (fPurgeDecodedTex) { | 150 for (int outer = 0; outer < numOuterLoops; ++outer) { |
| 150 fRenderer->purgeTextures(); | 151 SkAutoTDelete<BenchTimer> perTileTimer(this->setupTimer(false)); |
| 152 TimerData perTileTimerData(numInnerLoops); |
| 153 |
| 154 longRunningTimer->start(); |
| 155 for (int inner = 0; inner < numInnerLoops; ++inner) { |
| 156 perTileTimer->start(); |
| 157 tiledRenderer->drawCurrentTile(); |
| 158 perTileTimer->truncatedEnd(); |
| 159 tiledRenderer->resetState(false); // flush & swapBuffers, b
ut don't Finish |
| 160 perTileTimer->end(); |
| 161 SkAssertResult(perTileTimerData.appendTimes(perTileTimer.get
())); |
| 162 |
| 163 if (fPurgeDecodedTex) { |
| 164 fRenderer->purgeTextures(); |
| 165 } |
| 151 } | 166 } |
| 167 longRunningTimer->truncatedEnd(); |
| 168 tiledRenderer->resetState(true); // flush, swapBuffers and
Finish |
| 169 longRunningTimer->end(); |
| 170 SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer
.get())); |
| 152 } | 171 } |
| 153 longRunningTimer->truncatedEnd(); | |
| 154 tiledRenderer->resetState(true); | |
| 155 longRunningTimer->end(); | |
| 156 SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get
())); | |
| 157 | 172 |
| 158 SkString configName = tiledRenderer->getConfigName(); | 173 SkString configName = tiledRenderer->getConfigName(); |
| 159 configName.appendf(": tile [%i,%i] out of [%i,%i]", x, y, xTiles, yT
iles); | 174 configName.appendf(": tile [%i,%i] out of [%i,%i]", x, y, xTiles, yT
iles); |
| 160 | 175 |
| 176 // TODO(borenet): Turn off per-iteration tile time reporting for now
. |
| 177 // Avoiding logging the time for every iteration for each tile cuts |
| 178 // down on data file size by a significant amount. Re-enable this on
ce |
| 179 // we're loading the bench data directly into a data store and are n
o |
| 180 // longer generating SVG graphs. |
| 181 #if 0 |
| 161 SkString result = perTileTimerData.getResult(timeFormat.c_str(), fTi
merResult, | 182 SkString result = perTileTimerData.getResult(timeFormat.c_str(), fTi
merResult, |
| 162 configName.c_str(), tim
erTypes); | 183 configName.c_str(), tim
erTypes); |
| 163 result.append("\n"); | 184 result.append("\n"); |
| 164 | |
| 165 // TODO(borenet): Turn off per-iteration tile time reporting for now. Avoiding
logging the time | |
| 166 // for every iteration for each tile cuts down on data file size by a significan
t amount. Re-enable | |
| 167 // this once we're loading the bench data directly into a data store and are no
longer generating | |
| 168 // SVG graphs. | |
| 169 #if 0 | |
| 170 this->logProgress(result.c_str()); | 185 this->logProgress(result.c_str()); |
| 171 #endif | 186 #endif |
| 187 |
| 172 if (fPurgeDecodedTex) { | 188 if (fPurgeDecodedTex) { |
| 173 configName.append(" <withPurging>"); | 189 configName.append(" <withPurging>"); |
| 174 } | 190 } |
| 175 configName.append(" <averaged>"); | 191 configName.append(" <averaged>"); |
| 176 SkString longRunningResult = longRunningTimerData.getResult( | 192 SkString longRunningResult = longRunningTimerData.getResult( |
| 177 tiledRenderer->getNormalTimeFormat().c_str(), | 193 tiledRenderer->getNormalTimeFormat().c_str(), |
| 178 TimerData::kAvg_Result, | 194 TimerData::kAvg_Result, |
| 179 configName.c_str(), timerTypes, fRepeats); | 195 configName.c_str(), timerTypes, numInnerLoops); |
| 180 longRunningResult.append("\n"); | 196 longRunningResult.append("\n"); |
| 181 this->logProgress(longRunningResult.c_str()); | 197 this->logProgress(longRunningResult.c_str()); |
| 182 } | 198 } |
| 183 } else { | 199 } else { |
| 184 SkAutoTDelete<BenchTimer> longRunningTimer(this->setupTimer()); | 200 SkAutoTDelete<BenchTimer> longRunningTimer(this->setupTimer()); |
| 185 TimerData longRunningTimerData(1); | 201 TimerData longRunningTimerData(numOuterLoops); |
| 186 SkAutoTDelete<BenchTimer> perRunTimer(this->setupTimer(false)); | |
| 187 TimerData perRunTimerData(fRepeats); | |
| 188 | 202 |
| 189 longRunningTimer->start(); | 203 for (int outer = 0; outer < numOuterLoops; ++outer) { |
| 190 for (int i = 0; i < fRepeats; ++i) { | 204 SkAutoTDelete<BenchTimer> perRunTimer(this->setupTimer(false)); |
| 191 fRenderer->setup(); | 205 TimerData perRunTimerData(numInnerLoops); |
| 192 | 206 |
| 193 perRunTimer->start(); | 207 longRunningTimer->start(); |
| 194 fRenderer->render(NULL); | 208 for (int inner = 0; inner < numInnerLoops; ++inner) { |
| 195 perRunTimer->truncatedEnd(); | 209 fRenderer->setup(); |
| 196 fRenderer->resetState(false); | |
| 197 perRunTimer->end(); | |
| 198 | 210 |
| 199 SkAssertResult(perRunTimerData.appendTimes(perRunTimer.get())); | 211 perRunTimer->start(); |
| 212 fRenderer->render(NULL); |
| 213 perRunTimer->truncatedEnd(); |
| 214 fRenderer->resetState(false); // flush & swapBuffers, but don'
t Finish |
| 215 perRunTimer->end(); |
| 200 | 216 |
| 201 if (fPurgeDecodedTex) { | 217 SkAssertResult(perRunTimerData.appendTimes(perRunTimer.get())); |
| 202 fRenderer->purgeTextures(); | 218 |
| 219 if (fPurgeDecodedTex) { |
| 220 fRenderer->purgeTextures(); |
| 221 } |
| 203 } | 222 } |
| 223 longRunningTimer->truncatedEnd(); |
| 224 fRenderer->resetState(true); // flush, swapBuffers and Finish |
| 225 longRunningTimer->end(); |
| 226 SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get
())); |
| 204 } | 227 } |
| 205 longRunningTimer->truncatedEnd(); | |
| 206 fRenderer->resetState(true); | |
| 207 longRunningTimer->end(); | |
| 208 SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get()))
; | |
| 209 | 228 |
| 210 SkString configName = fRenderer->getConfigName(); | 229 SkString configName = fRenderer->getConfigName(); |
| 211 if (fPurgeDecodedTex) { | 230 if (fPurgeDecodedTex) { |
| 212 configName.append(" <withPurging>"); | 231 configName.append(" <withPurging>"); |
| 213 } | 232 } |
| 214 | 233 |
| 215 // Beware - since the per-run-timer doesn't ever include a glFinish it c
an | 234 // Beware - since the per-run-timer doesn't ever include a glFinish it c
an |
| 216 // report a lower time then the long-running-timer | 235 // report a lower time then the long-running-timer |
| 217 #if 0 | 236 #if 0 |
| 218 SkString result = perRunTimerData.getResult(timeFormat.c_str(), | 237 SkString result = perRunTimerData.getResult(timeFormat.c_str(), |
| 219 fTimerResult, | 238 fTimerResult, |
| 220 configName.c_str(), | 239 configName.c_str(), |
| 221 timerTypes); | 240 timerTypes); |
| 222 result.append("\n"); | 241 result.append("\n"); |
| 223 | 242 |
| 224 this->logProgress(result.c_str()); | 243 this->logProgress(result.c_str()); |
| 225 #else | 244 #else |
| 226 SkString result = longRunningTimerData.getResult(timeFormat.c_str(), | 245 SkString result = longRunningTimerData.getResult(timeFormat.c_str(), |
| 227 fTimerResult, | 246 fTimerResult, |
| 228 configName.c_str(), | 247 configName.c_str(), |
| 229 timerTypes, | 248 timerTypes, |
| 230 fRepeats); | 249 numInnerLoops); |
| 231 result.append("\n"); | 250 result.append("\n"); |
| 232 this->logProgress(result.c_str()); | 251 this->logProgress(result.c_str()); |
| 233 #endif | 252 #endif |
| 234 } | 253 } |
| 235 | 254 |
| 236 fRenderer->end(); | 255 fRenderer->end(); |
| 237 } | 256 } |
| 238 | 257 |
| 239 } | 258 } |
| OLD | NEW |