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 kPDF_Backend, 48 kHWUI_Backend, 49 }; 50 51 // Call to determine whether the benchmark is intended for 52 // the rendering mode. isSuitableFor(Backend backend)53 virtual bool isSuitableFor(Backend backend) { 54 return backend != kNonRendering_Backend; 55 } 56 57 // Allows a benchmark to override options used to construct the GrContext. modifyGrContextOptions(GrContextOptions *)58 virtual void modifyGrContextOptions(GrContextOptions*) {} 59 calculateLoops(int defaultLoops)60 virtual int calculateLoops(int defaultLoops) const { 61 return defaultLoops; 62 } 63 64 // Call before draw, allows the benchmark to do setup work outside of the 65 // timer. When a benchmark is repeatedly drawn, this should be called once 66 // before the initial draw. 67 void delayedSetup(); 68 69 // Called once before and after a series of draw calls to a single canvas. 70 // The setup/break down in these calls is not timed. 71 void perCanvasPreDraw(SkCanvas*); 72 void perCanvasPostDraw(SkCanvas*); 73 74 // Called just before and after each call to draw(). Not timed. 75 void preDraw(SkCanvas*); 76 void postDraw(SkCanvas*); 77 78 // Bench framework can tune loops to be large enough for stable timing. 79 void draw(int loops, SkCanvas*); 80 getGpuStats(SkCanvas *,SkTArray<SkString> * keys,SkTArray<double> * values)81 virtual void getGpuStats(SkCanvas*, SkTArray<SkString>* keys, SkTArray<double>* values) {} 82 83 // Replaces the GrRecordingContext's dmsaaStats() with a single frame of this benchmark. getDMSAAStats(GrRecordingContext *)84 virtual bool getDMSAAStats(GrRecordingContext*) { return false; } 85 86 // Count of units (pixels, whatever) being exercised, to scale timing by. getUnits()87 int getUnits() const { return fUnits; } 88 89 protected: setUnits(int units)90 void setUnits(int units) { SkASSERT(units > 0); fUnits = units; } 91 92 virtual void setupPaint(SkPaint* paint); 93 94 virtual const char* onGetName() = 0; onGetUniqueName()95 virtual const char* onGetUniqueName() { return this->onGetName(); } onDelayedSetup()96 virtual void onDelayedSetup() {} onPerCanvasPreDraw(SkCanvas *)97 virtual void onPerCanvasPreDraw(SkCanvas*) {} onPerCanvasPostDraw(SkCanvas *)98 virtual void onPerCanvasPostDraw(SkCanvas*) {} onPreDraw(SkCanvas *)99 virtual void onPreDraw(SkCanvas*) {} onPostDraw(SkCanvas *)100 virtual void onPostDraw(SkCanvas*) {} 101 // Each bench should do its main work in a loop like this: 102 // for (int i = 0; i < loops; i++) { <work here> } 103 virtual void onDraw(int loops, SkCanvas*) = 0; 104 105 virtual SkIPoint onGetSize(); 106 107 private: 108 int fUnits = 1; 109 110 using INHERITED = SkRefCnt; 111 }; 112 113 typedef sk_tools::Registry<Benchmark*(*)(void*)> BenchRegistry; 114 115 #endif 116