| 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" |
| 11 |
| 10 #include "Benchmark.h" | 12 #include "Benchmark.h" |
| 11 #include "CrashHandler.h" | 13 #include "CrashHandler.h" |
| 12 #include "DecodingBench.h" | 14 #include "DecodingBench.h" |
| 13 #include "DecodingSubsetBench.h" | 15 #include "DecodingSubsetBench.h" |
| 14 #include "GMBench.h" | 16 #include "GMBench.h" |
| 15 #include "ProcStats.h" | 17 #include "ProcStats.h" |
| 16 #include "ResultsWriter.h" | 18 #include "ResultsWriter.h" |
| 17 #include "RecordingBench.h" | 19 #include "RecordingBench.h" |
| 18 #include "SKPBench.h" | 20 #include "SKPBench.h" |
| 19 #include "Stats.h" | 21 #include "Stats.h" |
| 20 #include "Timer.h" | 22 #include "Timer.h" |
| 21 | 23 |
| 22 #include "SkBBoxHierarchy.h" | 24 #include "SkBBoxHierarchy.h" |
| 23 #include "SkCanvas.h" | 25 #include "SkCanvas.h" |
| 24 #include "SkCommonFlags.h" | 26 #include "SkCommonFlags.h" |
| 25 #include "SkData.h" | 27 #include "SkData.h" |
| 26 #include "SkForceLinking.h" | 28 #include "SkForceLinking.h" |
| 27 #include "SkGraphics.h" | 29 #include "SkGraphics.h" |
| 28 #include "SkOSFile.h" | 30 #include "SkOSFile.h" |
| 29 #include "SkPictureRecorder.h" | 31 #include "SkPictureRecorder.h" |
| 30 #include "SkPictureUtils.h" | 32 #include "SkPictureUtils.h" |
| 31 #include "SkString.h" | 33 #include "SkString.h" |
| 32 #include "SkSurface.h" | 34 #include "SkSurface.h" |
| 33 #include "SkTaskGroup.h" | 35 #include "SkTaskGroup.h" |
| 34 | 36 |
| 37 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| 38 #include "nanobenchAndroid.h" |
| 39 #endif |
| 40 |
| 35 #if SK_SUPPORT_GPU | 41 #if SK_SUPPORT_GPU |
| 36 #include "gl/GrGLDefines.h" | 42 #include "gl/GrGLDefines.h" |
| 37 #include "GrContextFactory.h" | 43 #include "GrContextFactory.h" |
| 38 SkAutoTDelete<GrContextFactory> gGrFactory; | 44 SkAutoTDelete<GrContextFactory> gGrFactory; |
| 39 #endif | 45 #endif |
| 40 | 46 |
| 41 __SK_FORCE_IMAGE_DECODER_LINKING; | 47 __SK_FORCE_IMAGE_DECODER_LINKING; |
| 42 | 48 |
| 43 static const int kAutoTuneLoops = 0; | 49 static const int kAutoTuneLoops = 0; |
| 44 | 50 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 DEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run."); | 85 DEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run."); |
| 80 DEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test
."); | 86 DEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test
."); |
| 81 DEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?"); | 87 DEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?"); |
| 82 | 88 |
| 83 static SkString humanize(double ms) { | 89 static SkString humanize(double ms) { |
| 84 if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); | 90 if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); |
| 85 return HumanizeMs(ms); | 91 return HumanizeMs(ms); |
| 86 } | 92 } |
| 87 #define HUMANIZE(ms) humanize(ms).c_str() | 93 #define HUMANIZE(ms) humanize(ms).c_str() |
| 88 | 94 |
| 89 static double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContext* g
l) { | 95 bool Target::init(SkImageInfo info, Benchmark* bench) { |
| 96 if (Benchmark::kRaster_Backend == config.backend) { |
| 97 this->surface.reset(SkSurface::NewRaster(info)); |
| 98 if (!this->surface.get()) { |
| 99 return false; |
| 100 } |
| 101 } |
| 102 return true; |
| 103 } |
| 104 bool Target::capturePixels(SkBitmap* bmp) { |
| 105 if (!this->surface.get()) { |
| 106 return false; |
| 107 } |
| 108 SkCanvas* canvas = this->surface->getCanvas(); |
| 109 if (!canvas) { |
| 110 return false; |
| 111 } |
| 112 bmp->setInfo(canvas->imageInfo()); |
| 113 if (!canvas->readPixels(bmp, 0, 0)) { |
| 114 SkDebugf("Can't read canvas pixels.\n"); |
| 115 return false; |
| 116 } |
| 117 return true; |
| 118 } |
| 119 |
| 120 #if SK_SUPPORT_GPU |
| 121 struct GPUTarget : public Target { |
| 122 explicit GPUTarget(const Config& c) : Target(c), gl(NULL) { } |
| 123 SkGLContext* gl; |
| 124 |
| 125 void setup() override { |
| 126 this->gl->makeCurrent(); |
| 127 // Make sure we're done with whatever came before. |
| 128 SK_GL(*this->gl, Finish()); |
| 129 } |
| 130 void endTiming() override { |
| 131 if (this->gl) { |
| 132 SK_GL(*this->gl, Flush()); |
| 133 this->gl->swapBuffers(); |
| 134 } |
| 135 } |
| 136 void fence() override { |
| 137 SK_GL(*this->gl, Finish()); |
| 138 } |
| 139 |
| 140 bool needsFrameTiming() const override { return true; } |
| 141 bool init(SkImageInfo info, Benchmark* bench) override { |
| 142 uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDistanceFi
eldFonts_Flag : 0; |
| 143 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
| 144 this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->con
fig.ctxType), |
| 145 SkSurface::kNo_Budgeted
, info, |
| 146 this->config.samples, &
props)); |
| 147 this->gl = gGrFactory->getGLContext(this->config.ctxType); |
| 148 if (!this->surface.get()) { |
| 149 return false; |
| 150 } |
| 151 return true; |
| 152 } |
| 153 void fillOptions(ResultsWriter* log) override { |
| 154 const GrGLubyte* version; |
| 155 SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION)); |
| 156 log->configOption("GL_VERSION", (const char*)(version)); |
| 157 |
| 158 SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER)); |
| 159 log->configOption("GL_RENDERER", (const char*) version); |
| 160 |
| 161 SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR)); |
| 162 log->configOption("GL_VENDOR", (const char*) version); |
| 163 |
| 164 SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION))
; |
| 165 log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); |
| 166 } |
| 167 }; |
| 168 |
| 169 #endif |
| 170 |
| 171 static double time(int loops, Benchmark* bench, SkCanvas* canvas, Target* target
) { |
| 90 if (canvas) { | 172 if (canvas) { |
| 91 canvas->clear(SK_ColorWHITE); | 173 canvas->clear(SK_ColorWHITE); |
| 92 } | 174 } |
| 93 WallTimer timer; | 175 WallTimer timer; |
| 94 timer.start(); | 176 timer.start(); |
| 177 if (target) { |
| 178 canvas = target->beginTiming(canvas); |
| 179 } |
| 95 if (bench) { | 180 if (bench) { |
| 96 bench->draw(loops, canvas); | 181 bench->draw(loops, canvas); |
| 97 } | 182 } |
| 98 if (canvas) { | 183 if (canvas) { |
| 99 canvas->flush(); | 184 canvas->flush(); |
| 100 } | 185 } |
| 101 #if SK_SUPPORT_GPU | 186 if (target) { |
| 102 if (gl) { | 187 target->endTiming(); |
| 103 SK_GL(*gl, Flush()); | |
| 104 gl->swapBuffers(); | |
| 105 } | 188 } |
| 106 #endif | |
| 107 timer.end(); | 189 timer.end(); |
| 108 return timer.fWall; | 190 return timer.fWall; |
| 109 } | 191 } |
| 110 | 192 |
| 111 static double estimate_timer_overhead() { | 193 static double estimate_timer_overhead() { |
| 112 double overhead = 0; | 194 double overhead = 0; |
| 113 for (int i = 0; i < FLAGS_overheadLoops; i++) { | 195 for (int i = 0; i < FLAGS_overheadLoops; i++) { |
| 114 overhead += time(1, NULL, NULL, NULL); | 196 overhead += time(1, NULL, NULL, NULL); |
| 115 } | 197 } |
| 116 return overhead / FLAGS_overheadLoops; | 198 return overhead / FLAGS_overheadLoops; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 130 "There's probably something wrong with the bench.\n", loops); | 212 "There's probably something wrong with the bench.\n", loops); |
| 131 return 1; | 213 return 1; |
| 132 } | 214 } |
| 133 if (loops > FLAGS_maxLoops) { | 215 if (loops > FLAGS_maxLoops) { |
| 134 SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loo
ps, FLAGS_maxLoops); | 216 SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loo
ps, FLAGS_maxLoops); |
| 135 return FLAGS_maxLoops; | 217 return FLAGS_maxLoops; |
| 136 } | 218 } |
| 137 return loops; | 219 return loops; |
| 138 } | 220 } |
| 139 | 221 |
| 140 static bool write_canvas_png(SkCanvas* canvas, const SkString& filename) { | 222 static bool write_canvas_png(Target* target, const SkString& filename) { |
| 223 |
| 141 if (filename.isEmpty()) { | 224 if (filename.isEmpty()) { |
| 142 return false; | 225 return false; |
| 143 } | 226 } |
| 144 if (kUnknown_SkColorType == canvas->imageInfo().colorType()) { | 227 if (target->surface.get() && target->surface->getCanvas() && |
| 228 kUnknown_SkColorType == target->surface->getCanvas()->imageInfo().colorT
ype()) { |
| 145 return false; | 229 return false; |
| 146 } | 230 } |
| 231 |
| 147 SkBitmap bmp; | 232 SkBitmap bmp; |
| 148 bmp.setInfo(canvas->imageInfo()); | 233 |
| 149 if (!canvas->readPixels(&bmp, 0, 0)) { | 234 if (!target->capturePixels(&bmp)) { |
| 150 SkDebugf("Can't read canvas pixels.\n"); | |
| 151 return false; | 235 return false; |
| 152 } | 236 } |
| 237 |
| 153 SkString dir = SkOSPath::Dirname(filename.c_str()); | 238 SkString dir = SkOSPath::Dirname(filename.c_str()); |
| 154 if (!sk_mkdir(dir.c_str())) { | 239 if (!sk_mkdir(dir.c_str())) { |
| 155 SkDebugf("Can't make dir %s.\n", dir.c_str()); | 240 SkDebugf("Can't make dir %s.\n", dir.c_str()); |
| 156 return false; | 241 return false; |
| 157 } | 242 } |
| 158 SkFILEWStream stream(filename.c_str()); | 243 SkFILEWStream stream(filename.c_str()); |
| 159 if (!stream.isValid()) { | 244 if (!stream.isValid()) { |
| 160 SkDebugf("Can't write %s.\n", filename.c_str()); | 245 SkDebugf("Can't write %s.\n", filename.c_str()); |
| 161 return false; | 246 return false; |
| 162 } | 247 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 } else { | 293 } else { |
| 209 loops = detect_forever_loops(loops); | 294 loops = detect_forever_loops(loops); |
| 210 } | 295 } |
| 211 | 296 |
| 212 for (int i = 0; i < FLAGS_samples; i++) { | 297 for (int i = 0; i < FLAGS_samples; i++) { |
| 213 samples[i] = time(loops, bench, canvas, NULL) / loops; | 298 samples[i] = time(loops, bench, canvas, NULL) / loops; |
| 214 } | 299 } |
| 215 return loops; | 300 return loops; |
| 216 } | 301 } |
| 217 | 302 |
| 218 #if SK_SUPPORT_GPU | 303 static int gpu_bench(Target* target, |
| 219 static void setup_gl(SkGLContext* gl) { | |
| 220 gl->makeCurrent(); | |
| 221 // Make sure we're done with whatever came before. | |
| 222 SK_GL(*gl, Finish()); | |
| 223 } | |
| 224 | |
| 225 static int gpu_bench(SkGLContext* gl, | |
| 226 Benchmark* bench, | 304 Benchmark* bench, |
| 227 SkCanvas* canvas, | 305 SkCanvas* canvas, |
| 228 double* samples) { | 306 double* samples) { |
| 229 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. | 307 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. |
| 230 int loops = FLAGS_loops; | 308 int loops = FLAGS_loops; |
| 231 if (kAutoTuneLoops == loops) { | 309 if (kAutoTuneLoops == loops) { |
| 232 loops = 1; | 310 loops = 1; |
| 233 double elapsed = 0; | 311 double elapsed = 0; |
| 234 do { | 312 do { |
| 235 if (1<<30 == loops) { | 313 if (1<<30 == loops) { |
| 236 // We're about to wrap. Something's wrong with the bench. | 314 // We're about to wrap. Something's wrong with the bench. |
| 237 loops = 0; | 315 loops = 0; |
| 238 break; | 316 break; |
| 239 } | 317 } |
| 240 loops *= 2; | 318 loops *= 2; |
| 241 // If the GPU lets frames lag at all, we need to make sure we're tim
ing | 319 // If the GPU lets frames lag at all, we need to make sure we're tim
ing |
| 242 // _this_ round, not still timing last round. We force this by loop
ing | 320 // _this_ round, not still timing last round. We force this by loop
ing |
| 243 // more times than any reasonable GPU will allow frames to lag. | 321 // more times than any reasonable GPU will allow frames to lag. |
| 244 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 322 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { |
| 245 elapsed = time(loops, bench, canvas, gl); | 323 elapsed = time(loops, bench, canvas, target); |
| 246 } | 324 } |
| 247 } while (elapsed < FLAGS_gpuMs); | 325 } while (elapsed < FLAGS_gpuMs); |
| 248 | 326 |
| 249 // We've overshot at least a little. Scale back linearly. | 327 // We've overshot at least a little. Scale back linearly. |
| 250 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); | 328 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); |
| 251 loops = clamp_loops(loops); | 329 loops = clamp_loops(loops); |
| 252 | 330 |
| 253 // Might as well make sure we're not still timing our calibration. | 331 // Make sure we're not still timing our calibration. |
| 254 SK_GL(*gl, Finish()); | 332 target->fence(); |
| 255 } else { | 333 } else { |
| 256 loops = detect_forever_loops(loops); | 334 loops = detect_forever_loops(loops); |
| 257 } | 335 } |
| 258 | 336 |
| 259 // Pretty much the same deal as the calibration: do some warmup to make | 337 // Pretty much the same deal as the calibration: do some warmup to make |
| 260 // sure we're timing steady-state pipelined frames. | 338 // sure we're timing steady-state pipelined frames. |
| 261 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 339 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { |
| 262 time(loops, bench, canvas, gl); | 340 time(loops, bench, canvas, target); |
| 263 } | 341 } |
| 264 | 342 |
| 265 // Now, actually do the timing! | 343 // Now, actually do the timing! |
| 266 for (int i = 0; i < FLAGS_samples; i++) { | 344 for (int i = 0; i < FLAGS_samples; i++) { |
| 267 samples[i] = time(loops, bench, canvas, gl) / loops; | 345 samples[i] = time(loops, bench, canvas, target) / loops; |
| 268 } | 346 } |
| 347 |
| 269 return loops; | 348 return loops; |
| 270 } | 349 } |
| 271 #endif | |
| 272 | 350 |
| 273 static SkString to_lower(const char* str) { | 351 static SkString to_lower(const char* str) { |
| 274 SkString lower(str); | 352 SkString lower(str); |
| 275 for (size_t i = 0; i < lower.size(); i++) { | 353 for (size_t i = 0; i < lower.size(); i++) { |
| 276 lower[i] = tolower(lower[i]); | 354 lower[i] = tolower(lower[i]); |
| 277 } | 355 } |
| 278 return lower; | 356 return lower; |
| 279 } | 357 } |
| 280 | 358 |
| 281 struct Config { | |
| 282 const char* name; | |
| 283 Benchmark::Backend backend; | |
| 284 SkColorType color; | |
| 285 SkAlphaType alpha; | |
| 286 int samples; | |
| 287 #if SK_SUPPORT_GPU | |
| 288 GrContextFactory::GLContextType ctxType; | |
| 289 bool useDFText; | |
| 290 #else | |
| 291 int bogusInt; | |
| 292 bool bogusBool; | |
| 293 #endif | |
| 294 }; | |
| 295 | |
| 296 struct Target { | |
| 297 explicit Target(const Config& c) : config(c) {} | |
| 298 const Config config; | |
| 299 SkAutoTDelete<SkSurface> surface; | |
| 300 #if SK_SUPPORT_GPU | |
| 301 SkGLContext* gl; | |
| 302 #endif | |
| 303 }; | |
| 304 | |
| 305 static bool is_cpu_config_allowed(const char* name) { | 359 static bool is_cpu_config_allowed(const char* name) { |
| 306 for (int i = 0; i < FLAGS_config.count(); i++) { | 360 for (int i = 0; i < FLAGS_config.count(); i++) { |
| 307 if (to_lower(FLAGS_config[i]).equals(name)) { | 361 if (to_lower(FLAGS_config[i]).equals(name)) { |
| 308 return true; | 362 return true; |
| 309 } | 363 } |
| 310 } | 364 } |
| 311 return false; | 365 return false; |
| 312 } | 366 } |
| 313 | 367 |
| 314 #if SK_SUPPORT_GPU | 368 #if SK_SUPPORT_GPU |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false) | 420 GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false) |
| 367 GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false) | 421 GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false) |
| 368 GPU_CONFIG(gpudft, kNative_GLContextType, 0, true) | 422 GPU_CONFIG(gpudft, kNative_GLContextType, 0, true) |
| 369 GPU_CONFIG(debug, kDebug_GLContextType, 0, false) | 423 GPU_CONFIG(debug, kDebug_GLContextType, 0, false) |
| 370 GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false) | 424 GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false) |
| 371 #ifdef SK_ANGLE | 425 #ifdef SK_ANGLE |
| 372 GPU_CONFIG(angle, kANGLE_GLContextType, 0, false) | 426 GPU_CONFIG(angle, kANGLE_GLContextType, 0, false) |
| 373 #endif | 427 #endif |
| 374 } | 428 } |
| 375 #endif | 429 #endif |
| 430 |
| 431 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| 432 if (is_cpu_config_allowed("hwui")) { |
| 433 Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorTy
pe, |
| 434 kPremul_SkAlphaType, 0, kBogusGLContextType, false }; |
| 435 configs->push(config); |
| 436 } |
| 437 #endif |
| 376 } | 438 } |
| 377 | 439 |
| 378 // If bench is enabled for config, returns a Target* for it, otherwise NULL. | 440 // If bench is enabled for config, returns a Target* for it, otherwise NULL. |
| 379 static Target* is_enabled(Benchmark* bench, const Config& config) { | 441 static Target* is_enabled(Benchmark* bench, const Config& config) { |
| 380 if (!bench->isSuitableFor(config.backend)) { | 442 if (!bench->isSuitableFor(config.backend)) { |
| 381 return NULL; | 443 return NULL; |
| 382 } | 444 } |
| 383 | 445 |
| 384 SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().f
Y, | 446 SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().f
Y, |
| 385 config.color, config.alpha); | 447 config.color, config.alpha); |
| 386 | 448 |
| 387 Target* target = new Target(config); | 449 Target* target = NULL; |
| 388 | 450 |
| 389 if (Benchmark::kRaster_Backend == config.backend) { | 451 switch (config.backend) { |
| 390 target->surface.reset(SkSurface::NewRaster(info)); | 452 #if SK_SUPPORT_GPU |
| 453 case Benchmark::kGPU_Backend: |
| 454 target = new GPUTarget(config); |
| 455 break; |
| 456 #endif |
| 457 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| 458 case Benchmark::kHWUI_Backend: |
| 459 target = new HWUITarget(config, bench); |
| 460 break; |
| 461 #endif |
| 462 default: |
| 463 target = new Target(config); |
| 464 break; |
| 391 } | 465 } |
| 392 #if SK_SUPPORT_GPU | |
| 393 else if (Benchmark::kGPU_Backend == config.backend) { | |
| 394 uint32_t flags = config.useDFText ? SkSurfaceProps::kUseDistanceFieldFon
ts_Flag : 0; | |
| 395 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | |
| 396 target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.
ctxType), | |
| 397 SkSurface::kNo_Budgeted
, info, | |
| 398 config.samples, &props)
); | |
| 399 target->gl = gGrFactory->getGLContext(config.ctxType); | |
| 400 } | |
| 401 #endif | |
| 402 | 466 |
| 403 if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.g
et()) { | 467 if (!target->init(info, bench)) { |
| 404 delete target; | 468 delete target; |
| 405 return NULL; | 469 return NULL; |
| 406 } | 470 } |
| 407 return target; | 471 return target; |
| 408 } | 472 } |
| 409 | 473 |
| 410 // Creates targets for a benchmark and a set of configs. | 474 // Creates targets for a benchmark and a set of configs. |
| 411 static void create_targets(SkTDArray<Target*>* targets, Benchmark* b, | 475 static void create_targets(SkTDArray<Target*>* targets, Benchmark* b, |
| 412 const SkTDArray<Config>& configs) { | 476 const SkTDArray<Config>& configs) { |
| 413 for (int i = 0; i < configs.count(); ++i) { | 477 for (int i = 0; i < configs.count(); ++i) { |
| 414 if (Target* t = is_enabled(b, configs[i])) { | 478 if (Target* t = is_enabled(b, configs[i])) { |
| 415 targets->push(t); | 479 targets->push(t); |
| 416 } | 480 } |
| 417 | 481 |
| 418 } | 482 } |
| 419 } | 483 } |
| 420 | 484 |
| 421 #if SK_SUPPORT_GPU | |
| 422 static void fill_gpu_options(ResultsWriter* log, SkGLContext* ctx) { | |
| 423 const GrGLubyte* version; | |
| 424 SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION)); | |
| 425 log->configOption("GL_VERSION", (const char*)(version)); | |
| 426 | |
| 427 SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER)); | |
| 428 log->configOption("GL_RENDERER", (const char*) version); | |
| 429 | |
| 430 SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR)); | |
| 431 log->configOption("GL_VENDOR", (const char*) version); | |
| 432 | |
| 433 SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); | |
| 434 log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); | |
| 435 } | |
| 436 #endif | |
| 437 | 485 |
| 438 class BenchmarkStream { | 486 class BenchmarkStream { |
| 439 public: | 487 public: |
| 440 BenchmarkStream() : fBenches(BenchRegistry::Head()) | 488 BenchmarkStream() : fBenches(BenchRegistry::Head()) |
| 441 , fGMs(skiagm::GMRegistry::Head()) | 489 , fGMs(skiagm::GMRegistry::Head()) |
| 442 , fCurrentRecording(0) | 490 , fCurrentRecording(0) |
| 443 , fCurrentScale(0) | 491 , fCurrentScale(0) |
| 444 , fCurrentSKP(0) | 492 , fCurrentSKP(0) |
| 445 , fCurrentUseMPD(0) | 493 , fCurrentUseMPD(0) |
| 446 , fCurrentImage(0) | 494 , fCurrentImage(0) |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 } | 831 } |
| 784 | 832 |
| 785 SkTDArray<Target*> targets; | 833 SkTDArray<Target*> targets; |
| 786 create_targets(&targets, bench.get(), configs); | 834 create_targets(&targets, bench.get(), configs); |
| 787 | 835 |
| 788 if (!targets.isEmpty()) { | 836 if (!targets.isEmpty()) { |
| 789 log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSi
ze().fY); | 837 log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSi
ze().fY); |
| 790 bench->preDraw(); | 838 bench->preDraw(); |
| 791 } | 839 } |
| 792 for (int j = 0; j < targets.count(); j++) { | 840 for (int j = 0; j < targets.count(); j++) { |
| 841 // During HWUI output this canvas may be NULL. |
| 793 SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->
getCanvas() : NULL; | 842 SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->
getCanvas() : NULL; |
| 794 const char* config = targets[j]->config.name; | 843 const char* config = targets[j]->config.name; |
| 795 | 844 |
| 796 #if SK_SUPPORT_GPU | 845 targets[j]->setup(); |
| 797 if (Benchmark::kGPU_Backend == targets[j]->config.backend) { | |
| 798 setup_gl(targets[j]->gl); | |
| 799 } | |
| 800 #endif | |
| 801 | |
| 802 bench->perCanvasPreDraw(canvas); | 846 bench->perCanvasPreDraw(canvas); |
| 803 | 847 |
| 804 const int loops = | 848 const int loops = |
| 805 #if SK_SUPPORT_GPU | 849 targets[j]->needsFrameTiming() |
| 806 Benchmark::kGPU_Backend == targets[j]->config.backend | 850 ? gpu_bench(targets[j], bench.get(), canvas, samples.get()) |
| 807 ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get()) | 851 : cpu_bench(overhead, bench.get(), canvas, samples.get()); |
| 808 : | |
| 809 #endif | |
| 810 cpu_bench( overhead, bench.get(), canvas, samples.get()); | |
| 811 | 852 |
| 812 bench->perCanvasPostDraw(canvas); | 853 bench->perCanvasPostDraw(canvas); |
| 813 | 854 |
| 814 if (canvas && !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { | 855 if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &
& |
| 856 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { |
| 815 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); | 857 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); |
| 816 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); | 858 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); |
| 817 pngFilename.append(".png"); | 859 pngFilename.append(".png"); |
| 818 write_canvas_png(canvas, pngFilename); | 860 write_canvas_png(targets[j], pngFilename); |
| 819 } | 861 } |
| 820 | 862 |
| 821 if (kFailedLoops == loops) { | 863 if (kFailedLoops == loops) { |
| 822 // Can't be timed. A warning note has already been printed. | 864 // Can't be timed. A warning note has already been printed. |
| 823 continue; | 865 continue; |
| 824 } | 866 } |
| 825 | 867 |
| 826 Stats stats(samples.get(), FLAGS_samples); | 868 Stats stats(samples.get(), FLAGS_samples); |
| 827 log->config(config); | 869 log->config(config); |
| 828 log->configOption("name", bench->getName()); | 870 log->configOption("name", bench->getName()); |
| 829 benchStream.fillCurrentOptions(log.get()); | 871 benchStream.fillCurrentOptions(log.get()); |
| 830 #if SK_SUPPORT_GPU | 872 targets[j]->fillOptions(log.get()); |
| 831 if (Benchmark::kGPU_Backend == targets[j]->config.backend) { | |
| 832 fill_gpu_options(log.get(), targets[j]->gl); | |
| 833 } | |
| 834 #endif | |
| 835 log->metric("min_ms", stats.min); | 873 log->metric("min_ms", stats.min); |
| 836 if (runs++ % FLAGS_flushEvery == 0) { | 874 if (runs++ % FLAGS_flushEvery == 0) { |
| 837 log->flush(); | 875 log->flush(); |
| 838 } | 876 } |
| 839 | 877 |
| 840 if (kAutoTuneLoops != FLAGS_loops) { | 878 if (kAutoTuneLoops != FLAGS_loops) { |
| 841 if (targets.count() == 1) { | 879 if (targets.count() == 1) { |
| 842 config = ""; // Only print the config if we run the same ben
ch on more than one. | 880 config = ""; // Only print the config if we run the same ben
ch on more than one. |
| 843 } | 881 } |
| 844 SkDebugf("%4dM\t%s\t%s\n" | 882 SkDebugf("%4dM\t%s\t%s\n" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 | 934 |
| 897 return 0; | 935 return 0; |
| 898 } | 936 } |
| 899 | 937 |
| 900 #if !defined SK_BUILD_FOR_IOS | 938 #if !defined SK_BUILD_FOR_IOS |
| 901 int main(int argc, char** argv) { | 939 int main(int argc, char** argv) { |
| 902 SkCommandLineFlags::Parse(argc, argv); | 940 SkCommandLineFlags::Parse(argc, argv); |
| 903 return nanobench_main(); | 941 return nanobench_main(); |
| 904 } | 942 } |
| 905 #endif | 943 #endif |
| OLD | NEW |