blob: 5726f38ede7a441d762b6e7df1f6b904482eb4a6 [file] [log] [blame]
reed@google.comddc518b2011-08-29 17:49:23 +00001#include "SkBenchmark.h"
reed@google.come05cc8e2011-10-10 14:19:40 +00002#include "SkColorPriv.h"
reed@google.comddc518b2011-08-29 17:49:23 +00003#include "SkMatrix.h"
4#include "SkRandom.h"
5#include "SkString.h"
6
7class MathBench : public SkBenchmark {
8 enum {
9 kBuffer = 100,
10 kLoop = 10000
11 };
12 SkString fName;
13 float fSrc[kBuffer], fDst[kBuffer];
14public:
15 MathBench(void* param, const char name[]) : INHERITED(param) {
16 fName.printf("math_%s", name);
17
18 SkRandom rand;
19 for (int i = 0; i < kBuffer; ++i) {
20 fSrc[i] = rand.nextSScalar1();
21 }
22 }
23
24 virtual void performTest(float dst[], const float src[], int count) = 0;
25
26protected:
27 virtual int mulLoopCount() const { return 1; }
28
29 virtual const char* onGetName() {
30 return fName.c_str();
31 }
32
33 virtual void onDraw(SkCanvas* canvas) {
34 int n = kLoop * this->mulLoopCount();
35 for (int i = 0; i < n; i++) {
36 this->performTest(fDst, fSrc, kBuffer);
37 }
38 }
39
40private:
41 typedef SkBenchmark INHERITED;
42};
43
reed@google.come05cc8e2011-10-10 14:19:40 +000044class MathBenchU32 : public MathBench {
45public:
46 MathBenchU32(void* param, const char name[]) : INHERITED(param, name) {}
reed@google.comddc518b2011-08-29 17:49:23 +000047
reed@google.come05cc8e2011-10-10 14:19:40 +000048protected:
49 virtual void performITest(uint32_t* dst, const uint32_t* src, int count) = 0;
50
51 virtual void performTest(float* SK_RESTRICT dst, const float* SK_RESTRICT src,
52 int count) SK_OVERRIDE {
53 uint32_t* d = SkTCast<uint32_t*>(dst);
54 const uint32_t* s = SkTCast<const uint32_t*>(src);
55 this->performITest(d, s, count);
56 }
57private:
58 typedef MathBench INHERITED;
59};
60
61///////////////////////////////////////////////////////////////////////////////
reed@google.comddc518b2011-08-29 17:49:23 +000062
63class NoOpMathBench : public MathBench {
64public:
bungeman@google.com9399cac2011-08-31 19:47:59 +000065 NoOpMathBench(void* param) : INHERITED(param, "noOp") {}
reed@google.comddc518b2011-08-29 17:49:23 +000066protected:
67 virtual void performTest(float dst[], const float src[], int count) {
68 for (int i = 0; i < count; ++i) {
69 dst[i] = src[i] + 1;
70 }
71 }
72private:
73 typedef MathBench INHERITED;
74};
75
76class SlowISqrtMathBench : public MathBench {
77public:
78 SlowISqrtMathBench(void* param) : INHERITED(param, "slowIsqrt") {}
79protected:
80 virtual void performTest(float dst[], const float src[], int count) {
81 for (int i = 0; i < count; ++i) {
82 dst[i] = 1.0f / sk_float_sqrt(src[i]);
83 }
84 }
85private:
86 typedef MathBench INHERITED;
87};
88
89static inline float SkFastInvSqrt(float x) {
90 float xhalf = 0.5f*x;
91 int i = *(int*)&x;
92 i = 0x5f3759df - (i>>1);
93 x = *(float*)&i;
94 x = x*(1.5f-xhalf*x*x);
95// x = x*(1.5f-xhalf*x*x); // this line takes err from 10^-3 to 10^-6
96 return x;
97}
98
99class FastISqrtMathBench : public MathBench {
100public:
101 FastISqrtMathBench(void* param) : INHERITED(param, "fastIsqrt") {}
102protected:
103 virtual void performTest(float dst[], const float src[], int count) {
104 for (int i = 0; i < count; ++i) {
105 dst[i] = SkFastInvSqrt(src[i]);
106 }
107 }
108private:
109 typedef MathBench INHERITED;
110};
111
reed@google.come05cc8e2011-10-10 14:19:40 +0000112static inline uint32_t QMul64(uint32_t value, U8CPU alpha) {
113 SkASSERT((uint8_t)alpha == alpha);
114 const uint32_t mask = 0xFF00FF;
115
116 uint64_t tmp = value;
117 tmp = (tmp & mask) | ((tmp & ~mask) << 24);
118 tmp *= alpha;
119 return ((tmp >> 8) & mask) | ((tmp >> 32) & ~mask);
120}
121
122class QMul64Bench : public MathBenchU32 {
123public:
124 QMul64Bench(void* param) : INHERITED(param, "qmul64") {}
125protected:
126 virtual void performITest(uint32_t* SK_RESTRICT dst,
127 const uint32_t* SK_RESTRICT src,
128 int count) SK_OVERRIDE {
129 for (int i = 0; i < count; ++i) {
130 dst[i] = QMul64(src[i], (uint8_t)i);
131 }
132 }
133private:
134 typedef MathBenchU32 INHERITED;
135};
136
137class QMul32Bench : public MathBenchU32 {
138public:
139 QMul32Bench(void* param) : INHERITED(param, "qmul32") {}
140protected:
141 virtual void performITest(uint32_t* SK_RESTRICT dst,
142 const uint32_t* SK_RESTRICT src,
143 int count) SK_OVERRIDE {
144 for (int i = 0; i < count; ++i) {
145 dst[i] = SkAlphaMulQ(src[i], (uint8_t)i);
146 }
147 }
148private:
149 typedef MathBenchU32 INHERITED;
150};
151
reed@google.comddc518b2011-08-29 17:49:23 +0000152///////////////////////////////////////////////////////////////////////////////
153
154static SkBenchmark* M0(void* p) { return new NoOpMathBench(p); }
155static SkBenchmark* M1(void* p) { return new SlowISqrtMathBench(p); }
156static SkBenchmark* M2(void* p) { return new FastISqrtMathBench(p); }
reed@google.come05cc8e2011-10-10 14:19:40 +0000157static SkBenchmark* M3(void* p) { return new QMul64Bench(p); }
158static SkBenchmark* M4(void* p) { return new QMul32Bench(p); }
reed@google.comddc518b2011-08-29 17:49:23 +0000159
160static BenchRegistry gReg0(M0);
161static BenchRegistry gReg1(M1);
162static BenchRegistry gReg2(M2);
reed@google.come05cc8e2011-10-10 14:19:40 +0000163static BenchRegistry gReg3(M3);
164static BenchRegistry gReg4(M4);