SkRasterPipelineBench.cpp revision 0a76b413eac46ec218b367c5456709059557f5db
1/*
2 * Copyright 2016 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#include "Benchmark.h"
9#include "SkOpts.h"
10#include "SkRasterPipeline.h"
11
12static const int N = 15;
13
14static uint64_t dst[N];  // sRGB or F16
15static uint32_t src[N];  // sRGB
16static uint8_t mask[N];  // 8-bit linear
17
18// We'll build up a somewhat realistic useful pipeline:
19//   - load srgb src
20//   - scale src by 8-bit mask
21//   - load srgb/f16 dst
22//   - src = srcover(dst, src)
23//   - store src back as srgb/f16
24
25template <bool kF16>
26class SkRasterPipelineBench : public Benchmark {
27public:
28    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
29    const char* onGetName() override {
30        switch ((int)kF16) {
31            case 0: return "SkRasterPipeline_srgb";
32            case 1: return "SkRasterPipeline_f16";
33        }
34        return "whoops";
35    }
36
37    void onDraw(int loops, SkCanvas*) override {
38        void* mask_ctx = mask;
39        void*  src_ctx = src;
40        void*  dst_ctx = dst;
41
42        SkRasterPipeline p;
43        p.append(SkRasterPipeline::load_8888, &src_ctx);
44        p.append_from_srgb(kUnpremul_SkAlphaType);
45        p.append(SkRasterPipeline::scale_u8, &mask_ctx);
46        p.append(SkRasterPipeline::move_src_dst);
47        if (kF16) {
48            p.append(SkRasterPipeline::load_f16, &dst_ctx);
49        } else {
50            p.append(SkRasterPipeline::load_8888, &dst_ctx);
51            p.append_from_srgb(kPremul_SkAlphaType);
52        }
53        p.append(SkRasterPipeline::dstover);
54        if (kF16) {
55            p.append(SkRasterPipeline::store_f16, &dst_ctx);
56        } else {
57            p.append(SkRasterPipeline::to_srgb);
58            p.append(SkRasterPipeline::store_8888, &dst_ctx);
59        }
60
61        while (loops --> 0) {
62            p.run(0,N);
63        }
64    }
65};
66DEF_BENCH( return (new SkRasterPipelineBench< true>); )
67DEF_BENCH( return (new SkRasterPipelineBench<false>); )
68
69class SkRasterPipelineCompileVsRunBench : public Benchmark {
70public:
71    explicit SkRasterPipelineCompileVsRunBench(bool compile) : fCompile(compile) {}
72    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
73    const char* onGetName() override {
74        return fCompile ? "SkRasterPipeline_compile"
75                        : "SkRasterPipeline_run";
76    }
77
78    void onDraw(int loops, SkCanvas*) override {
79        void*  src_ctx = src;
80        void*  dst_ctx = dst;
81
82        SkRasterPipeline p;
83        p.append(SkRasterPipeline::load_8888, &dst_ctx);
84        p.append(SkRasterPipeline::move_src_dst);
85        p.append(SkRasterPipeline::load_8888, &src_ctx);
86        p.append(SkRasterPipeline::srcover);
87        p.append(SkRasterPipeline::store_8888, &dst_ctx);
88
89        if (fCompile) {
90            char buffer[1024];
91            SkArenaAlloc alloc(buffer);
92            auto fn = p.compile(&alloc);
93            while (loops --> 0) {
94                fn(0,N);
95            }
96        } else {
97            while (loops --> 0) {
98                p.run(0,N);
99            }
100        }
101    }
102private:
103    bool fCompile;
104};
105DEF_BENCH( return (new SkRasterPipelineCompileVsRunBench(true )); )
106DEF_BENCH( return (new SkRasterPipelineCompileVsRunBench(false)); )
107
108static SkColorSpaceTransferFn gamma(float g) {
109    SkColorSpaceTransferFn fn = {0,0,0,0,0,0,0};
110    fn.fG = g;
111    fn.fA = 1;
112    return fn;
113}
114
115class SkRasterPipeline_2dot2 : public Benchmark {
116public:
117    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
118    const char* onGetName() override {
119        return "SkRasterPipeline_2dot2";
120    }
121
122    void onDraw(int loops, SkCanvas*) override {
123        SkColor4f c = { 1.0f, 1.0f, 1.0f, 1.0f };
124
125        SkColorSpaceTransferFn from_2dot2 = gamma(  2.2f),
126                                 to_2dot2 = gamma(1/2.2f);
127        SkRasterPipeline p;
128        p.append(SkRasterPipeline::constant_color, &c);
129        p.append(SkRasterPipeline::parametric_r, &from_2dot2);
130        p.append(SkRasterPipeline::parametric_g, &from_2dot2);
131        p.append(SkRasterPipeline::parametric_b, &from_2dot2);
132        p.append(SkRasterPipeline::parametric_r, &  to_2dot2);
133        p.append(SkRasterPipeline::parametric_g, &  to_2dot2);
134        p.append(SkRasterPipeline::parametric_b, &  to_2dot2);
135
136        while (loops --> 0) {
137            p.run(0,N);
138        }
139    }
140};
141DEF_BENCH( return (new SkRasterPipeline_2dot2); )
142
143class SkRasterPipelineToSRGB : public Benchmark {
144public:
145    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
146    const char* onGetName() override {
147        return "SkRasterPipeline_to_srgb";
148    }
149
150    void onDraw(int loops, SkCanvas*) override {
151        SkRasterPipeline p;
152        p.append(SkRasterPipeline::to_srgb);
153
154        while (loops --> 0) {
155            p.run(0,N);
156        }
157    }
158};
159DEF_BENCH( return (new SkRasterPipelineToSRGB); )
160
161class SkRasterPipelineReuseBench : public Benchmark {
162public:
163    enum Mode { None, Some, Full };
164
165    explicit SkRasterPipelineReuseBench(Mode mode) : fMode(mode), fName("SkRasterPipelineReuse") {
166        switch(mode) {
167            case None: fName.append("_none"); break;
168            case Some: fName.append("_some"); break;
169            case Full: fName.append("_full"); break;
170        }
171    }
172    const char* onGetName() override { return fName.c_str(); }
173    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
174
175    void onDraw(int loops, SkCanvas*) override {
176        const int kStages = 20;
177        const auto stage  = SkRasterPipeline::to_srgb;  // Any stage will do.  We won't call it.
178
179        switch(fMode) {
180            case None:
181                while (loops --> 0) {
182                    SkRasterPipeline p;
183                    for (int i = 0; i < kStages; i++) {
184                        p.append(stage);
185                    }
186                }
187                break;
188
189            case Some:
190                while (loops --> 0) {
191                    SkRasterPipeline p(kStages);
192                    for (int i = 0; i < kStages; i++) {
193                        p.append(stage);
194                    }
195                }
196                break;
197
198            case Full:
199                SkRasterPipeline p(kStages);
200                while (loops --> 0) {
201                    p.rewind();
202                    for (int i = 0; i < kStages; i++) {
203                        p.append(stage);
204                    }
205                }
206                break;
207        }
208    }
209
210private:
211    Mode     fMode;
212    SkString fName;
213};
214DEF_BENCH( return (new SkRasterPipelineReuseBench(SkRasterPipelineReuseBench::None)); )
215DEF_BENCH( return (new SkRasterPipelineReuseBench(SkRasterPipelineReuseBench::Some)); )
216DEF_BENCH( return (new SkRasterPipelineReuseBench(SkRasterPipelineReuseBench::Full)); )
217