diff options
Diffstat (limited to 'bench/nanobench.cpp')
-rw-r--r-- | bench/nanobench.cpp | 232 |
1 files changed, 135 insertions, 97 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index 5e059328ad..4bc1484da0 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -7,6 +7,8 @@ #include <ctype.h> +#include "nanobench.h" + #include "Benchmark.h" #include "CrashHandler.h" #include "DecodingBench.h" @@ -32,6 +34,10 @@ #include "SkSurface.h" #include "SkTaskGroup.h" +#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK + #include "nanobenchAndroid.h" +#endif + #if SK_SUPPORT_GPU #include "gl/GrGLDefines.h" #include "GrContextFactory.h" @@ -86,24 +92,100 @@ static SkString humanize(double ms) { } #define HUMANIZE(ms) humanize(ms).c_str() -static double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContext* gl) { +bool Target::init(SkImageInfo info, Benchmark* bench) { + if (Benchmark::kRaster_Backend == config.backend) { + this->surface.reset(SkSurface::NewRaster(info)); + if (!this->surface.get()) { + return false; + } + } + return true; +} +bool Target::capturePixels(SkBitmap* bmp) { + if (!this->surface.get()) { + return false; + } + SkCanvas* canvas = this->surface->getCanvas(); + if (!canvas) { + return false; + } + bmp->setInfo(canvas->imageInfo()); + if (!canvas->readPixels(bmp, 0, 0)) { + SkDebugf("Can't read canvas pixels.\n"); + return false; + } + return true; +} + +#if SK_SUPPORT_GPU +struct GPUTarget : public Target { + explicit GPUTarget(const Config& c) : Target(c), gl(NULL) { } + SkGLContext* gl; + + void setup() override { + this->gl->makeCurrent(); + // Make sure we're done with whatever came before. + SK_GL(*this->gl, Finish()); + } + void endTiming() override { + if (this->gl) { + SK_GL(*this->gl, Flush()); + this->gl->swapBuffers(); + } + } + void fence() override { + SK_GL(*this->gl, Finish()); + } + + bool needsFrameTiming() const override { return true; } + bool init(SkImageInfo info, Benchmark* bench) override { + uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0; + SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); + this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->config.ctxType), + SkSurface::kNo_Budgeted, info, + this->config.samples, &props)); + this->gl = gGrFactory->getGLContext(this->config.ctxType); + if (!this->surface.get()) { + return false; + } + return true; + } + void fillOptions(ResultsWriter* log) override { + const GrGLubyte* version; + SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION)); + log->configOption("GL_VERSION", (const char*)(version)); + + SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER)); + log->configOption("GL_RENDERER", (const char*) version); + + SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR)); + log->configOption("GL_VENDOR", (const char*) version); + + SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); + log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); + } +}; + +#endif + +static double time(int loops, Benchmark* bench, SkCanvas* canvas, Target* target) { if (canvas) { canvas->clear(SK_ColorWHITE); } WallTimer timer; timer.start(); + if (target) { + canvas = target->beginTiming(canvas); + } if (bench) { bench->draw(loops, canvas); } if (canvas) { canvas->flush(); } -#if SK_SUPPORT_GPU - if (gl) { - SK_GL(*gl, Flush()); - gl->swapBuffers(); + if (target) { + target->endTiming(); } -#endif timer.end(); return timer.fWall; } @@ -137,19 +219,22 @@ static int clamp_loops(int loops) { return loops; } -static bool write_canvas_png(SkCanvas* canvas, const SkString& filename) { +static bool write_canvas_png(Target* target, const SkString& filename) { + if (filename.isEmpty()) { return false; } - if (kUnknown_SkColorType == canvas->imageInfo().colorType()) { + if (target->surface.get() && target->surface->getCanvas() && + kUnknown_SkColorType == target->surface->getCanvas()->imageInfo().colorType()) { return false; } + SkBitmap bmp; - bmp.setInfo(canvas->imageInfo()); - if (!canvas->readPixels(&bmp, 0, 0)) { - SkDebugf("Can't read canvas pixels.\n"); + + if (!target->capturePixels(&bmp)) { return false; } + SkString dir = SkOSPath::Dirname(filename.c_str()); if (!sk_mkdir(dir.c_str())) { SkDebugf("Can't make dir %s.\n", dir.c_str()); @@ -215,14 +300,7 @@ static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, return loops; } -#if SK_SUPPORT_GPU -static void setup_gl(SkGLContext* gl) { - gl->makeCurrent(); - // Make sure we're done with whatever came before. - SK_GL(*gl, Finish()); -} - -static int gpu_bench(SkGLContext* gl, +static int gpu_bench(Target* target, Benchmark* bench, SkCanvas* canvas, double* samples) { @@ -242,7 +320,7 @@ static int gpu_bench(SkGLContext* gl, // _this_ round, not still timing last round. We force this by looping // more times than any reasonable GPU will allow frames to lag. for (int i = 0; i < FLAGS_gpuFrameLag; i++) { - elapsed = time(loops, bench, canvas, gl); + elapsed = time(loops, bench, canvas, target); } } while (elapsed < FLAGS_gpuMs); @@ -250,8 +328,8 @@ static int gpu_bench(SkGLContext* gl, loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); loops = clamp_loops(loops); - // Might as well make sure we're not still timing our calibration. - SK_GL(*gl, Finish()); + // Make sure we're not still timing our calibration. + target->fence(); } else { loops = detect_forever_loops(loops); } @@ -259,16 +337,16 @@ static int gpu_bench(SkGLContext* gl, // Pretty much the same deal as the calibration: do some warmup to make // sure we're timing steady-state pipelined frames. for (int i = 0; i < FLAGS_gpuFrameLag; i++) { - time(loops, bench, canvas, gl); + time(loops, bench, canvas, target); } // Now, actually do the timing! for (int i = 0; i < FLAGS_samples; i++) { - samples[i] = time(loops, bench, canvas, gl) / loops; + samples[i] = time(loops, bench, canvas, target) / loops; } + return loops; } -#endif static SkString to_lower(const char* str) { SkString lower(str); @@ -278,30 +356,6 @@ static SkString to_lower(const char* str) { return lower; } -struct Config { - const char* name; - Benchmark::Backend backend; - SkColorType color; - SkAlphaType alpha; - int samples; -#if SK_SUPPORT_GPU - GrContextFactory::GLContextType ctxType; - bool useDFText; -#else - int bogusInt; - bool bogusBool; -#endif -}; - -struct Target { - explicit Target(const Config& c) : config(c) {} - const Config config; - SkAutoTDelete<SkSurface> surface; -#if SK_SUPPORT_GPU - SkGLContext* gl; -#endif -}; - static bool is_cpu_config_allowed(const char* name) { for (int i = 0; i < FLAGS_config.count(); i++) { if (to_lower(FLAGS_config[i]).equals(name)) { @@ -373,6 +427,14 @@ static void create_configs(SkTDArray<Config>* configs) { #endif } #endif + +#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK + if (is_cpu_config_allowed("hwui")) { + Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorType, + kPremul_SkAlphaType, 0, kBogusGLContextType, false }; + configs->push(config); + } +#endif } // If bench is enabled for config, returns a Target* for it, otherwise NULL. @@ -384,23 +446,25 @@ static Target* is_enabled(Benchmark* bench, const Config& config) { SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY, config.color, config.alpha); - Target* target = new Target(config); + Target* target = NULL; - if (Benchmark::kRaster_Backend == config.backend) { - target->surface.reset(SkSurface::NewRaster(info)); - } + switch (config.backend) { #if SK_SUPPORT_GPU - else if (Benchmark::kGPU_Backend == config.backend) { - uint32_t flags = config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0; - SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); - target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType), - SkSurface::kNo_Budgeted, info, - config.samples, &props)); - target->gl = gGrFactory->getGLContext(config.ctxType); - } + case Benchmark::kGPU_Backend: + target = new GPUTarget(config); + break; +#endif +#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK + case Benchmark::kHWUI_Backend: + target = new HWUITarget(config, bench); + break; #endif + default: + target = new Target(config); + break; + } - if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) { + if (!target->init(info, bench)) { delete target; return NULL; } @@ -418,22 +482,6 @@ static void create_targets(SkTDArray<Target*>* targets, Benchmark* b, } } -#if SK_SUPPORT_GPU -static void fill_gpu_options(ResultsWriter* log, SkGLContext* ctx) { - const GrGLubyte* version; - SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION)); - log->configOption("GL_VERSION", (const char*)(version)); - - SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER)); - log->configOption("GL_RENDERER", (const char*) version); - - SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR)); - log->configOption("GL_VENDOR", (const char*) version); - - SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); - log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version); -} -#endif class BenchmarkStream { public: @@ -790,32 +838,26 @@ int nanobench_main() { bench->preDraw(); } for (int j = 0; j < targets.count(); j++) { + // During HWUI output this canvas may be NULL. SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL; const char* config = targets[j]->config.name; -#if SK_SUPPORT_GPU - if (Benchmark::kGPU_Backend == targets[j]->config.backend) { - setup_gl(targets[j]->gl); - } -#endif - + targets[j]->setup(); bench->perCanvasPreDraw(canvas); const int loops = -#if SK_SUPPORT_GPU - Benchmark::kGPU_Backend == targets[j]->config.backend - ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get()) - : -#endif - cpu_bench( overhead, bench.get(), canvas, samples.get()); + targets[j]->needsFrameTiming() + ? gpu_bench(targets[j], bench.get(), canvas, samples.get()) + : cpu_bench(overhead, bench.get(), canvas, samples.get()); bench->perCanvasPostDraw(canvas); - if (canvas && !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { + if (Benchmark::kNonRendering_Backend != targets[j]->config.backend && + !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config); pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName()); pngFilename.append(".png"); - write_canvas_png(canvas, pngFilename); + write_canvas_png(targets[j], pngFilename); } if (kFailedLoops == loops) { @@ -827,11 +869,7 @@ int nanobench_main() { log->config(config); log->configOption("name", bench->getName()); benchStream.fillCurrentOptions(log.get()); -#if SK_SUPPORT_GPU - if (Benchmark::kGPU_Backend == targets[j]->config.backend) { - fill_gpu_options(log.get(), targets[j]->gl); - } -#endif + targets[j]->fillOptions(log.get()); log->metric("min_ms", stats.min); if (runs++ % FLAGS_flushEvery == 0) { log->flush(); |