blob: 111b574b7b63feb7a2cb013fe0bda558b8928eea [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"
Robert Phillipsf0288102020-07-06 13:45:34 -040011#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/private/SkHalf.h"
13#include "src/core/SkColorSpacePriv.h"
Adlai Hollera0693042020-10-14 11:23:11 -040014#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#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/SkGr.h"
19#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
20#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
21#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
22#include "src/gpu/glsl/GrGLSLVarying.h"
23#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
24#include "src/gpu/ops/GrMeshDrawOp.h"
Robert Phillips3968fcb2019-12-05 16:40:31 -050025#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
Robert Phillips4dca8312021-07-28 15:13:20 -040026#include "src/gpu/v1/SurfaceDrawContext_v1.h"
Brian Osman387eaff2018-07-20 14:50:44 -040027
28namespace {
29
30enum Mode {
31 kBaseline_Mode, // Do the wrong thing, but quickly.
32 kFloat_Mode, // Transform colors on CPU, use float4 attributes.
Brian Osman499bf1a2018-09-17 11:32:42 -040033 kHalf_Mode, // Transform colors on CPU, use half4 attributes.
Brian Osman387eaff2018-07-20 14:50:44 -040034 kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
35};
36
37class GP : public GrGeometryProcessor {
38public:
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050039 static GrGeometryProcessor* Make(SkArenaAlloc* arena, Mode mode,
40 sk_sp<GrColorSpaceXform> colorSpaceXform) {
Mike Kleinf1241082020-12-14 15:59:09 -060041 return arena->make([&](void* ptr) {
42 return new (ptr) GP(mode, std::move(colorSpaceXform));
43 });
Brian Osman387eaff2018-07-20 14:50:44 -040044 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050045
Brian Osman387eaff2018-07-20 14:50:44 -040046 const char* name() const override { return "VertexColorXformGP"; }
47
Brian Salomonf95940b2021-08-09 15:56:24 -040048 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
49 class GLSLGP : public ProgramImpl {
Brian Osman387eaff2018-07-20 14:50:44 -040050 public:
51 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
Robert Phillips787fd9d2021-03-22 14:48:09 -040052 const GP& gp = args.fGeomProc.cast<GP>();
Brian Osman387eaff2018-07-20 14:50:44 -040053 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
54 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
55 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
56 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
57
58 varyingHandler->emitAttributes(gp);
59
60 // Setup color
61 GrGLSLVarying varying(kHalf4_GrSLType);
62 varyingHandler->addVarying("color", &varying);
63 vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
64
65 if (kShader_Mode == gp.fMode) {
66 fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
67 kVertex_GrShaderFlag);
68 SkString xformedColor;
69 vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
70 vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
71 vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
72 }
73
74 vertBuilder->codeAppendf("%s = color;", varying.vsOut());
John Stiles4d7ac492021-03-09 20:16:43 -050075 fragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, varying.fsIn());
Brian Osman387eaff2018-07-20 14:50:44 -040076
77 // Position
Brian Salomon5a328282021-04-14 10:32:25 -040078 WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
Brian Osman387eaff2018-07-20 14:50:44 -040079
80 // Coverage
John Stiles4d7ac492021-03-09 20:16:43 -050081 fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
Brian Osman387eaff2018-07-20 14:50:44 -040082 }
83 void setData(const GrGLSLProgramDataManager& pdman,
Brian Salomon5a328282021-04-14 10:32:25 -040084 const GrShaderCaps&,
Robert Phillips787fd9d2021-03-22 14:48:09 -040085 const GrGeometryProcessor& geomProc) override {
86 const GP& gp = geomProc.cast<GP>();
Brian Osman387eaff2018-07-20 14:50:44 -040087 fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
88 }
89
90 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
91 };
Brian Salomonf95940b2021-08-09 15:56:24 -040092 return std::make_unique<GLSLGP>();
Brian Osman387eaff2018-07-20 14:50:44 -040093 }
94
Brian Salomon13b28732021-08-06 15:33:58 -040095 void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
Brian Osman387eaff2018-07-20 14:50:44 -040096 b->add32(fMode);
97 b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
98 }
99
100private:
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500101 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
John Stiles7571f9e2020-09-02 22:42:33 -0400127 using INHERITED = GrGeometryProcessor;
Brian Osman387eaff2018-07-20 14:50:44 -0400128};
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 Dalton57ab06c2021-04-22 12:57:28 -0600163 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700164 return GrProcessorSet::EmptySetAnalysis();
Brian Osman387eaff2018-07-20 14:50:44 -0400165 }
166
167private:
Herb Derbye32e1ab2020-10-27 10:29:46 -0400168 friend class ::GrMemoryPool;
Brian Osman387eaff2018-07-20 14:50:44 -0400169
Robert Phillips2669a7b2020-03-12 12:07:19 -0400170 GrProgramInfo* programInfo() override { return fProgramInfo; }
171
Robert Phillips6941f4a2020-03-12 09:41:54 -0400172 void onCreateProgramInfo(const GrCaps* caps,
173 SkArenaAlloc* arena,
Adlai Hollere2296f72020-11-19 13:41:26 -0500174 const GrSurfaceProxyView& writeView,
Chris Dalton6aaf00f2021-07-13 13:26:39 -0600175 bool usesMSAASurface,
Robert Phillips6941f4a2020-03-12 09:41:54 -0400176 GrAppliedClip&& appliedClip,
John Stiles52cb1d02021-06-02 11:58:05 -0400177 const GrDstProxyView& dstProxyView,
Greg Daniel42dbca52020-11-20 10:22:43 -0500178 GrXferBarrierFlags renderPassXferBarriers,
179 GrLoadOp colorLoadOp) override {
Robert Phillips6941f4a2020-03-12 09:41:54 -0400180 GrGeometryProcessor* gp = GP::Make(arena, fMode, fColorSpaceXform);
181
182 fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps,
183 arena,
Brian Salomon8afde5f2020-04-01 16:22:00 -0400184 writeView,
Robert Phillips6941f4a2020-03-12 09:41:54 -0400185 std::move(appliedClip),
186 dstProxyView,
187 gp,
188 GrProcessorSet::MakeEmptySet(),
189 GrPrimitiveType::kTriangleStrip,
Greg Danield358cbe2020-09-11 09:33:54 -0400190 renderPassXferBarriers,
Greg Daniel42dbca52020-11-20 10:22:43 -0500191 colorLoadOp,
Robert Phillips6941f4a2020-03-12 09:41:54 -0400192 GrPipeline::InputFlags::kNone);
193 }
194
Robert Phillips71143952021-06-17 14:55:07 -0400195 void onPrepareDraws(GrMeshDrawTarget* target) override {
Robert Phillips6941f4a2020-03-12 09:41:54 -0400196 if (!fProgramInfo) {
197 this->createProgramInfo(target);
198 }
Brian Osman387eaff2018-07-20 14:50:44 -0400199
Robert Phillips787fd9d2021-03-22 14:48:09 -0400200 size_t vertexStride = fProgramInfo->geomProc().vertexStride();
Brian Osman387eaff2018-07-20 14:50:44 -0400201 const int kVertexCount = 1024;
Brian Salomon12d22642019-01-29 14:38:50 -0500202 sk_sp<const GrBuffer> vertexBuffer;
Brian Osman387eaff2018-07-20 14:50:44 -0400203 int firstVertex = 0;
204 void* verts = target->makeVertexSpace(vertexStride, kVertexCount, &vertexBuffer,
205 &firstVertex);
206 if (!verts) {
207 return;
208 }
209
210 const float dx = 100.0f / kVertexCount;
211 if (kFloat_Mode == fMode) {
212 struct V {
213 SkPoint fPos;
Brian Osmancb3d0872018-10-16 15:19:28 -0400214 SkColor4f fColor;
Brian Osman387eaff2018-07-20 14:50:44 -0400215 };
216 SkASSERT(sizeof(V) == vertexStride);
217 V* v = (V*)verts;
218 for (int i = 0; i < kVertexCount; i += 2) {
219 v[i + 0].fPos.set(dx * i, 0.0f);
220 v[i + 0].fColor = fColor4f;
221 v[i + 1].fPos.set(dx * i, 100.0f);
222 v[i + 1].fColor = fColor4f;
223 }
Brian Osman499bf1a2018-09-17 11:32:42 -0400224 } else if (kHalf_Mode == fMode) {
225 struct V {
226 SkPoint fPos;
227 uint64_t fColor;
228 };
229 SkASSERT(sizeof(V) == vertexStride);
230 uint64_t color;
Brian Osmana5c578f2018-09-19 14:19:02 -0400231 Sk4h halfColor = SkFloatToHalf_finite_ftz(Sk4f::Load(&fColor4f));
Brian Osman499bf1a2018-09-17 11:32:42 -0400232 color = (uint64_t)halfColor[0] << 48 |
233 (uint64_t)halfColor[1] << 32 |
234 (uint64_t)halfColor[2] << 16 |
235 (uint64_t)halfColor[3] << 0;
236 V* v = (V*)verts;
237 for (int i = 0; i < kVertexCount; i += 2) {
238 v[i + 0].fPos.set(dx * i, 0.0f);
239 v[i + 0].fColor = color;
240 v[i + 1].fPos.set(dx * i, 100.0f);
241 v[i + 1].fColor = color;
242 }
Brian Osman387eaff2018-07-20 14:50:44 -0400243 } else {
244 struct V {
245 SkPoint fPos;
246 GrColor fColor;
247 };
248 SkASSERT(sizeof(V) == vertexStride);
249 V* v = (V*)verts;
250 for (int i = 0; i < kVertexCount; i += 2) {
251 v[i + 0].fPos.set(dx * i, 0.0f);
252 v[i + 0].fColor = fColor;
253 v[i + 1].fPos.set(dx * i, 100.0f);
254 v[i + 1].fColor = fColor;
255 }
256 }
257
Robert Phillips6941f4a2020-03-12 09:41:54 -0400258 fMesh = target->allocMesh();
Chris Dalton37c7bdd2020-03-13 09:21:12 -0600259 fMesh->set(std::move(vertexBuffer), kVertexCount, firstVertex);
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700260 }
261
262 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
Robert Phillips6941f4a2020-03-12 09:41:54 -0400263 if (!fProgramInfo || !fMesh) {
264 return;
265 }
Robert Phillips3968fcb2019-12-05 16:40:31 -0500266
Chris Dalton765ed362020-03-16 17:34:44 -0600267 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
Robert Phillips787fd9d2021-03-22 14:48:09 -0400268 flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
Chris Dalton765ed362020-03-16 17:34:44 -0600269 flushState->drawMesh(*fMesh);
Brian Osman387eaff2018-07-20 14:50:44 -0400270 }
271
272 Mode fMode;
273 GrColor fColor;
Brian Osmancb3d0872018-10-16 15:19:28 -0400274 SkColor4f fColor4f;
Brian Osman387eaff2018-07-20 14:50:44 -0400275 sk_sp<GrColorSpaceXform> fColorSpaceXform;
276
Chris Daltoneb694b72020-03-16 09:25:50 -0600277 GrSimpleMesh* fMesh = nullptr;
Robert Phillips6941f4a2020-03-12 09:41:54 -0400278 GrProgramInfo* fProgramInfo = nullptr;
279
John Stiles7571f9e2020-09-02 22:42:33 -0400280 using INHERITED = GrMeshDrawOp;
Brian Osman387eaff2018-07-20 14:50:44 -0400281};
John Stilesa6841be2020-08-06 14:11:56 -0400282} // namespace
Brian Osman387eaff2018-07-20 14:50:44 -0400283
284class VertexColorSpaceBench : public Benchmark {
285public:
286 VertexColorSpaceBench(Mode mode, const char* name) : fMode(mode) {
287 fName = "vertexcolorspace";
288 fName.appendf("_%s", name);
289 }
290
291 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
292 const char* onGetName() override { return fName.c_str(); }
293
294 void onDraw(int loops, SkCanvas* canvas) override {
Robert Phillipsf0288102020-07-06 13:45:34 -0400295 auto context = canvas->recordingContext()->asDirectContext();
Brian Osman499bf1a2018-09-17 11:32:42 -0400296 SkASSERT(context);
297
298 if (kHalf_Mode == fMode &&
Robert Phillips9da87e02019-02-04 13:26:26 -0500299 !context->priv().caps()->halfFloatVertexAttributeSupport()) {
Brian Osman499bf1a2018-09-17 11:32:42 -0400300 return;
301 }
302
Brian Osman82ebe042019-01-04 17:03:00 -0500303 auto p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
Mike Kleinb147ace2020-01-16 11:11:06 -0600304 SkNamedGamut::kDisplayP3);
Mike Kleine03a1762018-08-22 11:52:16 -0400305 auto xform = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
306 p3.get(), kUnpremul_SkAlphaType);
Brian Osman387eaff2018-07-20 14:50:44 -0400307
308 SkRandom r;
309 const int kDrawsPerLoop = 32;
310
311 for (int i = 0; i < loops; ++i) {
Robert Phillips4dca8312021-07-28 15:13:20 -0400312 auto sdc = skgpu::v1::SurfaceDrawContext::Make(context, GrColorType::kRGBA_8888, p3,
313 SkBackingFit::kApprox, {100, 100},
314 SkSurfaceProps());
315 SkASSERT(sdc);
Brian Osman387eaff2018-07-20 14:50:44 -0400316
317 for (int j = 0; j < kDrawsPerLoop; ++j) {
318 SkColor c = r.nextU();
Herb Derbyc76d4092020-10-07 16:46:15 -0400319 GrOp::Owner op = nullptr;
320 GrRecordingContext* rContext = canvas->recordingContext();
Brian Osman387eaff2018-07-20 14:50:44 -0400321 switch (fMode) {
322 case kBaseline_Mode:
Herb Derbyc76d4092020-10-07 16:46:15 -0400323 op = GrOp::Make<Op>(rContext, SkColorToPremulGrColor(c));
Brian Osman387eaff2018-07-20 14:50:44 -0400324 break;
325 case kShader_Mode:
Herb Derbyc76d4092020-10-07 16:46:15 -0400326 op = GrOp::Make<Op>(rContext, SkColorToUnpremulGrColor(c), xform);
Brian Osman387eaff2018-07-20 14:50:44 -0400327 break;
Brian Osman499bf1a2018-09-17 11:32:42 -0400328 case kHalf_Mode:
Brian Osman387eaff2018-07-20 14:50:44 -0400329 case kFloat_Mode: {
Brian Osmancb3d0872018-10-16 15:19:28 -0400330 SkColor4f c4f = SkColor4f::FromColor(c);
Brian Osman387eaff2018-07-20 14:50:44 -0400331 c4f = xform->apply(c4f);
Herb Derbyc76d4092020-10-07 16:46:15 -0400332 op = GrOp::Make<Op>(rContext, c4f, fMode);
Brian Osman387eaff2018-07-20 14:50:44 -0400333 }
334 }
Robert Phillips4dca8312021-07-28 15:13:20 -0400335 sdc->addDrawOp(std::move(op));
Brian Osman387eaff2018-07-20 14:50:44 -0400336 }
337
Greg Daniel0a2464f2020-05-14 15:45:44 -0400338 context->flushAndSubmit();
Brian Osman387eaff2018-07-20 14:50:44 -0400339 }
340 }
341
342private:
343 SkString fName;
344 Mode fMode;
345
John Stiles7571f9e2020-09-02 22:42:33 -0400346 using INHERITED = Benchmark;
Brian Osman387eaff2018-07-20 14:50:44 -0400347};
348
349DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
350DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
Brian Osman499bf1a2018-09-17 11:32:42 -0400351DEF_BENCH(return new VertexColorSpaceBench(kHalf_Mode, "half"));
Brian Osman387eaff2018-07-20 14:50:44 -0400352DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));