1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef Benchmark_DEFINED 9 #define Benchmark_DEFINED 10 11 #include "include/core/SkPoint.h" 12 #include "include/core/SkRefCnt.h" 13 #include "include/core/SkString.h" 14 #include "tools/Registry.h" 15 16 #define DEF_BENCH3(code, N) \ 17 static BenchRegistry gBench##N([](void*) -> Benchmark* { code; }); 18 #define DEF_BENCH2(code, N) DEF_BENCH3(code, N) 19 #define DEF_BENCH(code) DEF_BENCH2(code, __COUNTER__) 20 21 /* 22 * With the above macros, you can register benches as follows (at the bottom 23 * of your .cpp) 24 * 25 * DEF_BENCH(return new MyBenchmark(...)) 26 * DEF_BENCH(return new MyBenchmark(...)) 27 * DEF_BENCH(return new MyBenchmark(...)) 28 */ 29 30 struct GrContextOptions; 31 class GrRecordingContext; 32 class SkCanvas; 33 class SkPaint; 34 35 class Benchmark : public SkRefCnt { 36 public: 37 Benchmark(); 38 39 const char* getName(); 40 const char* getUniqueName(); 41 SkIPoint getSize(); 42 43 enum Backend { 44 kNonRendering_Backend, 45 kRaster_Backend, 46 kGPU_Backend, 47 kGraphite_Backend, 48 kPDF_Backend, 49 kHWUI_Backend, 50 }; 51 52 // Call to determine whether the benchmark is intended for 53 // the rendering mode. isSuitableFor(Backend backend)54 virtual bool isSuitableFor(Backend backend) { 55 return backend != kNonRendering_Backend; 56 } 57 58 // Allows a benchmark to override options used to construct the GrContext. modifyGrContextOptions(GrContextOptions *)59 virtual void modifyGrContextOptions(GrContextOptions*) {} 60 calculateLoops(int defaultLoops)61 virtual int calculateLoops(int defaultLoops) const { 62 return defaultLoops; 63 } 64 65 // Call before draw, allows the benchmark to do setup work outside of the 66 // timer. When a benchmark is repeatedly drawn, this should be called once 67 // before the initial draw. 68 void delayedSetup(); 69 70 // Called once before and after a series of draw calls to a single canvas. 71 // The setup/break down in these calls is not timed. 72 void perCanvasPreDraw(SkCanvas*); 73 void perCanvasPostDraw(SkCanvas*); 74 75 // Called just before and after each call to draw(). Not timed. 76 void preDraw(SkCanvas*); 77 void postDraw(SkCanvas*); 78 79 // Bench framework can tune loops to be large enough for stable timing. 80 void draw(int loops, SkCanvas*); 81 getGpuStats(SkCanvas *,SkTArray<SkString> * keys,SkTArray<double> * values)82 virtual void getGpuStats(SkCanvas*, SkTArray<SkString>* keys, SkTArray<double>* values) {} 83 84 // Replaces the GrRecordingContext's dmsaaStats() with a single frame of this benchmark. getDMSAAStats(GrRecordingContext *)85 virtual bool getDMSAAStats(GrRecordingContext*) { return false; } 86 87 // Count of units (pixels, whatever) being exercised, to scale timing by. getUnits()88 int getUnits() const { return fUnits; } 89 90 protected: setUnits(int units)91 void setUnits(int units) { SkASSERT(units > 0); fUnits = units; } 92 93 virtual void setupPaint(SkPaint* paint); 94 95 virtual const char* onGetName() = 0; onGetUniqueName()96 virtual const char* onGetUniqueName() { return this->onGetName(); } onDelayedSetup()97 virtual void onDelayedSetup() {} onPerCanvasPreDraw(SkCanvas *)98 virtual void onPerCanvasPreDraw(SkCanvas*) {} onPerCanvasPostDraw(SkCanvas *)99 virtual void onPerCanvasPostDraw(SkCanvas*) {} onPreDraw(SkCanvas *)100 virtual void onPreDraw(SkCanvas*) {} onPostDraw(SkCanvas *)101 virtual void onPostDraw(SkCanvas*) {} 102 // Each bench should do its main work in a loop like this: 103 // for (int i = 0; i < loops; i++) { <work here> } 104 virtual void onDraw(int loops, SkCanvas*) = 0; 105 106 virtual SkIPoint onGetSize(); 107 108 private: 109 int fUnits = 1; 110 111 using INHERITED = SkRefCnt; 112 }; 113 114 typedef sk_tools::Registry<Benchmark*(*)(void*)> BenchRegistry; 115 116 #endif 117