blob: 369f8ad32bcbbc9fc910af936b02890c50e5bd99 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "bench/Benchmark.h"
Brian Osman387eaff2018-07-20 14:50:44 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkString.h"
11#include "include/gpu/GrContext.h"
12#include "include/private/SkHalf.h"
13#include "src/core/SkColorSpacePriv.h"
14#include "src/gpu/GrContextPriv.h"
15#include "src/gpu/GrGeometryProcessor.h"
16#include "src/gpu/GrMemoryPool.h"
Robert Phillips6941f4a2020-03-12 09:41:54 -040017#include "src/gpu/GrProgramInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrRenderTargetContext.h"
19#include "src/gpu/GrRenderTargetContextPriv.h"
20#include "src/gpu/SkGr.h"
21#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
22#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
23#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
24#include "src/gpu/glsl/GrGLSLVarying.h"
25#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
26#include "src/gpu/ops/GrMeshDrawOp.h"
Robert Phillips3968fcb2019-12-05 16:40:31 -050027#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
Brian Osman387eaff2018-07-20 14:50:44 -040028
29namespace {
30
31enum Mode {
32 kBaseline_Mode, // Do the wrong thing, but quickly.
33 kFloat_Mode, // Transform colors on CPU, use float4 attributes.
Brian Osman499bf1a2018-09-17 11:32:42 -040034 kHalf_Mode, // Transform colors on CPU, use half4 attributes.
Brian Osman387eaff2018-07-20 14:50:44 -040035 kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
36};
37
38class GP : public GrGeometryProcessor {
39public:
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050040 static GrGeometryProcessor* Make(SkArenaAlloc* arena, Mode mode,
41 sk_sp<GrColorSpaceXform> colorSpaceXform) {
42 return arena->make<GP>(mode, std::move(colorSpaceXform));
Brian Osman387eaff2018-07-20 14:50:44 -040043 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050044
Brian Osman387eaff2018-07-20 14:50:44 -040045 const char* name() const override { return "VertexColorXformGP"; }
46
47 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
48 class GLSLGP : public GrGLSLGeometryProcessor {
49 public:
50 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
51 const GP& gp = args.fGP.cast<GP>();
52 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
53 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
54 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
55 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
56
57 varyingHandler->emitAttributes(gp);
58
59 // Setup color
60 GrGLSLVarying varying(kHalf4_GrSLType);
61 varyingHandler->addVarying("color", &varying);
62 vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
63
64 if (kShader_Mode == gp.fMode) {
65 fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
66 kVertex_GrShaderFlag);
67 SkString xformedColor;
68 vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
69 vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
70 vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
71 }
72
73 vertBuilder->codeAppendf("%s = color;", varying.vsOut());
74 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
75
76 // Position
77 this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
78
79 // Coverage
80 fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
81 }
82 void setData(const GrGLSLProgramDataManager& pdman,
Brian Osman609f1592020-07-01 15:14:39 -040083 const GrPrimitiveProcessor& primProc) override {
Brian Osman387eaff2018-07-20 14:50:44 -040084 const GP& gp = primProc.cast<GP>();
85 fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
86 }
87
88 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
89 };
90 return new GLSLGP();
91 }
92
93 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
94 b->add32(fMode);
95 b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
96 }
97
98private:
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050099 friend class ::SkArenaAlloc; // for access to ctor
100
101 GP(Mode mode, sk_sp<GrColorSpaceXform> colorSpaceXform)
102 : INHERITED(kVertexColorSpaceBenchGP_ClassID)
103 , fMode(mode)
104 , fColorSpaceXform(std::move(colorSpaceXform)) {
105 fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
106 switch (fMode) {
107 case kBaseline_Mode:
108 case kShader_Mode:
109 fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
110 break;
111 case kFloat_Mode:
112 fInColor = {"inColor", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
113 break;
114 case kHalf_Mode:
115 fInColor = {"inColor", kHalf4_GrVertexAttribType, kHalf4_GrSLType};
116 break;
117 }
118 this->setVertexAttributes(&fInPosition, 2);
119 }
120
Brian Osman387eaff2018-07-20 14:50:44 -0400121 Mode fMode;
122 sk_sp<GrColorSpaceXform> fColorSpaceXform;
123
124 Attribute fInPosition;
125 Attribute fInColor;
126
127 typedef GrGeometryProcessor INHERITED;
128};
129
130class Op : public GrMeshDrawOp {
131public:
132 DEFINE_OP_CLASS_ID
133
134 const char* name() const override { return "VertColorXformOp"; }
135
136 Op(GrColor color)
137 : INHERITED(ClassID())
138 , fMode(kBaseline_Mode)
139 , fColor(color) {
Greg Daniel5faf4742019-10-01 15:14:44 -0400140 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsHairline::kNo);
Brian Osman387eaff2018-07-20 14:50:44 -0400141 }
142
Brian Osmancb3d0872018-10-16 15:19:28 -0400143 Op(const SkColor4f& color4f, Mode mode)
Brian Osman387eaff2018-07-20 14:50:44 -0400144 : INHERITED(ClassID())
Brian Osman499bf1a2018-09-17 11:32:42 -0400145 , fMode(mode)
Brian Osman387eaff2018-07-20 14:50:44 -0400146 , fColor4f(color4f) {
Brian Osman3b79aa32018-10-26 14:57:35 -0400147 SkASSERT(kFloat_Mode == fMode || kHalf_Mode == mode);
Greg Daniel5faf4742019-10-01 15:14:44 -0400148 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsHairline::kNo);
Brian Osman387eaff2018-07-20 14:50:44 -0400149 }
150
151 Op(GrColor color, sk_sp<GrColorSpaceXform> colorSpaceXform)
152 : INHERITED(ClassID())
153 , fMode(kShader_Mode)
154 , fColor(color)
155 , fColorSpaceXform(std::move(colorSpaceXform)) {
Greg Daniel5faf4742019-10-01 15:14:44 -0400156 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsHairline::kNo);
Brian Osman387eaff2018-07-20 14:50:44 -0400157 }
158
159 FixedFunctionFlags fixedFunctionFlags() const override {
160 return FixedFunctionFlags::kNone;
161 }
162
Chris Dalton6ce447a2019-06-23 18:07:38 -0600163 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
164 bool hasMixedSampledCoverage, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700165 return GrProcessorSet::EmptySetAnalysis();
Brian Osman387eaff2018-07-20 14:50:44 -0400166 }
167
168private:
169 friend class ::GrOpMemoryPool;
170
Robert Phillips2669a7b2020-03-12 12:07:19 -0400171 GrProgramInfo* programInfo() override { return fProgramInfo; }
172
Robert Phillips6941f4a2020-03-12 09:41:54 -0400173 void onCreateProgramInfo(const GrCaps* caps,
174 SkArenaAlloc* arena,
Brian Salomon8afde5f2020-04-01 16:22:00 -0400175 const GrSurfaceProxyView* writeView,
Robert Phillips6941f4a2020-03-12 09:41:54 -0400176 GrAppliedClip&& appliedClip,
177 const GrXferProcessor::DstProxyView& dstProxyView) override {
178 GrGeometryProcessor* gp = GP::Make(arena, fMode, fColorSpaceXform);
179
180 fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps,
181 arena,
Brian Salomon8afde5f2020-04-01 16:22:00 -0400182 writeView,
Robert Phillips6941f4a2020-03-12 09:41:54 -0400183 std::move(appliedClip),
184 dstProxyView,
185 gp,
186 GrProcessorSet::MakeEmptySet(),
187 GrPrimitiveType::kTriangleStrip,
188 GrPipeline::InputFlags::kNone);
189 }
190
Brian Osman387eaff2018-07-20 14:50:44 -0400191 void onPrepareDraws(Target* target) override {
Robert Phillips6941f4a2020-03-12 09:41:54 -0400192 if (!fProgramInfo) {
193 this->createProgramInfo(target);
194 }
Brian Osman387eaff2018-07-20 14:50:44 -0400195
Robert Phillips6941f4a2020-03-12 09:41:54 -0400196 size_t vertexStride = fProgramInfo->primProc().vertexStride();
Brian Osman387eaff2018-07-20 14:50:44 -0400197 const int kVertexCount = 1024;
Brian Salomon12d22642019-01-29 14:38:50 -0500198 sk_sp<const GrBuffer> vertexBuffer;
Brian Osman387eaff2018-07-20 14:50:44 -0400199 int firstVertex = 0;
200 void* verts = target->makeVertexSpace(vertexStride, kVertexCount, &vertexBuffer,
201 &firstVertex);
202 if (!verts) {
203 return;
204 }
205
206 const float dx = 100.0f / kVertexCount;
207 if (kFloat_Mode == fMode) {
208 struct V {
209 SkPoint fPos;
Brian Osmancb3d0872018-10-16 15:19:28 -0400210 SkColor4f fColor;
Brian Osman387eaff2018-07-20 14:50:44 -0400211 };
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 = fColor4f;
217 v[i + 1].fPos.set(dx * i, 100.0f);
218 v[i + 1].fColor = fColor4f;
219 }
Brian Osman499bf1a2018-09-17 11:32:42 -0400220 } else if (kHalf_Mode == fMode) {
221 struct V {
222 SkPoint fPos;
223 uint64_t fColor;
224 };
225 SkASSERT(sizeof(V) == vertexStride);
226 uint64_t color;
Brian Osmana5c578f2018-09-19 14:19:02 -0400227 Sk4h halfColor = SkFloatToHalf_finite_ftz(Sk4f::Load(&fColor4f));
Brian Osman499bf1a2018-09-17 11:32:42 -0400228 color = (uint64_t)halfColor[0] << 48 |
229 (uint64_t)halfColor[1] << 32 |
230 (uint64_t)halfColor[2] << 16 |
231 (uint64_t)halfColor[3] << 0;
232 V* v = (V*)verts;
233 for (int i = 0; i < kVertexCount; i += 2) {
234 v[i + 0].fPos.set(dx * i, 0.0f);
235 v[i + 0].fColor = color;
236 v[i + 1].fPos.set(dx * i, 100.0f);
237 v[i + 1].fColor = color;
238 }
Brian Osman387eaff2018-07-20 14:50:44 -0400239 } else {
240 struct V {
241 SkPoint fPos;
242 GrColor fColor;
243 };
244 SkASSERT(sizeof(V) == vertexStride);
245 V* v = (V*)verts;
246 for (int i = 0; i < kVertexCount; i += 2) {
247 v[i + 0].fPos.set(dx * i, 0.0f);
248 v[i + 0].fColor = fColor;
249 v[i + 1].fPos.set(dx * i, 100.0f);
250 v[i + 1].fColor = fColor;
251 }
252 }
253
Robert Phillips6941f4a2020-03-12 09:41:54 -0400254 fMesh = target->allocMesh();
Chris Dalton37c7bdd2020-03-13 09:21:12 -0600255 fMesh->set(std::move(vertexBuffer), kVertexCount, firstVertex);
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700256 }
257
258 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
Robert Phillips6941f4a2020-03-12 09:41:54 -0400259 if (!fProgramInfo || !fMesh) {
260 return;
261 }
Robert Phillips3968fcb2019-12-05 16:40:31 -0500262
Chris Dalton765ed362020-03-16 17:34:44 -0600263 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
264 flushState->bindTextures(fProgramInfo->primProc(), nullptr, fProgramInfo->pipeline());
265 flushState->drawMesh(*fMesh);
Brian Osman387eaff2018-07-20 14:50:44 -0400266 }
267
268 Mode fMode;
269 GrColor fColor;
Brian Osmancb3d0872018-10-16 15:19:28 -0400270 SkColor4f fColor4f;
Brian Osman387eaff2018-07-20 14:50:44 -0400271 sk_sp<GrColorSpaceXform> fColorSpaceXform;
272
Chris Daltoneb694b72020-03-16 09:25:50 -0600273 GrSimpleMesh* fMesh = nullptr;
Robert Phillips6941f4a2020-03-12 09:41:54 -0400274 GrProgramInfo* fProgramInfo = nullptr;
275
Brian Osman387eaff2018-07-20 14:50:44 -0400276 typedef GrMeshDrawOp INHERITED;
277};
278}
279
280class VertexColorSpaceBench : public Benchmark {
281public:
282 VertexColorSpaceBench(Mode mode, const char* name) : fMode(mode) {
283 fName = "vertexcolorspace";
284 fName.appendf("_%s", name);
285 }
286
287 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
288 const char* onGetName() override { return fName.c_str(); }
289
290 void onDraw(int loops, SkCanvas* canvas) override {
291 GrContext* context = canvas->getGrContext();
Brian Osman499bf1a2018-09-17 11:32:42 -0400292 SkASSERT(context);
293
294 if (kHalf_Mode == fMode &&
Robert Phillips9da87e02019-02-04 13:26:26 -0500295 !context->priv().caps()->halfFloatVertexAttributeSupport()) {
Brian Osman499bf1a2018-09-17 11:32:42 -0400296 return;
297 }
298
Robert Phillips9da87e02019-02-04 13:26:26 -0500299 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Brian Osman387eaff2018-07-20 14:50:44 -0400300
Brian Osman82ebe042019-01-04 17:03:00 -0500301 auto p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
Mike Kleinb147ace2020-01-16 11:11:06 -0600302 SkNamedGamut::kDisplayP3);
Mike Kleine03a1762018-08-22 11:52:16 -0400303 auto xform = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
304 p3.get(), kUnpremul_SkAlphaType);
Brian Osman387eaff2018-07-20 14:50:44 -0400305
306 SkRandom r;
307 const int kDrawsPerLoop = 32;
308
309 for (int i = 0; i < loops; ++i) {
Greg Daniele20fcad2020-01-08 11:52:34 -0500310 auto rtc = GrRenderTargetContext::Make(
311 context, GrColorType::kRGBA_8888, p3, SkBackingFit::kApprox, {100, 100});
Brian Osman387eaff2018-07-20 14:50:44 -0400312 SkASSERT(rtc);
313
314 for (int j = 0; j < kDrawsPerLoop; ++j) {
315 SkColor c = r.nextU();
316 std::unique_ptr<GrDrawOp> op = nullptr;
317
318 switch (fMode) {
319 case kBaseline_Mode:
320 op = pool->allocate<Op>(SkColorToPremulGrColor(c));
321 break;
322 case kShader_Mode:
323 op = pool->allocate<Op>(SkColorToUnpremulGrColor(c), xform);
324 break;
Brian Osman499bf1a2018-09-17 11:32:42 -0400325 case kHalf_Mode:
Brian Osman387eaff2018-07-20 14:50:44 -0400326 case kFloat_Mode: {
Brian Osmancb3d0872018-10-16 15:19:28 -0400327 SkColor4f c4f = SkColor4f::FromColor(c);
Brian Osman387eaff2018-07-20 14:50:44 -0400328 c4f = xform->apply(c4f);
Brian Osman499bf1a2018-09-17 11:32:42 -0400329 op = pool->allocate<Op>(c4f, fMode);
Brian Osman387eaff2018-07-20 14:50:44 -0400330 }
331 }
332 rtc->priv().testingOnly_addDrawOp(std::move(op));
333 }
334
Greg Daniel0a2464f2020-05-14 15:45:44 -0400335 context->flushAndSubmit();
Brian Osman387eaff2018-07-20 14:50:44 -0400336 }
337 }
338
339private:
340 SkString fName;
341 Mode fMode;
342
343 typedef Benchmark INHERITED;
344};
345
346DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
347DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
Brian Osman499bf1a2018-09-17 11:32:42 -0400348DEF_BENCH(return new VertexColorSpaceBench(kHalf_Mode, "half"));
Brian Osman387eaff2018-07-20 14:50:44 -0400349DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));