Flutter Engine
The Flutter Engine
VertexColorSpaceBench.cpp
Go to the documentation of this file.
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 "bench/Benchmark.h"
9
12#include "src/base/SkHalf.h"
14#include "src/gpu/KeyBuilder.h"
20#include "src/gpu/ganesh/SkGr.h"
28
29namespace {
30
31enum Mode {
32 kBaseline_Mode, // Do the wrong thing, but quickly.
33 kFloat_Mode, // Transform colors on CPU, use float4 attributes.
34 kHalf_Mode, // Transform colors on CPU, use half4 attributes.
35 kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
36};
37
38class GP : public GrGeometryProcessor {
39public:
41 sk_sp<GrColorSpaceXform> colorSpaceXform) {
42 return arena->make([&](void* ptr) {
43 return new (ptr) GP(mode, std::move(colorSpaceXform));
44 });
45 }
46
47 const char* name() const override { return "VertexColorXformGP"; }
48
49 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
50 class Impl : public ProgramImpl {
51 public:
52 void setData(const GrGLSLProgramDataManager& pdman,
53 const GrShaderCaps&,
54 const GrGeometryProcessor& geomProc) override {
55 const GP& gp = geomProc.cast<GP>();
56 fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
57 }
58
59 private:
60 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
61 const GP& gp = args.fGeomProc.cast<GP>();
62 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
63 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
64 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
65 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
66
67 varyingHandler->emitAttributes(gp);
68
69 // Setup color
71 varyingHandler->addVarying("color", &varying);
72 vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
73
74 if (kShader_Mode == gp.fMode) {
75 fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
77 SkString xformedColor;
78 vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
79 vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
80 vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
81 }
82
83 vertBuilder->codeAppendf("%s = color;", varying.vsOut());
84 fragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, varying.fsIn());
85
86 // Position
87 WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
88
89 // Coverage
90 fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
91 }
92
93 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
94 };
95
96 return std::make_unique<Impl>();
97 }
98
99 void addToKey(const GrShaderCaps&, skgpu::KeyBuilder* b) const override {
100 b->add32(fMode);
101 b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
102 }
103
104private:
105 GP(Mode mode, sk_sp<GrColorSpaceXform> colorSpaceXform)
106 : INHERITED(kVertexColorSpaceBenchGP_ClassID)
107 , fMode(mode)
108 , fColorSpaceXform(std::move(colorSpaceXform)) {
109 fInPosition = {"inPosition", kFloat2_GrVertexAttribType, SkSLType::kFloat2};
110 switch (fMode) {
111 case kBaseline_Mode:
112 case kShader_Mode:
113 fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, SkSLType::kHalf4};
114 break;
115 case kFloat_Mode:
116 fInColor = {"inColor", kFloat4_GrVertexAttribType, SkSLType::kHalf4};
117 break;
118 case kHalf_Mode:
119 fInColor = {"inColor", kHalf4_GrVertexAttribType, SkSLType::kHalf4};
120 break;
121 }
122 this->setVertexAttributesWithImplicitOffsets(&fInPosition, 2);
123 }
124
125 Mode fMode;
126 sk_sp<GrColorSpaceXform> fColorSpaceXform;
127
128 Attribute fInPosition;
129 Attribute fInColor;
130
132};
133
134class Op : public GrMeshDrawOp {
135public:
137
138 const char* name() const override { return "VertColorXformOp"; }
139
141 : INHERITED(ClassID())
142 , fMode(kBaseline_Mode)
143 , fColor(color) {
144 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsHairline::kNo);
145 }
146
147 Op(const SkColor4f& color4f, Mode mode)
148 : INHERITED(ClassID())
149 , fMode(mode)
150 , fColor4f(color4f) {
151 SkASSERT(kFloat_Mode == fMode || kHalf_Mode == mode);
152 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsHairline::kNo);
153 }
154
155 Op(GrColor color, sk_sp<GrColorSpaceXform> colorSpaceXform)
156 : INHERITED(ClassID())
157 , fMode(kShader_Mode)
158 , fColor(color)
159 , fColorSpaceXform(std::move(colorSpaceXform)) {
160 this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsHairline::kNo);
161 }
162
163 FixedFunctionFlags fixedFunctionFlags() const override {
165 }
166
169 }
170
171private:
172 friend class ::GrMemoryPool;
173
174 GrProgramInfo* programInfo() override { return fProgramInfo; }
175
176 void onCreateProgramInfo(const GrCaps* caps,
177 SkArenaAlloc* arena,
178 const GrSurfaceProxyView& writeView,
179 bool usesMSAASurface,
180 GrAppliedClip&& appliedClip,
181 const GrDstProxyView& dstProxyView,
182 GrXferBarrierFlags renderPassXferBarriers,
183 GrLoadOp colorLoadOp) override {
184 GrGeometryProcessor* gp = GP::Make(arena, fMode, fColorSpaceXform);
185
187 arena,
188 writeView,
189 usesMSAASurface,
190 std::move(appliedClip),
191 dstProxyView,
192 gp,
195 renderPassXferBarriers,
196 colorLoadOp,
198 }
199
200 void onPrepareDraws(GrMeshDrawTarget* target) override {
201 if (!fProgramInfo) {
202 this->createProgramInfo(target);
203 }
204
205 size_t vertexStride = fProgramInfo->geomProc().vertexStride();
206 const int kVertexCount = 1024;
207 sk_sp<const GrBuffer> vertexBuffer;
208 int firstVertex = 0;
209 void* verts = target->makeVertexSpace(vertexStride, kVertexCount, &vertexBuffer,
210 &firstVertex);
211 if (!verts) {
212 return;
213 }
214
215 const float dx = 100.0f / kVertexCount;
216 if (kFloat_Mode == fMode) {
217 struct V {
218 SkPoint fPos;
219 SkColor4f fColor;
220 };
221 SkASSERT(sizeof(V) == vertexStride);
222 V* v = (V*)verts;
223 for (int i = 0; i < kVertexCount; i += 2) {
224 v[i + 0].fPos.set(dx * i, 0.0f);
225 v[i + 0].fColor = fColor4f;
226 v[i + 1].fPos.set(dx * i, 100.0f);
227 v[i + 1].fColor = fColor4f;
228 }
229 } else if (kHalf_Mode == fMode) {
230 struct V {
231 SkPoint fPos;
232 uint64_t fColor;
233 };
234 SkASSERT(sizeof(V) == vertexStride);
235 uint64_t color;
236 to_half(skvx::float4::Load(&fColor4f)).store(&color);
237 V* v = (V*)verts;
238 for (int i = 0; i < kVertexCount; i += 2) {
239 v[i + 0].fPos.set(dx * i, 0.0f);
240 v[i + 0].fColor = color;
241 v[i + 1].fPos.set(dx * i, 100.0f);
242 v[i + 1].fColor = color;
243 }
244 } else {
245 struct V {
246 SkPoint fPos;
247 GrColor fColor;
248 };
249 SkASSERT(sizeof(V) == vertexStride);
250 V* v = (V*)verts;
251 for (int i = 0; i < kVertexCount; i += 2) {
252 v[i + 0].fPos.set(dx * i, 0.0f);
253 v[i + 0].fColor = fColor;
254 v[i + 1].fPos.set(dx * i, 100.0f);
255 v[i + 1].fColor = fColor;
256 }
257 }
258
259 fMesh = target->allocMesh();
260 fMesh->set(std::move(vertexBuffer), kVertexCount, firstVertex);
261 }
262
263 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
264 if (!fProgramInfo || !fMesh) {
265 return;
266 }
267
268 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
269 flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
270 flushState->drawMesh(*fMesh);
271 }
272
273 Mode fMode;
274 GrColor fColor;
275 SkColor4f fColor4f;
276 sk_sp<GrColorSpaceXform> fColorSpaceXform;
277
278 GrSimpleMesh* fMesh = nullptr;
279 GrProgramInfo* fProgramInfo = nullptr;
280
281 using INHERITED = GrMeshDrawOp;
282};
283} // namespace
284
286public:
287 VertexColorSpaceBench(Mode mode, const char* name) : fMode(mode) {
288 fName = "vertexcolorspace";
289 fName.appendf("_%s", name);
290 }
291
293 const char* onGetName() override { return fName.c_str(); }
294
295 void onDraw(int loops, SkCanvas* canvas) override {
296 auto context = canvas->recordingContext()->asDirectContext();
297 SkASSERT(context);
298
299 if (kHalf_Mode == fMode &&
300 !context->priv().caps()->halfFloatVertexAttributeSupport()) {
301 return;
302 }
303
307 p3.get(), kUnpremul_SkAlphaType);
308
309 SkRandom r;
310 const int kDrawsPerLoop = 32;
311
312 for (int i = 0; i < loops; ++i) {
313 auto sdc =
316 p3,
318 {100, 100},
320 /*label=*/"DrawVertexColorSpaceBench");
321 SkASSERT(sdc);
322
323 for (int j = 0; j < kDrawsPerLoop; ++j) {
324 SkColor c = r.nextU();
325 GrOp::Owner op = nullptr;
326 GrRecordingContext* rContext = canvas->recordingContext();
327 switch (fMode) {
328 case kBaseline_Mode:
329 op = GrOp::Make<Op>(rContext, SkColorToPremulGrColor(c));
330 break;
331 case kShader_Mode:
332 op = GrOp::Make<Op>(rContext, SkColorToUnpremulGrColor(c), xform);
333 break;
334 case kHalf_Mode:
335 case kFloat_Mode: {
336 SkColor4f c4f = SkColor4f::FromColor(c);
337 c4f = xform->apply(c4f);
338 op = GrOp::Make<Op>(rContext, c4f, fMode);
339 }
340 }
341 sdc->addDrawOp(std::move(op));
342 }
343
344 context->flushAndSubmit();
345 }
346 }
347
348private:
349 SkString fName;
350 Mode fMode;
351
352 using INHERITED = Benchmark;
353};
354
355DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
356DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
357DEF_BENCH(return new VertexColorSpaceBench(kHalf_Mode, "half"));
358DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));
const char * backend
uint32_t GrColor
Definition: GrColor.h:25
#define DEFINE_OP_CLASS_ID
Definition: GrOp.h:64
GrClampType
Definition: GrTypesPriv.h:228
@ kVertex_GrShaderFlag
Definition: GrTypesPriv.h:286
GrLoadOp
Definition: GrTypesPriv.h:155
@ kFloat2_GrVertexAttribType
Definition: GrTypesPriv.h:314
@ kUByte4_norm_GrVertexAttribType
Definition: GrTypesPriv.h:334
@ kFloat4_GrVertexAttribType
Definition: GrTypesPriv.h:316
@ kHalf4_GrVertexAttribType
Definition: GrTypesPriv.h:319
GrXferBarrierFlags
static const size_t kVertexCount
kUnpremul_SkAlphaType
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkColorSpace * sk_srgb_singleton()
uint32_t SkColor
Definition: SkColor.h:37
static GrColor SkColorToUnpremulGrColor(SkColor c)
Definition: SkGr.h:60
static GrColor SkColorToPremulGrColor(SkColor c)
Definition: SkGr.h:51
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"))
Definition: GrCaps.h:57
static sk_sp< GrColorSpaceXform > Make(SkColorSpace *src, SkAlphaType srcAT, SkColorSpace *dst, SkAlphaType dstAT)
static uint32_t XformKey(const GrColorSpaceXform *xform)
virtual GrDirectContext * asDirectContext()
virtual FixedFunctionFlags fixedFunctionFlags() const
Definition: GrDrawOp.h:112
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
void emitAttributes(const GrGeometryProcessor &)
void addVarying(const char *name, GrGLSLVarying *varying, Interpolation=Interpolation::kInterpolated)
virtual std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const =0
size_t vertexStride() const
virtual GrProgramInfo * programInfo()=0
void createProgramInfo(const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
Definition: GrMeshDrawOp.h:39
GrMeshDrawOp(uint32_t classID)
virtual void onCreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
virtual void onPrepareDraws(GrMeshDrawTarget *)=0
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
std::unique_ptr< GrOp > Owner
Definition: GrOp.h:72
virtual const char * name() const =0
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
Definition: GrOp.h:279
static constexpr Analysis EmptySetAnalysis()
static GrProcessorSet MakeEmptySet()
const T & cast() const
Definition: GrProcessor.h:127
virtual const char * name() const =0
const GrPipeline & pipeline() const
Definition: GrProgramInfo.h:39
const GrGeometryProcessor & geomProc() const
Definition: GrProgramInfo.h:40
static GrProgramInfo * CreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrPipeline *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp, const GrUserStencilSettings *=&GrUserStencilSettings::kUnused)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
uint32_t nextU()
Definition: SkRandom.h:42
const char * c_str() const
Definition: SkString.h:133
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
VertexColorSpaceBench(Mode mode, const char *name)
const char * onGetName() override
bool isSuitableFor(Backend backend) override
void onDraw(int loops, SkCanvas *canvas) override
T * get() const
Definition: SkRefCnt.h:303
static std::unique_ptr< SurfaceDrawContext > Make(GrRecordingContext *, GrColorType, sk_sp< GrSurfaceProxy >, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &)
DlColor color
static bool b
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t * target
T __attribute__((ext_vector_type(N))) V
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
static constexpr skcms_Matrix3x3 kDisplayP3
Definition: SkColorSpace.h:87
static constexpr skcms_TransferFunction kSRGB
Definition: SkColorSpace.h:45
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
SIN Vec< N, uint16_t > to_half(const Vec< N, float > &x)
Definition: SkVx.h:750
Definition: ref_ptr.h:256
void set(sk_sp< const GrBuffer > vertexBuffer, int vertexCount, int baseVertex)
Definition: GrSimpleMesh.h:47
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition: SkVx.h:109
SkBlendMode fMode
Definition: xfermodes.cpp:52