| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef Benchmark_DEFINED | |
| #define Benchmark_DEFINED | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkSize.h" | |
| #include "include/core/SkString.h" | |
| #include "include/private/SkTArray.h" | |
| #include "tools/Registry.h" | |
| #if defined(SK_GRAPHITE) | |
| #include "include/gpu/graphite/Context.h" | |
| #endif | |
| #include <functional> | |
| #define DEF_BENCH3(code, N) \ | |
| static BenchRegistry gBench##N([](void*) -> Benchmark* { code; }); | |
| #define DEF_BENCH2(code, N) DEF_BENCH3(code, N) | |
| #define DEF_BENCH(code) DEF_BENCH2(code, __COUNTER__) | |
| /* | |
| * With the above macros, you can register benches as follows (at the bottom | |
| * of your .cpp) | |
| * | |
| * DEF_BENCH(return new MyBenchmark(...)) | |
| * DEF_BENCH(return new MyBenchmark(...)) | |
| * DEF_BENCH(return new MyBenchmark(...)) | |
| */ | |
| struct GrContextOptions; | |
| class GrRecordingContext; | |
| class SkCanvas; | |
| class SkPaint; | |
| class Benchmark : public SkRefCnt { | |
| public: | |
| Benchmark(); | |
| const char* getName(); | |
| const char* getUniqueName(); | |
| SkISize getSize(); | |
| enum class Backend { | |
| kNonRendering, | |
| kRaster, | |
| kGanesh, | |
| kGraphite, | |
| kPDF, | |
| kHWUI, | |
| }; | |
| // Call to determine whether the benchmark is intended for | |
| // the rendering mode. | |
| virtual bool isSuitableFor(Backend backend) { | |
| return backend != Backend::kNonRendering; | |
| } | |
| // Allows a benchmark to override options used to construct the GrContext. | |
| virtual void modifyGrContextOptions(GrContextOptions*) {} | |
| #if defined(SK_GRAPHITE) | |
| virtual void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions*) {} | |
| #endif | |
| // Whether or not this benchmark requires multiple samples to get a meaningful result. | |
| virtual bool shouldLoop() const { | |
| return true; | |
| } | |
| // Call before draw, allows the benchmark to do setup work outside of the | |
| // timer. When a benchmark is repeatedly drawn, this should be called once | |
| // before the initial draw. | |
| void delayedSetup(); | |
| // Called once before and after a series of draw calls to a single canvas. | |
| // The setup/break down in these calls is not timed. | |
| void perCanvasPreDraw(SkCanvas*); | |
| void perCanvasPostDraw(SkCanvas*); | |
| // Called just before and after each call to draw(). Not timed. | |
| void preDraw(SkCanvas*); | |
| void postDraw(SkCanvas*); | |
| // Bench framework can tune loops to be large enough for stable timing. | |
| void draw(int loops, SkCanvas*, std::function<void()> submitFrame = nullptr); | |
| virtual void getGpuStats(SkCanvas*, | |
| skia_private::TArray<SkString>* keys, | |
| skia_private::TArray<double>* values) {} | |
| // Replaces the GrRecordingContext's dmsaaStats() with a single frame of this benchmark. | |
| virtual bool getDMSAAStats(GrRecordingContext*) { return false; } | |
| // Count of units (pixels, whatever) being exercised, to scale timing by. | |
| int getUnits() const { return fUnits; } | |
| protected: | |
| void setUnits(int units) { SkASSERT(units > 0); fUnits = units; } | |
| virtual void setupPaint(SkPaint* paint); | |
| virtual const char* onGetName() = 0; | |
| virtual const char* onGetUniqueName() { return this->onGetName(); } | |
| virtual void onDelayedSetup() {} | |
| virtual void onPerCanvasPreDraw(SkCanvas*) {} | |
| virtual void onPerCanvasPostDraw(SkCanvas*) {} | |
| virtual void onPreDraw(SkCanvas*) {} | |
| virtual void onPostDraw(SkCanvas*) {} | |
| // Each bench should do its main work in a loop like this: | |
| // for (int i = 0; i < loops; i++) { <work here> } | |
| virtual void onDraw(int loops, SkCanvas*) = 0; | |
| // Similar to onDraw except after each frame the Benchmark draws it should call the endFrame | |
| // callback (if valid). This is useful for Benchmarks like MSKP which inherently draw multiple | |
| // frames within one draw call. Benchmarks that want to use this should make sure to return | |
| // true from hasInternalFrames. | |
| virtual void onDrawFrame(int loops, SkCanvas*, std::function<void()> endFrame) {} | |
| virtual SkISize onGetSize(); | |
| private: | |
| // If the Benchmark has its own internal frames (e.g. MSKPs) this function should return true. | |
| // If it returns true then onDrawFrame will be called intstead of onDraw. | |
| virtual bool submitsInternalFrames() { return false; } | |
| int fUnits = 1; | |
| using INHERITED = SkRefCnt; | |
| }; | |
| typedef sk_tools::Registry<Benchmark*(*)(void*)> BenchRegistry; | |
| #endif |