1
2 /*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 #include "SkBenchmark.h"
9 #include "SkFloatBits.h"
10 #include "SkRandom.h"
11 #include "SkRect.h"
12 #include "SkString.h"
13
14 class ScalarBench : public SkBenchmark {
15 SkString fName;
16 public:
ScalarBench(const char name[])17 ScalarBench(const char name[]) {
18 fName.printf("scalar_%s", name);
19 }
20
isSuitableFor(Backend backend)21 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
22 return backend == kNonRendering_Backend;
23 }
24
25 virtual void performTest() = 0;
26
27 protected:
mulLoopCount() const28 virtual int mulLoopCount() const { return 1; }
29
onGetName()30 virtual const char* onGetName() SK_OVERRIDE {
31 return fName.c_str();
32 }
33
onDraw(const int loops,SkCanvas * canvas)34 virtual void onDraw(const int loops, SkCanvas* canvas) {
35 for (int i = 0; i < loops; i++) {
36 this->performTest();
37 }
38 }
39
40 private:
41 typedef SkBenchmark INHERITED;
42 };
43
44 // we want to stop the compiler from eliminating code that it thinks is a no-op
45 // so we have a non-static global we increment, hoping that will convince the
46 // compiler to execute everything
47 int gScalarBench_NonStaticGlobal;
48
49 #define always_do(pred) \
50 do { \
51 if (pred) { \
52 ++gScalarBench_NonStaticGlobal; \
53 } \
54 } while (0)
55
56 // having unknown values in our arrays can throw off the timing a lot, perhaps
57 // handling NaN values is a lot slower. Anyway, this guy is just meant to put
58 // reasonable values in our arrays.
init9(T array[9])59 template <typename T> void init9(T array[9]) {
60 SkRandom rand;
61 for (int i = 0; i < 9; i++) {
62 array[i] = rand.nextSScalar1();
63 }
64 }
65
66 class FloatComparisonBench : public ScalarBench {
67 public:
FloatComparisonBench()68 FloatComparisonBench() : INHERITED("compare_float") {
69 init9(fArray);
70 }
71 protected:
mulLoopCount() const72 virtual int mulLoopCount() const { return 4; }
performTest()73 virtual void performTest() {
74 always_do(fArray[6] != 0.0f || fArray[7] != 0.0f || fArray[8] != 1.0f);
75 always_do(fArray[2] != 0.0f || fArray[5] != 0.0f);
76 }
77 private:
78 float fArray[9];
79 typedef ScalarBench INHERITED;
80 };
81
82 class ForcedIntComparisonBench : public ScalarBench {
83 public:
ForcedIntComparisonBench()84 ForcedIntComparisonBench()
85 : INHERITED("compare_forced_int") {
86 init9(fArray);
87 }
88 protected:
mulLoopCount() const89 virtual int mulLoopCount() const { return 4; }
performTest()90 virtual void performTest() {
91 always_do(SkScalarAs2sCompliment(fArray[6]) |
92 SkScalarAs2sCompliment(fArray[7]) |
93 (SkScalarAs2sCompliment(fArray[8]) - kPersp1Int));
94 always_do(SkScalarAs2sCompliment(fArray[2]) |
95 SkScalarAs2sCompliment(fArray[5]));
96 }
97 private:
98 static const int32_t kPersp1Int = 0x3f800000;
99 SkScalar fArray[9];
100 typedef ScalarBench INHERITED;
101 };
102
103 class IsFiniteScalarBench : public ScalarBench {
104 public:
IsFiniteScalarBench()105 IsFiniteScalarBench() : INHERITED("isfinite") {
106 SkRandom rand;
107 for (size_t i = 0; i < ARRAY_N; ++i) {
108 fArray[i] = rand.nextSScalar1();
109 }
110 }
111 protected:
mulLoopCount() const112 virtual int mulLoopCount() const { return 1; }
performTest()113 virtual void performTest() SK_OVERRIDE {
114 int sum = 0;
115 for (size_t i = 0; i < ARRAY_N; ++i) {
116 // We pass -fArray[i], so the compiler can't cheat and treat the
117 // value as an int (even though we tell it that it is a float)
118 sum += SkScalarIsFinite(-fArray[i]);
119 }
120 // we do this so the compiler won't optimize our loop away...
121 this->doSomething(fArray, sum);
122 }
123
doSomething(SkScalar array[],int sum)124 virtual void doSomething(SkScalar array[], int sum) {}
125 private:
126 enum {
127 ARRAY_N = 64
128 };
129 SkScalar fArray[ARRAY_N];
130
131 typedef ScalarBench INHERITED;
132 };
133
134 ///////////////////////////////////////////////////////////////////////////////
135
136 class RectBoundsBench : public SkBenchmark {
137 enum {
138 PTS = 100,
139 };
140 SkPoint fPts[PTS];
141
142 public:
RectBoundsBench()143 RectBoundsBench() {
144 SkRandom rand;
145 for (int i = 0; i < PTS; ++i) {
146 fPts[i].fX = rand.nextSScalar1();
147 fPts[i].fY = rand.nextSScalar1();
148 }
149 }
150
isSuitableFor(Backend backend)151 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
152 return backend == kNonRendering_Backend;
153 }
154
155 protected:
onGetName()156 virtual const char* onGetName() SK_OVERRIDE {
157 return "rect_bounds";
158 }
159
onDraw(const int loops,SkCanvas * canvas)160 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
161 SkRect r;
162 for (int i = 0; i < loops; ++i) {
163 r.set(fPts, PTS);
164 }
165 }
166
167 private:
168 typedef SkBenchmark INHERITED;
169 };
170
171 ///////////////////////////////////////////////////////////////////////////////
172
173 DEF_BENCH( return new FloatComparisonBench(); )
174 DEF_BENCH( return new ForcedIntComparisonBench(); )
175 DEF_BENCH( return new RectBoundsBench(); )
176 DEF_BENCH( return new IsFiniteScalarBench(); )
177