xref: /aosp_15_r20/external/skia/bench/Benchmark.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/SkRefCnt.h"
12 #include "include/core/SkSize.h"
13 #include "include/core/SkString.h"
14 #include "include/private/base/SkTArray.h"
15 #include "tools/Registry.h"
16 
17 #if defined(SK_GRAPHITE)
18 #include "include/gpu/graphite/Context.h"
19 #endif
20 
21 #define DEF_BENCH3(code, N) \
22     static BenchRegistry gBench##N([](void*) -> Benchmark* { code; });
23 #define DEF_BENCH2(code, N) DEF_BENCH3(code, N)
24 #define DEF_BENCH(code) DEF_BENCH2(code, __COUNTER__)
25 
26 /*
27  *  With the above macros, you can register benches as follows (at the bottom
28  *  of your .cpp)
29  *
30  *  DEF_BENCH(return new MyBenchmark(...))
31  *  DEF_BENCH(return new MyBenchmark(...))
32  *  DEF_BENCH(return new MyBenchmark(...))
33  */
34 
35 struct GrContextOptions;
36 class GrRecordingContext;
37 class SkCanvas;
38 class SkPaint;
39 
40 class Benchmark : public SkRefCnt {
41 public:
42     Benchmark();
43 
44     const char* getName();
45     const char* getUniqueName();
46     SkISize getSize();
47 
48     enum class Backend {
49         kNonRendering,
50         kRaster,
51         kGanesh,
52         kGraphite,
53         kPDF,
54         kHWUI,
55     };
56 
57     // Call to determine whether the benchmark is intended for
58     // the rendering mode.
isSuitableFor(Backend backend)59     virtual bool isSuitableFor(Backend backend) {
60         return backend != Backend::kNonRendering;
61     }
62 
63     // Allows a benchmark to override options used to construct the GrContext.
modifyGrContextOptions(GrContextOptions *)64     virtual void modifyGrContextOptions(GrContextOptions*) {}
65 
66 #if defined(SK_GRAPHITE)
modifyGraphiteContextOptions(skgpu::graphite::ContextOptions *)67     virtual void modifyGraphiteContextOptions(skgpu::graphite::ContextOptions*) {}
68 #endif
69 
70     // Whether or not this benchmark requires multiple samples to get a meaningful result.
shouldLoop()71     virtual bool shouldLoop() const {
72         return true;
73     }
74 
75     // Call before draw, allows the benchmark to do setup work outside of the
76     // timer. When a benchmark is repeatedly drawn, this should be called once
77     // before the initial draw.
78     void delayedSetup();
79 
80     // Called once before and after a series of draw calls to a single canvas.
81     // The setup/break down in these calls is not timed.
82     void perCanvasPreDraw(SkCanvas*);
83     void perCanvasPostDraw(SkCanvas*);
84 
85     // Called just before and after each call to draw().  Not timed.
86     void preDraw(SkCanvas*);
87     void postDraw(SkCanvas*);
88 
89     // Bench framework can tune loops to be large enough for stable timing.
90     void draw(int loops, SkCanvas*);
91 
getGpuStats(SkCanvas *,skia_private::TArray<SkString> * keys,skia_private::TArray<double> * values)92     virtual void getGpuStats(SkCanvas*,
93                              skia_private::TArray<SkString>* keys,
94                              skia_private::TArray<double>* values) {}
95 
96     // Replaces the GrRecordingContext's dmsaaStats() with a single frame of this benchmark.
getDMSAAStats(GrRecordingContext *)97     virtual bool getDMSAAStats(GrRecordingContext*) { return false; }
98 
99     // Count of units (pixels, whatever) being exercised, to scale timing by.
getUnits()100     int getUnits() const { return fUnits; }
101 
102 protected:
setUnits(int units)103     void setUnits(int units) { SkASSERT(units > 0); fUnits = units; }
104 
105     virtual void setupPaint(SkPaint* paint);
106 
107     virtual const char* onGetName() = 0;
onGetUniqueName()108     virtual const char* onGetUniqueName() { return this->onGetName(); }
onDelayedSetup()109     virtual void onDelayedSetup() {}
onPerCanvasPreDraw(SkCanvas *)110     virtual void onPerCanvasPreDraw(SkCanvas*) {}
onPerCanvasPostDraw(SkCanvas *)111     virtual void onPerCanvasPostDraw(SkCanvas*) {}
onPreDraw(SkCanvas *)112     virtual void onPreDraw(SkCanvas*) {}
onPostDraw(SkCanvas *)113     virtual void onPostDraw(SkCanvas*) {}
114     // Each bench should do its main work in a loop like this:
115     //   for (int i = 0; i < loops; i++) { <work here> }
116     virtual void onDraw(int loops, SkCanvas*) = 0;
117 
118     virtual SkISize onGetSize();
119 
120 private:
121     int fUnits = 1;
122 
123     using INHERITED = SkRefCnt;
124 };
125 
126 typedef sk_tools::Registry<Benchmark*(*)(void*)> BenchRegistry;
127 
128 #endif
129