aboutsummaryrefslogtreecommitdiffhomepage
path: root/bench
diff options
context:
space:
mode:
Diffstat (limited to 'bench')
-rw-r--r--bench/VertexColorSpaceBench.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/bench/VertexColorSpaceBench.cpp b/bench/VertexColorSpaceBench.cpp
new file mode 100644
index 0000000000..4e300b7689
--- /dev/null
+++ b/bench/VertexColorSpaceBench.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+
+#include "GrContext.h"
+#include "GrContextPriv.h"
+#include "GrGeometryProcessor.h"
+#include "GrMemoryPool.h"
+#include "GrRenderTargetContext.h"
+#include "GrRenderTargetContextPriv.h"
+#include "SkGr.h"
+#include "SkString.h"
+#include "glsl/GrGLSLColorSpaceXformHelper.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLGeometryProcessor.h"
+#include "glsl/GrGLSLVarying.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
+#include "ops/GrMeshDrawOp.h"
+
+namespace {
+
+enum Mode {
+ kBaseline_Mode, // Do the wrong thing, but quickly.
+ kFloat_Mode, // Transform colors on CPU, use float4 attributes.
+ kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
+};
+
+class GP : public GrGeometryProcessor {
+public:
+ GP(Mode mode, sk_sp<GrColorSpaceXform> colorSpaceXform)
+ : INHERITED(kVertexColorSpaceBenchGP_ClassID)
+ , fMode(mode)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
+ fInPosition = {"inPosition", kFloat2_GrVertexAttribType};
+ if (kFloat_Mode == fMode) {
+ fInColor = {"inColor", kFloat4_GrVertexAttribType};
+ } else {
+ fInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
+ }
+ this->setVertexAttributeCnt(2);
+ }
+ const char* name() const override { return "VertexColorXformGP"; }
+
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
+ class GLSLGP : public GrGLSLGeometryProcessor {
+ public:
+ void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
+ const GP& gp = args.fGP.cast<GP>();
+ GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
+ GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+ GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
+ GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
+
+ varyingHandler->emitAttributes(gp);
+
+ // Setup color
+ GrGLSLVarying varying(kHalf4_GrSLType);
+ varyingHandler->addVarying("color", &varying);
+ vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
+
+ if (kShader_Mode == gp.fMode) {
+ fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
+ kVertex_GrShaderFlag);
+ SkString xformedColor;
+ vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
+ vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
+ vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
+ }
+
+ vertBuilder->codeAppendf("%s = color;", varying.vsOut());
+ fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
+
+ // Position
+ this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
+
+ // Coverage
+ fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
+ }
+ void setData(const GrGLSLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& primProc,
+ FPCoordTransformIter&&) override {
+ const GP& gp = primProc.cast<GP>();
+ fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
+ }
+
+ GrGLSLColorSpaceXformHelper fColorSpaceHelper;
+ };
+ return new GLSLGP();
+ }
+
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
+ b->add32(fMode);
+ b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
+ }
+
+private:
+ const GrPrimitiveProcessor::Attribute& onVertexAttribute(int i) const override {
+ return IthAttribute(i, fInPosition, fInColor);
+ }
+
+ Mode fMode;
+ sk_sp<GrColorSpaceXform> fColorSpaceXform;
+
+ Attribute fInPosition;
+ Attribute fInColor;
+
+ typedef GrGeometryProcessor INHERITED;
+};
+
+class Op : public GrMeshDrawOp {
+public:
+ DEFINE_OP_CLASS_ID
+
+ const char* name() const override { return "VertColorXformOp"; }
+
+ Op(GrColor color)
+ : INHERITED(ClassID())
+ , fMode(kBaseline_Mode)
+ , fColor(color) {
+ this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
+ }
+
+ Op(GrColor4f color4f)
+ : INHERITED(ClassID())
+ , fMode(kFloat_Mode)
+ , fColor4f(color4f) {
+ this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
+ }
+
+ Op(GrColor color, sk_sp<GrColorSpaceXform> colorSpaceXform)
+ : INHERITED(ClassID())
+ , fMode(kShader_Mode)
+ , fColor(color)
+ , fColorSpaceXform(std::move(colorSpaceXform)) {
+ this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
+ }
+
+ FixedFunctionFlags fixedFunctionFlags() const override {
+ return FixedFunctionFlags::kNone;
+ }
+
+ RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override {
+ return RequiresDstTexture::kNo;
+ }
+
+private:
+ friend class ::GrOpMemoryPool;
+
+ bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; }
+
+ void onPrepareDraws(Target* target) override {
+ sk_sp<GrGeometryProcessor> gp(new GP(fMode, fColorSpaceXform));
+
+ size_t vertexStride = sizeof(SkPoint) +
+ ((kFloat_Mode == fMode) ? sizeof(GrColor4f) : sizeof(uint32_t));
+ SkASSERT(vertexStride == gp->debugOnly_vertexStride());
+
+ const int kVertexCount = 1024;
+ const GrBuffer* vertexBuffer = nullptr;
+ int firstVertex = 0;
+ void* verts = target->makeVertexSpace(vertexStride, kVertexCount, &vertexBuffer,
+ &firstVertex);
+ if (!verts) {
+ return;
+ }
+
+ const float dx = 100.0f / kVertexCount;
+ if (kFloat_Mode == fMode) {
+ struct V {
+ SkPoint fPos;
+ GrColor4f fColor;
+ };
+ SkASSERT(sizeof(V) == vertexStride);
+ V* v = (V*)verts;
+ for (int i = 0; i < kVertexCount; i += 2) {
+ v[i + 0].fPos.set(dx * i, 0.0f);
+ v[i + 0].fColor = fColor4f;
+ v[i + 1].fPos.set(dx * i, 100.0f);
+ v[i + 1].fColor = fColor4f;
+ }
+ } else {
+ struct V {
+ SkPoint fPos;
+ GrColor fColor;
+ };
+ SkASSERT(sizeof(V) == vertexStride);
+ V* v = (V*)verts;
+ for (int i = 0; i < kVertexCount; i += 2) {
+ v[i + 0].fPos.set(dx * i, 0.0f);
+ v[i + 0].fColor = fColor;
+ v[i + 1].fPos.set(dx * i, 100.0f);
+ v[i + 1].fColor = fColor;
+ }
+ }
+
+ GrMesh mesh(GrPrimitiveType::kTriangleStrip);
+ mesh.setNonIndexedNonInstanced(kVertexCount);
+ mesh.setVertexData(vertexBuffer, firstVertex);
+ auto pipe = target->makePipeline(0, GrProcessorSet::MakeEmptySet(),
+ target->detachAppliedClip());
+ target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ }
+
+ Mode fMode;
+ GrColor fColor;
+ GrColor4f fColor4f;
+ sk_sp<GrColorSpaceXform> fColorSpaceXform;
+
+ typedef GrMeshDrawOp INHERITED;
+};
+}
+
+class VertexColorSpaceBench : public Benchmark {
+public:
+ VertexColorSpaceBench(Mode mode, const char* name) : fMode(mode) {
+ fName = "vertexcolorspace";
+ fName.appendf("_%s", name);
+ }
+
+ bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
+ const char* onGetName() override { return fName.c_str(); }
+
+ void onDraw(int loops, SkCanvas* canvas) override {
+ GrContext* context = canvas->getGrContext();
+ GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
+
+ SkASSERT(context);
+ auto p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
+ auto xform = GrColorSpaceXform::MakeUnpremulToUnpremul(SkColorSpace::MakeSRGB().get(),
+ p3.get());
+
+ SkRandom r;
+ const int kDrawsPerLoop = 32;
+
+ for (int i = 0; i < loops; ++i) {
+ sk_sp<GrRenderTargetContext> rtc(
+ context->contextPriv().makeDeferredRenderTargetContext(SkBackingFit::kApprox,
+ 100, 100, kRGBA_8888_GrPixelConfig, p3));
+ SkASSERT(rtc);
+
+ for (int j = 0; j < kDrawsPerLoop; ++j) {
+ SkColor c = r.nextU();
+ std::unique_ptr<GrDrawOp> op = nullptr;
+
+ switch (fMode) {
+ case kBaseline_Mode:
+ op = pool->allocate<Op>(SkColorToPremulGrColor(c));
+ break;
+ case kShader_Mode:
+ op = pool->allocate<Op>(SkColorToUnpremulGrColor(c), xform);
+ break;
+ case kFloat_Mode: {
+ GrColor4f c4f = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
+ c4f = xform->apply(c4f);
+ op = pool->allocate<Op>(c4f);
+ }
+ }
+ rtc->priv().testingOnly_addDrawOp(std::move(op));
+ }
+
+ context->flush();
+ }
+ }
+
+private:
+ SkString fName;
+ Mode fMode;
+
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
+DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
+DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));