| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 <ctype.h> | 8 #include <ctype.h> |
| 9 | 9 |
| 10 #include "nanobench.h" | 10 #include "nanobench.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 bool Target::init(SkImageInfo info, Benchmark* bench) { | 95 bool Target::init(SkImageInfo info, Benchmark* bench) { |
| 96 if (Benchmark::kRaster_Backend == config.backend) { | 96 if (Benchmark::kRaster_Backend == config.backend) { |
| 97 this->surface.reset(SkSurface::NewRaster(info)); | 97 this->surface.reset(SkSurface::NewRaster(info)); |
| 98 if (!this->surface.get()) { | 98 if (!this->surface.get()) { |
| 99 return false; | 99 return false; |
| 100 } | 100 } |
| 101 } | 101 } |
| 102 return true; | 102 return true; |
| 103 } | 103 } |
| 104 bool Target::capturePixels(SkBitmap* bmp) { | 104 bool Target::capturePixels(SkBitmap* bmp) { |
| 105 if (!this->surface.get()) { | 105 SkCanvas* canvas = this->getCanvas(); |
| 106 return false; | |
| 107 } | |
| 108 SkCanvas* canvas = this->surface->getCanvas(); | |
| 109 if (!canvas) { | 106 if (!canvas) { |
| 110 return false; | 107 return false; |
| 111 } | 108 } |
| 112 bmp->setInfo(canvas->imageInfo()); | 109 bmp->setInfo(canvas->imageInfo()); |
| 113 if (!canvas->readPixels(bmp, 0, 0)) { | 110 if (!canvas->readPixels(bmp, 0, 0)) { |
| 114 SkDebugf("Can't read canvas pixels.\n"); | 111 SkDebugf("Can't read canvas pixels.\n"); |
| 115 return false; | 112 return false; |
| 116 } | 113 } |
| 117 return true; | 114 return true; |
| 118 } | 115 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR)); | 158 SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR)); |
| 162 log->configOption("GL_VENDOR", (const char*) version); | 159 log->configOption("GL_VENDOR", (const char*) version); |
| 163 | 160 |
| 164 SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION))
; | 161 SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION))
; |
| 165 log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); | 162 log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); |
| 166 } | 163 } |
| 167 }; | 164 }; |
| 168 | 165 |
| 169 #endif | 166 #endif |
| 170 | 167 |
| 171 static double time(int loops, Benchmark* bench, SkCanvas* canvas, Target* target
) { | 168 static double time(int loops, Benchmark* bench, Target* target) { |
| 169 SkCanvas* canvas = target->getCanvas(); |
| 172 if (canvas) { | 170 if (canvas) { |
| 173 canvas->clear(SK_ColorWHITE); | 171 canvas->clear(SK_ColorWHITE); |
| 174 } | 172 } |
| 175 WallTimer timer; | 173 WallTimer timer; |
| 176 timer.start(); | 174 timer.start(); |
| 177 if (target) { | 175 canvas = target->beginTiming(canvas); |
| 178 canvas = target->beginTiming(canvas); | 176 bench->draw(loops, canvas); |
| 179 } | |
| 180 if (bench) { | |
| 181 bench->draw(loops, canvas); | |
| 182 } | |
| 183 if (canvas) { | 177 if (canvas) { |
| 184 canvas->flush(); | 178 canvas->flush(); |
| 185 } | 179 } |
| 186 if (target) { | 180 target->endTiming(); |
| 187 target->endTiming(); | |
| 188 } | |
| 189 timer.end(); | 181 timer.end(); |
| 190 return timer.fWall; | 182 return timer.fWall; |
| 191 } | 183 } |
| 192 | 184 |
| 193 static double estimate_timer_overhead() { | 185 static double estimate_timer_overhead() { |
| 194 double overhead = 0; | 186 double overhead = 0; |
| 195 for (int i = 0; i < FLAGS_overheadLoops; i++) { | 187 for (int i = 0; i < FLAGS_overheadLoops; i++) { |
| 196 overhead += time(1, NULL, NULL, NULL); | 188 WallTimer timer; |
| 189 timer.start(); |
| 190 timer.end(); |
| 191 overhead += timer.fWall; |
| 197 } | 192 } |
| 198 return overhead / FLAGS_overheadLoops; | 193 return overhead / FLAGS_overheadLoops; |
| 199 } | 194 } |
| 200 | 195 |
| 201 static int detect_forever_loops(int loops) { | 196 static int detect_forever_loops(int loops) { |
| 202 // look for a magic run-forever value | 197 // look for a magic run-forever value |
| 203 if (loops < 0) { | 198 if (loops < 0) { |
| 204 loops = SK_MaxS32; | 199 loops = SK_MaxS32; |
| 205 } | 200 } |
| 206 return loops; | 201 return loops; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 217 return FLAGS_maxLoops; | 212 return FLAGS_maxLoops; |
| 218 } | 213 } |
| 219 return loops; | 214 return loops; |
| 220 } | 215 } |
| 221 | 216 |
| 222 static bool write_canvas_png(Target* target, const SkString& filename) { | 217 static bool write_canvas_png(Target* target, const SkString& filename) { |
| 223 | 218 |
| 224 if (filename.isEmpty()) { | 219 if (filename.isEmpty()) { |
| 225 return false; | 220 return false; |
| 226 } | 221 } |
| 227 if (target->surface.get() && target->surface->getCanvas() && | 222 if (target->getCanvas() && |
| 228 kUnknown_SkColorType == target->surface->getCanvas()->imageInfo().colorT
ype()) { | 223 kUnknown_SkColorType == target->getCanvas()->imageInfo().colorType()) { |
| 229 return false; | 224 return false; |
| 230 } | 225 } |
| 231 | 226 |
| 232 SkBitmap bmp; | 227 SkBitmap bmp; |
| 233 | 228 |
| 234 if (!target->capturePixels(&bmp)) { | 229 if (!target->capturePixels(&bmp)) { |
| 235 return false; | 230 return false; |
| 236 } | 231 } |
| 237 | 232 |
| 238 SkString dir = SkOSPath::Dirname(filename.c_str()); | 233 SkString dir = SkOSPath::Dirname(filename.c_str()); |
| 239 if (!sk_mkdir(dir.c_str())) { | 234 if (!sk_mkdir(dir.c_str())) { |
| 240 SkDebugf("Can't make dir %s.\n", dir.c_str()); | 235 SkDebugf("Can't make dir %s.\n", dir.c_str()); |
| 241 return false; | 236 return false; |
| 242 } | 237 } |
| 243 SkFILEWStream stream(filename.c_str()); | 238 SkFILEWStream stream(filename.c_str()); |
| 244 if (!stream.isValid()) { | 239 if (!stream.isValid()) { |
| 245 SkDebugf("Can't write %s.\n", filename.c_str()); | 240 SkDebugf("Can't write %s.\n", filename.c_str()); |
| 246 return false; | 241 return false; |
| 247 } | 242 } |
| 248 if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 1
00)) { | 243 if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 1
00)) { |
| 249 SkDebugf("Can't encode a PNG.\n"); | 244 SkDebugf("Can't encode a PNG.\n"); |
| 250 return false; | 245 return false; |
| 251 } | 246 } |
| 252 return true; | 247 return true; |
| 253 } | 248 } |
| 254 | 249 |
| 255 static int kFailedLoops = -2; | 250 static int kFailedLoops = -2; |
| 256 static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas,
double* samples) { | 251 static int cpu_bench(const double overhead, Target* target, Benchmark* bench, do
uble* samples) { |
| 257 // First figure out approximately how many loops of bench it takes to make o
verhead negligible. | 252 // First figure out approximately how many loops of bench it takes to make o
verhead negligible. |
| 258 double bench_plus_overhead = 0.0; | 253 double bench_plus_overhead = 0.0; |
| 259 int round = 0; | 254 int round = 0; |
| 260 if (kAutoTuneLoops == FLAGS_loops) { | 255 if (kAutoTuneLoops == FLAGS_loops) { |
| 261 while (bench_plus_overhead < overhead) { | 256 while (bench_plus_overhead < overhead) { |
| 262 if (round++ == FLAGS_maxCalibrationAttempts) { | 257 if (round++ == FLAGS_maxCalibrationAttempts) { |
| 263 SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skip
ping.\n", | 258 SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skip
ping.\n", |
| 264 bench->getUniqueName(), HUMANIZE(bench_plus_overhead),
HUMANIZE(overhead)); | 259 bench->getUniqueName(), HUMANIZE(bench_plus_overhead),
HUMANIZE(overhead)); |
| 265 return kFailedLoops; | 260 return kFailedLoops; |
| 266 } | 261 } |
| 267 bench_plus_overhead = time(1, bench, canvas, NULL); | 262 bench_plus_overhead = time(1, bench, target); |
| 268 } | 263 } |
| 269 } | 264 } |
| 270 | 265 |
| 271 // Later we'll just start and stop the timer once but loop N times. | 266 // Later we'll just start and stop the timer once but loop N times. |
| 272 // We'll pick N to make timer overhead negligible: | 267 // We'll pick N to make timer overhead negligible: |
| 273 // | 268 // |
| 274 // overhead | 269 // overhead |
| 275 // ------------------------- < FLAGS_overheadGoal | 270 // ------------------------- < FLAGS_overheadGoal |
| 276 // overhead + N * Bench Time | 271 // overhead + N * Bench Time |
| 277 // | 272 // |
| (...skipping 10 matching lines...) Expand all Loading... |
| 288 if (kAutoTuneLoops == loops) { | 283 if (kAutoTuneLoops == loops) { |
| 289 const double numer = overhead / FLAGS_overheadGoal - overhead; | 284 const double numer = overhead / FLAGS_overheadGoal - overhead; |
| 290 const double denom = bench_plus_overhead - overhead; | 285 const double denom = bench_plus_overhead - overhead; |
| 291 loops = (int)ceil(numer / denom); | 286 loops = (int)ceil(numer / denom); |
| 292 loops = clamp_loops(loops); | 287 loops = clamp_loops(loops); |
| 293 } else { | 288 } else { |
| 294 loops = detect_forever_loops(loops); | 289 loops = detect_forever_loops(loops); |
| 295 } | 290 } |
| 296 | 291 |
| 297 for (int i = 0; i < FLAGS_samples; i++) { | 292 for (int i = 0; i < FLAGS_samples; i++) { |
| 298 samples[i] = time(loops, bench, canvas, NULL) / loops; | 293 samples[i] = time(loops, bench, target) / loops; |
| 299 } | 294 } |
| 300 return loops; | 295 return loops; |
| 301 } | 296 } |
| 302 | 297 |
| 303 static int gpu_bench(Target* target, | 298 static int gpu_bench(Target* target, |
| 304 Benchmark* bench, | 299 Benchmark* bench, |
| 305 SkCanvas* canvas, | |
| 306 double* samples) { | 300 double* samples) { |
| 307 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. | 301 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. |
| 308 int loops = FLAGS_loops; | 302 int loops = FLAGS_loops; |
| 309 if (kAutoTuneLoops == loops) { | 303 if (kAutoTuneLoops == loops) { |
| 310 loops = 1; | 304 loops = 1; |
| 311 double elapsed = 0; | 305 double elapsed = 0; |
| 312 do { | 306 do { |
| 313 if (1<<30 == loops) { | 307 if (1<<30 == loops) { |
| 314 // We're about to wrap. Something's wrong with the bench. | 308 // We're about to wrap. Something's wrong with the bench. |
| 315 loops = 0; | 309 loops = 0; |
| 316 break; | 310 break; |
| 317 } | 311 } |
| 318 loops *= 2; | 312 loops *= 2; |
| 319 // If the GPU lets frames lag at all, we need to make sure we're tim
ing | 313 // If the GPU lets frames lag at all, we need to make sure we're tim
ing |
| 320 // _this_ round, not still timing last round. We force this by loop
ing | 314 // _this_ round, not still timing last round. We force this by loop
ing |
| 321 // more times than any reasonable GPU will allow frames to lag. | 315 // more times than any reasonable GPU will allow frames to lag. |
| 322 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 316 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { |
| 323 elapsed = time(loops, bench, canvas, target); | 317 elapsed = time(loops, bench, target); |
| 324 } | 318 } |
| 325 } while (elapsed < FLAGS_gpuMs); | 319 } while (elapsed < FLAGS_gpuMs); |
| 326 | 320 |
| 327 // We've overshot at least a little. Scale back linearly. | 321 // We've overshot at least a little. Scale back linearly. |
| 328 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); | 322 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); |
| 329 loops = clamp_loops(loops); | 323 loops = clamp_loops(loops); |
| 330 | 324 |
| 331 // Make sure we're not still timing our calibration. | 325 // Make sure we're not still timing our calibration. |
| 332 target->fence(); | 326 target->fence(); |
| 333 } else { | 327 } else { |
| 334 loops = detect_forever_loops(loops); | 328 loops = detect_forever_loops(loops); |
| 335 } | 329 } |
| 336 | 330 |
| 337 // Pretty much the same deal as the calibration: do some warmup to make | 331 // Pretty much the same deal as the calibration: do some warmup to make |
| 338 // sure we're timing steady-state pipelined frames. | 332 // sure we're timing steady-state pipelined frames. |
| 339 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 333 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { |
| 340 time(loops, bench, canvas, target); | 334 time(loops, bench, target); |
| 341 } | 335 } |
| 342 | 336 |
| 343 // Now, actually do the timing! | 337 // Now, actually do the timing! |
| 344 for (int i = 0; i < FLAGS_samples; i++) { | 338 for (int i = 0; i < FLAGS_samples; i++) { |
| 345 samples[i] = time(loops, bench, canvas, target) / loops; | 339 samples[i] = time(loops, bench, target) / loops; |
| 346 } | 340 } |
| 347 | 341 |
| 348 return loops; | 342 return loops; |
| 349 } | 343 } |
| 350 | 344 |
| 351 static SkString to_lower(const char* str) { | 345 static SkString to_lower(const char* str) { |
| 352 SkString lower(str); | 346 SkString lower(str); |
| 353 for (size_t i = 0; i < lower.size(); i++) { | 347 for (size_t i = 0; i < lower.size(); i++) { |
| 354 lower[i] = tolower(lower[i]); | 348 lower[i] = tolower(lower[i]); |
| 355 } | 349 } |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 | 826 |
| 833 SkTDArray<Target*> targets; | 827 SkTDArray<Target*> targets; |
| 834 create_targets(&targets, bench.get(), configs); | 828 create_targets(&targets, bench.get(), configs); |
| 835 | 829 |
| 836 if (!targets.isEmpty()) { | 830 if (!targets.isEmpty()) { |
| 837 log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSi
ze().fY); | 831 log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSi
ze().fY); |
| 838 bench->preDraw(); | 832 bench->preDraw(); |
| 839 } | 833 } |
| 840 for (int j = 0; j < targets.count(); j++) { | 834 for (int j = 0; j < targets.count(); j++) { |
| 841 // During HWUI output this canvas may be NULL. | 835 // During HWUI output this canvas may be NULL. |
| 842 SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->
getCanvas() : NULL; | 836 SkCanvas* canvas = targets[j]->getCanvas(); |
| 843 const char* config = targets[j]->config.name; | 837 const char* config = targets[j]->config.name; |
| 844 | 838 |
| 845 targets[j]->setup(); | 839 targets[j]->setup(); |
| 846 bench->perCanvasPreDraw(canvas); | 840 bench->perCanvasPreDraw(canvas); |
| 847 | 841 |
| 848 const int loops = | 842 const int loops = |
| 849 targets[j]->needsFrameTiming() | 843 targets[j]->needsFrameTiming() |
| 850 ? gpu_bench(targets[j], bench.get(), canvas, samples.get()) | 844 ? gpu_bench(targets[j], bench.get(), samples.get()) |
| 851 : cpu_bench(overhead, bench.get(), canvas, samples.get()); | 845 : cpu_bench(overhead, targets[j], bench.get(), samples.get()); |
| 852 | 846 |
| 853 bench->perCanvasPostDraw(canvas); | 847 bench->perCanvasPostDraw(canvas); |
| 854 | 848 |
| 855 if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &
& | 849 if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &
& |
| 856 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { | 850 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { |
| 857 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); | 851 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); |
| 858 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); | 852 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); |
| 859 pngFilename.append(".png"); | 853 pngFilename.append(".png"); |
| 860 write_canvas_png(targets[j], pngFilename); | 854 write_canvas_png(targets[j], pngFilename); |
| 861 } | 855 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 | 934 |
| 941 return 0; | 935 return 0; |
| 942 } | 936 } |
| 943 | 937 |
| 944 #if !defined SK_BUILD_FOR_IOS | 938 #if !defined SK_BUILD_FOR_IOS |
| 945 int main(int argc, char** argv) { | 939 int main(int argc, char** argv) { |
| 946 SkCommandLineFlags::Parse(argc, argv); | 940 SkCommandLineFlags::Parse(argc, argv); |
| 947 return nanobench_main(); | 941 return nanobench_main(); |
| 948 } | 942 } |
| 949 #endif | 943 #endif |
| OLD | NEW |