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 |