blob: b8f54726ba262ad671d90cd0d30f6e6e04670959 [file] [log] [blame]
Brian Osman387eaff2018-07-20 14:50:44 -04001/*
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
10#include "GrContext.h"
11#include "GrContextPriv.h"
12#include "GrGeometryProcessor.h"
13#include "GrMemoryPool.h"
14#include "GrRenderTargetContext.h"
15#include "GrRenderTargetContextPriv.h"
Mike Kleine28a6b52018-07-25 13:05:17 -040016#include "SkColorSpacePriv.h"
Brian Osman387eaff2018-07-20 14:50:44 -040017#include "SkGr.h"
Brian Osman499bf1a2018-09-17 11:32:42 -040018#include "SkHalf.h"
Brian Osman387eaff2018-07-20 14:50:44 -040019#include "SkString.h"
20#include "glsl/GrGLSLColorSpaceXformHelper.h"
21#include "glsl/GrGLSLFragmentShaderBuilder.h"
22#include "glsl/GrGLSLGeometryProcessor.h"
23#include "glsl/GrGLSLVarying.h"
24#include "glsl/GrGLSLVertexGeoBuilder.h"
25#include "ops/GrMeshDrawOp.h"
26
27namespace {
28
29enum Mode {
30 kBaseline_Mode, // Do the wrong thing, but quickly.
31 kFloat_Mode, // Transform colors on CPU, use float4 attributes.
Brian Osman499bf1a2018-09-17 11:32:42 -040032 kHalf_Mode, // Transform colors on CPU, use half4 attributes.
Brian Osman387eaff2018-07-20 14:50:44 -040033 kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
34};
35
36class GP : public GrGeometryProcessor {
37public:
38 GP(Mode mode, sk_sp<GrColorSpaceXform> colorSpaceXform)
39 : INHERITED(kVertexColorSpaceBenchGP_ClassID)
40 , fMode(mode)
41 , fColorSpaceXform(std::move(colorSpaceXform)) {
Brian Osmand4c29702018-09-14 16:16:55 -040042 fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
Brian Osman499bf1a2018-09-17 11:32:42 -040043 switch (fMode) {
44 case kBaseline_Mode:
45 case kShader_Mode:
46 fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
47 break;
48 case kFloat_Mode:
49 fInColor = {"inColor", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
50 break;
51 case kHalf_Mode:
52 fInColor = {"inColor", kHalf4_GrVertexAttribType, kHalf4_GrSLType};
53 break;
Brian Osman387eaff2018-07-20 14:50:44 -040054 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -050055 this->setVertexAttributes(&fInPosition, 2);
Brian Osman387eaff2018-07-20 14:50:44 -040056 }
57 const char* name() const override { return "VertexColorXformGP"; }
58
59 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
60 class GLSLGP : public GrGLSLGeometryProcessor {
61 public:
62 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
63 const GP& gp = args.fGP.cast<GP>();
64 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
65 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
66 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
67 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
68
69 varyingHandler->emitAttributes(gp);
70
71 // Setup color
72 GrGLSLVarying varying(kHalf4_GrSLType);
73 varyingHandler->addVarying("color", &varying);
74 vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
75
76 if (kShader_Mode == gp.fMode) {
77 fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
78 kVertex_GrShaderFlag);
79 SkString xformedColor;
80 vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
81 vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
82 vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
83 }
84
85 vertBuilder->codeAppendf("%s = color;", varying.vsOut());
86 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
87
88 // Position
89 this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
90
91 // Coverage
92 fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
93 }
94 void setData(const GrGLSLProgramDataManager& pdman,
95 const GrPrimitiveProcessor& primProc,
96 FPCoordTransformIter&&) override {
97 const GP& gp = primProc.cast<GP>();
98 fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
99 }
100
101 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
102 };
103 return new GLSLGP();
104 }
105
106 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
107 b->add32(fMode);
108 b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
109 }
110
111private:
Brian Osman387eaff2018-07-20 14:50:44 -0400112 Mode fMode;
113 sk_sp<GrColorSpaceXform> fColorSpaceXform;
114
115 Attribute fInPosition;
116 Attribute fInColor;
117
118 typedef GrGeometryProcessor INHERITED;
119};
120
121class Op : public GrMeshDrawOp {
122public:
123 DEFINE_OP_CLASS_ID
124
125 const char* name() const override { return "VertColorXformOp"; }
126
127 Op(GrColor color)
128 : INHERITED(ClassID())
129 , fMode(kBaseline_Mode)
130 , fColor(color) {
131 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
132 }
133
Brian Osmancb3d0872018-10-16 15:19:28 -0400134 Op(const SkColor4f& color4f, Mode mode)
Brian Osman387eaff2018-07-20 14:50:44 -0400135 : INHERITED(ClassID())
Brian Osman499bf1a2018-09-17 11:32:42 -0400136 , fMode(mode)
Brian Osman387eaff2018-07-20 14:50:44 -0400137 , fColor4f(color4f) {
Brian Osman3b79aa32018-10-26 14:57:35 -0400138 SkASSERT(kFloat_Mode == fMode || kHalf_Mode == mode);
Brian Osman387eaff2018-07-20 14:50:44 -0400139 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
140 }
141
142 Op(GrColor color, sk_sp<GrColorSpaceXform> colorSpaceXform)
143 : INHERITED(ClassID())
144 , fMode(kShader_Mode)
145 , fColor(color)
146 , fColorSpaceXform(std::move(colorSpaceXform)) {
147 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
148 }
149
150 FixedFunctionFlags fixedFunctionFlags() const override {
151 return FixedFunctionFlags::kNone;
152 }
153
154 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
155 return RequiresDstTexture::kNo;
156 }
157
158private:
159 friend class ::GrOpMemoryPool;
160
Brian Osman387eaff2018-07-20 14:50:44 -0400161 void onPrepareDraws(Target* target) override {
162 sk_sp<GrGeometryProcessor> gp(new GP(fMode, fColorSpaceXform));
163
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500164 size_t vertexStride = gp->vertexStride();
Brian Osman387eaff2018-07-20 14:50:44 -0400165 const int kVertexCount = 1024;
166 const GrBuffer* vertexBuffer = nullptr;
167 int firstVertex = 0;
168 void* verts = target->makeVertexSpace(vertexStride, kVertexCount, &vertexBuffer,
169 &firstVertex);
170 if (!verts) {
171 return;
172 }
173
174 const float dx = 100.0f / kVertexCount;
175 if (kFloat_Mode == fMode) {
176 struct V {
177 SkPoint fPos;
Brian Osmancb3d0872018-10-16 15:19:28 -0400178 SkColor4f fColor;
Brian Osman387eaff2018-07-20 14:50:44 -0400179 };
180 SkASSERT(sizeof(V) == vertexStride);
181 V* v = (V*)verts;
182 for (int i = 0; i < kVertexCount; i += 2) {
183 v[i + 0].fPos.set(dx * i, 0.0f);
184 v[i + 0].fColor = fColor4f;
185 v[i + 1].fPos.set(dx * i, 100.0f);
186 v[i + 1].fColor = fColor4f;
187 }
Brian Osman499bf1a2018-09-17 11:32:42 -0400188 } else if (kHalf_Mode == fMode) {
189 struct V {
190 SkPoint fPos;
191 uint64_t fColor;
192 };
193 SkASSERT(sizeof(V) == vertexStride);
194 uint64_t color;
Brian Osmana5c578f2018-09-19 14:19:02 -0400195 Sk4h halfColor = SkFloatToHalf_finite_ftz(Sk4f::Load(&fColor4f));
Brian Osman499bf1a2018-09-17 11:32:42 -0400196 color = (uint64_t)halfColor[0] << 48 |
197 (uint64_t)halfColor[1] << 32 |
198 (uint64_t)halfColor[2] << 16 |
199 (uint64_t)halfColor[3] << 0;
200 V* v = (V*)verts;
201 for (int i = 0; i < kVertexCount; i += 2) {
202 v[i + 0].fPos.set(dx * i, 0.0f);
203 v[i + 0].fColor = color;
204 v[i + 1].fPos.set(dx * i, 100.0f);
205 v[i + 1].fColor = color;
206 }
Brian Osman387eaff2018-07-20 14:50:44 -0400207 } else {
208 struct V {
209 SkPoint fPos;
210 GrColor fColor;
211 };
212 SkASSERT(sizeof(V) == vertexStride);
213 V* v = (V*)verts;
214 for (int i = 0; i < kVertexCount; i += 2) {
215 v[i + 0].fPos.set(dx * i, 0.0f);
216 v[i + 0].fColor = fColor;
217 v[i + 1].fPos.set(dx * i, 100.0f);
218 v[i + 1].fColor = fColor;
219 }
220 }
221
Brian Salomon7eae3e02018-08-07 14:02:38 +0000222 GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangleStrip);
223 mesh->setNonIndexedNonInstanced(kVertexCount);
224 mesh->setVertexData(vertexBuffer, firstVertex);
Brian Osman387eaff2018-07-20 14:50:44 -0400225 auto pipe = target->makePipeline(0, GrProcessorSet::MakeEmptySet(),
226 target->detachAppliedClip());
Brian Salomon7eae3e02018-08-07 14:02:38 +0000227 target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
Brian Osman387eaff2018-07-20 14:50:44 -0400228 }
229
230 Mode fMode;
231 GrColor fColor;
Brian Osmancb3d0872018-10-16 15:19:28 -0400232 SkColor4f fColor4f;
Brian Osman387eaff2018-07-20 14:50:44 -0400233 sk_sp<GrColorSpaceXform> fColorSpaceXform;
234
235 typedef GrMeshDrawOp INHERITED;
236};
237}
238
239class VertexColorSpaceBench : public Benchmark {
240public:
241 VertexColorSpaceBench(Mode mode, const char* name) : fMode(mode) {
242 fName = "vertexcolorspace";
243 fName.appendf("_%s", name);
244 }
245
246 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
247 const char* onGetName() override { return fName.c_str(); }
248
249 void onDraw(int loops, SkCanvas* canvas) override {
250 GrContext* context = canvas->getGrContext();
Brian Osman499bf1a2018-09-17 11:32:42 -0400251 SkASSERT(context);
252
253 if (kHalf_Mode == fMode &&
254 !context->contextPriv().caps()->halfFloatVertexAttributeSupport()) {
255 return;
256 }
257
Brian Osman387eaff2018-07-20 14:50:44 -0400258 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
259
Brian Osman387eaff2018-07-20 14:50:44 -0400260 auto p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
261 SkColorSpace::kDCIP3_D65_Gamut);
Mike Kleine03a1762018-08-22 11:52:16 -0400262 auto xform = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
263 p3.get(), kUnpremul_SkAlphaType);
Brian Osman387eaff2018-07-20 14:50:44 -0400264
265 SkRandom r;
266 const int kDrawsPerLoop = 32;
267
268 for (int i = 0; i < loops; ++i) {
269 sk_sp<GrRenderTargetContext> rtc(
Greg Daniel919c9e72018-11-09 10:31:55 -0500270 context->contextPriv().makeDeferredRenderTargetContext(SkBackingFit::kApprox,
271 100, 100, kRGBA_8888_GrPixelConfig, p3));
Brian Osman387eaff2018-07-20 14:50:44 -0400272 SkASSERT(rtc);
273
274 for (int j = 0; j < kDrawsPerLoop; ++j) {
275 SkColor c = r.nextU();
276 std::unique_ptr<GrDrawOp> op = nullptr;
277
278 switch (fMode) {
279 case kBaseline_Mode:
280 op = pool->allocate<Op>(SkColorToPremulGrColor(c));
281 break;
282 case kShader_Mode:
283 op = pool->allocate<Op>(SkColorToUnpremulGrColor(c), xform);
284 break;
Brian Osman499bf1a2018-09-17 11:32:42 -0400285 case kHalf_Mode:
Brian Osman387eaff2018-07-20 14:50:44 -0400286 case kFloat_Mode: {
Brian Osmancb3d0872018-10-16 15:19:28 -0400287 SkColor4f c4f = SkColor4f::FromColor(c);
Brian Osman387eaff2018-07-20 14:50:44 -0400288 c4f = xform->apply(c4f);
Brian Osman499bf1a2018-09-17 11:32:42 -0400289 op = pool->allocate<Op>(c4f, fMode);
Brian Osman387eaff2018-07-20 14:50:44 -0400290 }
291 }
292 rtc->priv().testingOnly_addDrawOp(std::move(op));
293 }
294
295 context->flush();
296 }
297 }
298
299private:
300 SkString fName;
301 Mode fMode;
302
303 typedef Benchmark INHERITED;
304};
305
306DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
307DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
Brian Osman499bf1a2018-09-17 11:32:42 -0400308DEF_BENCH(return new VertexColorSpaceBench(kHalf_Mode, "half"));
Brian Osman387eaff2018-07-20 14:50:44 -0400309DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));