• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkBenchmark.h"
2 #include "SkMatrix.h"
3 #include "SkRandom.h"
4 #include "SkString.h"
5 
6 class MatrixBench : public SkBenchmark {
7     SkString    fName;
8     enum { N = 100000 };
9 public:
MatrixBench(void * param,const char name[])10     MatrixBench(void* param, const char name[]) : INHERITED(param) {
11         fName.printf("matrix_%s", name);
12     }
13 
14     virtual void performTest() = 0;
15 
16 protected:
mulLoopCount() const17     virtual int mulLoopCount() const { return 1; }
18 
onGetName()19     virtual const char* onGetName() {
20         return fName.c_str();
21     }
22 
onDraw(SkCanvas * canvas)23     virtual void onDraw(SkCanvas* canvas) {
24         int n = N * this->mulLoopCount();
25         for (int i = 0; i < n; i++) {
26             this->performTest();
27         }
28     }
29 
30 private:
31     typedef SkBenchmark INHERITED;
32 };
33 
34 // we want to stop the compiler from eliminating code that it thinks is a no-op
35 // so we have a non-static global we increment, hoping that will convince the
36 // compiler to execute everything
37 int gMatrixBench_NonStaticGlobal;
38 
39 #define always_do(pred)                     \
40     do {                                    \
41         if (pred) {                         \
42             ++gMatrixBench_NonStaticGlobal; \
43         }                                   \
44     } while (0)
45 
46 class EqualsMatrixBench : public MatrixBench {
47 public:
EqualsMatrixBench(void * param)48     EqualsMatrixBench(void* param) : INHERITED(param, "equals") {}
49 protected:
performTest()50     virtual void performTest() {
51         SkMatrix m0, m1, m2;
52 
53         m0.reset();
54         m1.reset();
55         m2.reset();
56         always_do(m0 == m1);
57         always_do(m1 == m2);
58         always_do(m2 == m0);
59         always_do(m0.getType());
60         always_do(m1.getType());
61         always_do(m2.getType());
62     }
63 private:
64     typedef MatrixBench INHERITED;
65 };
66 
67 class ScaleMatrixBench : public MatrixBench {
68 public:
ScaleMatrixBench(void * param)69     ScaleMatrixBench(void* param) : INHERITED(param, "scale") {
70         fSX = fSY = SkFloatToScalar(1.5f);
71         fM0.reset();
72         fM1.setScale(fSX, fSY);
73         fM2.setTranslate(fSX, fSY);
74     }
75 protected:
performTest()76     virtual void performTest() {
77         SkMatrix m;
78         m = fM0; m.preScale(fSX, fSY);
79         m = fM1; m.preScale(fSX, fSY);
80         m = fM2; m.preScale(fSX, fSY);
81     }
82 private:
83     SkMatrix fM0, fM1, fM2;
84     SkScalar fSX, fSY;
85     typedef MatrixBench INHERITED;
86 };
87 
88 // having unknown values in our arrays can throw off the timing a lot, perhaps
89 // handling NaN values is a lot slower. Anyway, this guy is just meant to put
90 // reasonable values in our arrays.
init9(T array[9])91 template <typename T> void init9(T array[9]) {
92     SkRandom rand;
93     for (int i = 0; i < 9; i++) {
94         array[i] = rand.nextSScalar1();
95     }
96 }
97 
98 // Test the performance of setConcat() non-perspective case:
99 // using floating point precision only.
100 class FloatConcatMatrixBench : public MatrixBench {
101 public:
FloatConcatMatrixBench(void * p)102     FloatConcatMatrixBench(void* p) : INHERITED(p, "concat_floatfloat") {
103         init9(mya);
104         init9(myb);
105         init9(myr);
106     }
107 protected:
mulLoopCount() const108     virtual int mulLoopCount() const { return 4; }
109 
muladdmul(float a,float b,float c,float d,float * result)110     static inline void muladdmul(float a, float b, float c, float d,
111                                    float* result) {
112       *result = a * b + c * d;
113     }
performTest()114     virtual void performTest() {
115         const float* a = mya;
116         const float* b = myb;
117         float* r = myr;
118         muladdmul(a[0], b[0], a[1], b[3], &r[0]);
119         muladdmul(a[0], b[1], a[1], b[4], &r[1]);
120         muladdmul(a[0], b[2], a[1], b[5], &r[2]);
121         r[2] += a[2];
122         muladdmul(a[3], b[0], a[4], b[3], &r[3]);
123         muladdmul(a[3], b[1], a[4], b[4], &r[4]);
124         muladdmul(a[3], b[2], a[4], b[5], &r[5]);
125         r[5] += a[5];
126         r[6] = r[7] = 0.0f;
127         r[8] = 1.0f;
128     }
129 private:
130     float mya [9];
131     float myb [9];
132     float myr [9];
133     typedef MatrixBench INHERITED;
134 };
135 
SkDoubleToFloat(double x)136 static inline float SkDoubleToFloat(double x) {
137     return static_cast<float>(x);
138 }
139 
140 // Test the performance of setConcat() non-perspective case:
141 // using floating point precision but casting up to float for
142 // intermediate results during computations.
143 class FloatDoubleConcatMatrixBench : public MatrixBench {
144 public:
FloatDoubleConcatMatrixBench(void * p)145     FloatDoubleConcatMatrixBench(void* p) : INHERITED(p, "concat_floatdouble") {
146         init9(mya);
147         init9(myb);
148         init9(myr);
149     }
150 protected:
mulLoopCount() const151     virtual int mulLoopCount() const { return 4; }
152 
muladdmul(float a,float b,float c,float d,float * result)153     static inline void muladdmul(float a, float b, float c, float d,
154                                    float* result) {
155       *result = SkDoubleToFloat((double)a * b + (double)c * d);
156     }
performTest()157     virtual void performTest() {
158         const float* a = mya;
159         const float* b = myb;
160         float* r = myr;
161         muladdmul(a[0], b[0], a[1], b[3], &r[0]);
162         muladdmul(a[0], b[1], a[1], b[4], &r[1]);
163         muladdmul(a[0], b[2], a[1], b[5], &r[2]);
164         r[2] += a[2];
165         muladdmul(a[3], b[0], a[4], b[3], &r[3]);
166         muladdmul(a[3], b[1], a[4], b[4], &r[4]);
167         muladdmul(a[3], b[2], a[4], b[5], &r[5]);
168         r[5] += a[5];
169         r[6] = r[7] = 0.0f;
170         r[8] = 1.0f;
171     }
172 private:
173     float mya [9];
174     float myb [9];
175     float myr [9];
176     typedef MatrixBench INHERITED;
177 };
178 
179 // Test the performance of setConcat() non-perspective case:
180 // using double precision only.
181 class DoubleConcatMatrixBench : public MatrixBench {
182 public:
DoubleConcatMatrixBench(void * p)183     DoubleConcatMatrixBench(void* p) : INHERITED(p, "concat_double") {
184         init9(mya);
185         init9(myb);
186         init9(myr);
187     }
188 protected:
mulLoopCount() const189     virtual int mulLoopCount() const { return 4; }
190 
muladdmul(double a,double b,double c,double d,double * result)191     static inline void muladdmul(double a, double b, double c, double d,
192                                    double* result) {
193       *result = a * b + c * d;
194     }
performTest()195     virtual void performTest() {
196         const double* a = mya;
197         const double* b = myb;
198         double* r = myr;
199         muladdmul(a[0], b[0], a[1], b[3], &r[0]);
200         muladdmul(a[0], b[1], a[1], b[4], &r[1]);
201         muladdmul(a[0], b[2], a[1], b[5], &r[2]);
202         r[2] += a[2];
203         muladdmul(a[3], b[0], a[4], b[3], &r[3]);
204         muladdmul(a[3], b[1], a[4], b[4], &r[4]);
205         muladdmul(a[3], b[2], a[4], b[5], &r[5]);
206         r[5] += a[5];
207         r[6] = r[7] = 0.0;
208         r[8] = 1.0;
209     }
210 private:
211     double mya [9];
212     double myb [9];
213     double myr [9];
214     typedef MatrixBench INHERITED;
215 };
216 
217 #ifdef SK_SCALAR_IS_FLOAT
218 class ScaleTransMixedMatrixBench : public MatrixBench {
219  public:
ScaleTransMixedMatrixBench(void * p)220     ScaleTransMixedMatrixBench(void* p) : INHERITED(p, "scaletrans_mixed"), fCount (16) {
221         fMatrix.setAll(fRandom.nextS(), fRandom.nextS(), fRandom.nextS(),
222                        fRandom.nextS(), fRandom.nextS(), fRandom.nextS(),
223                        fRandom.nextS(), fRandom.nextS(), fRandom.nextS());
224         int i;
225         for (i = 0; i < fCount; i++) {
226             fSrc[i].fX = fRandom.nextS();
227             fSrc[i].fY = fRandom.nextS();
228             fDst[i].fX = fRandom.nextS();
229             fDst[i].fY = fRandom.nextS();
230         }
231     }
232  protected:
performTest()233     virtual void performTest() {
234         SkPoint* dst = fDst;
235         const SkPoint* src = fSrc;
236         int count = fCount;
237         float mx = fMatrix[SkMatrix::kMScaleX];
238         float my = fMatrix[SkMatrix::kMScaleY];
239         float tx = fMatrix[SkMatrix::kMTransX];
240         float ty = fMatrix[SkMatrix::kMTransY];
241         do {
242             dst->fY = SkScalarMulAdd(src->fY, my, ty);
243             dst->fX = SkScalarMulAdd(src->fX, mx, tx);
244             src += 1;
245             dst += 1;
246         } while (--count);
247     }
248  private:
249     SkMatrix fMatrix;
250     SkPoint fSrc [16];
251     SkPoint fDst [16];
252     int fCount;
253     SkRandom fRandom;
254     typedef MatrixBench INHERITED;
255 };
256 
257 
258 class ScaleTransDoubleMatrixBench : public MatrixBench {
259  public:
ScaleTransDoubleMatrixBench(void * p)260     ScaleTransDoubleMatrixBench(void* p) : INHERITED(p, "scaletrans_double"), fCount (16) {
261         init9(fMatrix);
262         int i;
263         for (i = 0; i < fCount; i++) {
264             fSrc[i].fX = fRandom.nextS();
265             fSrc[i].fY = fRandom.nextS();
266             fDst[i].fX = fRandom.nextS();
267             fDst[i].fY = fRandom.nextS();
268         }
269     }
270  protected:
performTest()271     virtual void performTest() {
272         SkPoint* dst = fDst;
273         const SkPoint* src = fSrc;
274         int count = fCount;
275         // As doubles, on Z600 Linux systems this is 2.5x as expensive as mixed mode
276         float mx = fMatrix[SkMatrix::kMScaleX];
277         float my = fMatrix[SkMatrix::kMScaleY];
278         float tx = fMatrix[SkMatrix::kMTransX];
279         float ty = fMatrix[SkMatrix::kMTransY];
280         do {
281             dst->fY = src->fY * my + ty;
282             dst->fX = src->fX * mx + tx;
283             src += 1;
284             dst += 1;
285         } while (--count);
286     }
287  private:
288     double fMatrix [9];
289     SkPoint fSrc [16];
290     SkPoint fDst [16];
291     int fCount;
292     SkRandom fRandom;
293     typedef MatrixBench INHERITED;
294 };
295 #endif
296 
297 
298 
299 
300 
M0(void * p)301 static SkBenchmark* M0(void* p) { return new EqualsMatrixBench(p); }
M1(void * p)302 static SkBenchmark* M1(void* p) { return new ScaleMatrixBench(p); }
M2(void * p)303 static SkBenchmark* M2(void* p) { return new FloatConcatMatrixBench(p); }
M3(void * p)304 static SkBenchmark* M3(void* p) { return new FloatDoubleConcatMatrixBench(p); }
M4(void * p)305 static SkBenchmark* M4(void* p) { return new DoubleConcatMatrixBench(p); }
306 
307 static BenchRegistry gReg0(M0);
308 static BenchRegistry gReg1(M1);
309 static BenchRegistry gReg2(M2);
310 static BenchRegistry gReg3(M3);
311 static BenchRegistry gReg4(M4);
312 
313 #ifdef SK_SCALAR_IS_FLOAT
FlM0(void * p)314 static SkBenchmark* FlM0(void* p) { return new ScaleTransMixedMatrixBench(p); }
FlM1(void * p)315 static SkBenchmark* FlM1(void* p) { return new ScaleTransDoubleMatrixBench(p); }
316 static BenchRegistry gFlReg5(FlM0);
317 static BenchRegistry gFlReg6(FlM1);
318 #endif
319