VertexColorSpaceBench.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. #include "bench/Benchmark.h"
  8. #include "include/core/SkString.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "include/private/SkHalf.h"
  11. #include "src/core/SkColorSpacePriv.h"
  12. #include "src/gpu/GrContextPriv.h"
  13. #include "src/gpu/GrGeometryProcessor.h"
  14. #include "src/gpu/GrMemoryPool.h"
  15. #include "src/gpu/GrRenderTargetContext.h"
  16. #include "src/gpu/GrRenderTargetContextPriv.h"
  17. #include "src/gpu/SkGr.h"
  18. #include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
  19. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  20. #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
  21. #include "src/gpu/glsl/GrGLSLVarying.h"
  22. #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
  23. #include "src/gpu/ops/GrMeshDrawOp.h"
  24. namespace {
  25. enum Mode {
  26. kBaseline_Mode, // Do the wrong thing, but quickly.
  27. kFloat_Mode, // Transform colors on CPU, use float4 attributes.
  28. kHalf_Mode, // Transform colors on CPU, use half4 attributes.
  29. kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
  30. };
  31. class GP : public GrGeometryProcessor {
  32. public:
  33. GP(Mode mode, sk_sp<GrColorSpaceXform> colorSpaceXform)
  34. : INHERITED(kVertexColorSpaceBenchGP_ClassID)
  35. , fMode(mode)
  36. , fColorSpaceXform(std::move(colorSpaceXform)) {
  37. fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
  38. switch (fMode) {
  39. case kBaseline_Mode:
  40. case kShader_Mode:
  41. fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
  42. break;
  43. case kFloat_Mode:
  44. fInColor = {"inColor", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
  45. break;
  46. case kHalf_Mode:
  47. fInColor = {"inColor", kHalf4_GrVertexAttribType, kHalf4_GrSLType};
  48. break;
  49. }
  50. this->setVertexAttributes(&fInPosition, 2);
  51. }
  52. const char* name() const override { return "VertexColorXformGP"; }
  53. GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
  54. class GLSLGP : public GrGLSLGeometryProcessor {
  55. public:
  56. void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
  57. const GP& gp = args.fGP.cast<GP>();
  58. GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
  59. GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
  60. GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
  61. GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
  62. varyingHandler->emitAttributes(gp);
  63. // Setup color
  64. GrGLSLVarying varying(kHalf4_GrSLType);
  65. varyingHandler->addVarying("color", &varying);
  66. vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
  67. if (kShader_Mode == gp.fMode) {
  68. fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
  69. kVertex_GrShaderFlag);
  70. SkString xformedColor;
  71. vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
  72. vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
  73. vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
  74. }
  75. vertBuilder->codeAppendf("%s = color;", varying.vsOut());
  76. fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
  77. // Position
  78. this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
  79. // Coverage
  80. fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
  81. }
  82. void setData(const GrGLSLProgramDataManager& pdman,
  83. const GrPrimitiveProcessor& primProc,
  84. FPCoordTransformIter&&) override {
  85. const GP& gp = primProc.cast<GP>();
  86. fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
  87. }
  88. GrGLSLColorSpaceXformHelper fColorSpaceHelper;
  89. };
  90. return new GLSLGP();
  91. }
  92. void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
  93. b->add32(fMode);
  94. b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
  95. }
  96. private:
  97. Mode fMode;
  98. sk_sp<GrColorSpaceXform> fColorSpaceXform;
  99. Attribute fInPosition;
  100. Attribute fInColor;
  101. typedef GrGeometryProcessor INHERITED;
  102. };
  103. class Op : public GrMeshDrawOp {
  104. public:
  105. DEFINE_OP_CLASS_ID
  106. const char* name() const override { return "VertColorXformOp"; }
  107. Op(GrColor color)
  108. : INHERITED(ClassID())
  109. , fMode(kBaseline_Mode)
  110. , fColor(color) {
  111. this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
  112. }
  113. Op(const SkColor4f& color4f, Mode mode)
  114. : INHERITED(ClassID())
  115. , fMode(mode)
  116. , fColor4f(color4f) {
  117. SkASSERT(kFloat_Mode == fMode || kHalf_Mode == mode);
  118. this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
  119. }
  120. Op(GrColor color, sk_sp<GrColorSpaceXform> colorSpaceXform)
  121. : INHERITED(ClassID())
  122. , fMode(kShader_Mode)
  123. , fColor(color)
  124. , fColorSpaceXform(std::move(colorSpaceXform)) {
  125. this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
  126. }
  127. FixedFunctionFlags fixedFunctionFlags() const override {
  128. return FixedFunctionFlags::kNone;
  129. }
  130. GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
  131. bool hasMixedSampledCoverage, GrClampType) override {
  132. return GrProcessorSet::EmptySetAnalysis();
  133. }
  134. private:
  135. friend class ::GrOpMemoryPool;
  136. void onPrepareDraws(Target* target) override {
  137. sk_sp<GrGeometryProcessor> gp(new GP(fMode, fColorSpaceXform));
  138. size_t vertexStride = gp->vertexStride();
  139. const int kVertexCount = 1024;
  140. sk_sp<const GrBuffer> vertexBuffer;
  141. int firstVertex = 0;
  142. void* verts = target->makeVertexSpace(vertexStride, kVertexCount, &vertexBuffer,
  143. &firstVertex);
  144. if (!verts) {
  145. return;
  146. }
  147. const float dx = 100.0f / kVertexCount;
  148. if (kFloat_Mode == fMode) {
  149. struct V {
  150. SkPoint fPos;
  151. SkColor4f fColor;
  152. };
  153. SkASSERT(sizeof(V) == vertexStride);
  154. V* v = (V*)verts;
  155. for (int i = 0; i < kVertexCount; i += 2) {
  156. v[i + 0].fPos.set(dx * i, 0.0f);
  157. v[i + 0].fColor = fColor4f;
  158. v[i + 1].fPos.set(dx * i, 100.0f);
  159. v[i + 1].fColor = fColor4f;
  160. }
  161. } else if (kHalf_Mode == fMode) {
  162. struct V {
  163. SkPoint fPos;
  164. uint64_t fColor;
  165. };
  166. SkASSERT(sizeof(V) == vertexStride);
  167. uint64_t color;
  168. Sk4h halfColor = SkFloatToHalf_finite_ftz(Sk4f::Load(&fColor4f));
  169. color = (uint64_t)halfColor[0] << 48 |
  170. (uint64_t)halfColor[1] << 32 |
  171. (uint64_t)halfColor[2] << 16 |
  172. (uint64_t)halfColor[3] << 0;
  173. V* v = (V*)verts;
  174. for (int i = 0; i < kVertexCount; i += 2) {
  175. v[i + 0].fPos.set(dx * i, 0.0f);
  176. v[i + 0].fColor = color;
  177. v[i + 1].fPos.set(dx * i, 100.0f);
  178. v[i + 1].fColor = color;
  179. }
  180. } else {
  181. struct V {
  182. SkPoint fPos;
  183. GrColor fColor;
  184. };
  185. SkASSERT(sizeof(V) == vertexStride);
  186. V* v = (V*)verts;
  187. for (int i = 0; i < kVertexCount; i += 2) {
  188. v[i + 0].fPos.set(dx * i, 0.0f);
  189. v[i + 0].fColor = fColor;
  190. v[i + 1].fPos.set(dx * i, 100.0f);
  191. v[i + 1].fColor = fColor;
  192. }
  193. }
  194. GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangleStrip);
  195. mesh->setNonIndexedNonInstanced(kVertexCount);
  196. mesh->setVertexData(std::move(vertexBuffer), firstVertex);
  197. target->recordDraw(gp, mesh);
  198. }
  199. void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
  200. flushState->executeDrawsAndUploadsForMeshDrawOp(
  201. this, chainBounds, GrProcessorSet::MakeEmptySet());
  202. }
  203. Mode fMode;
  204. GrColor fColor;
  205. SkColor4f fColor4f;
  206. sk_sp<GrColorSpaceXform> fColorSpaceXform;
  207. typedef GrMeshDrawOp INHERITED;
  208. };
  209. }
  210. class VertexColorSpaceBench : public Benchmark {
  211. public:
  212. VertexColorSpaceBench(Mode mode, const char* name) : fMode(mode) {
  213. fName = "vertexcolorspace";
  214. fName.appendf("_%s", name);
  215. }
  216. bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; }
  217. const char* onGetName() override { return fName.c_str(); }
  218. void onDraw(int loops, SkCanvas* canvas) override {
  219. GrContext* context = canvas->getGrContext();
  220. SkASSERT(context);
  221. if (kHalf_Mode == fMode &&
  222. !context->priv().caps()->halfFloatVertexAttributeSupport()) {
  223. return;
  224. }
  225. GrOpMemoryPool* pool = context->priv().opMemoryPool();
  226. auto p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
  227. SkNamedGamut::kDCIP3);
  228. auto xform = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
  229. p3.get(), kUnpremul_SkAlphaType);
  230. SkRandom r;
  231. const int kDrawsPerLoop = 32;
  232. for (int i = 0; i < loops; ++i) {
  233. sk_sp<GrRenderTargetContext> rtc(context->priv().makeDeferredRenderTargetContext(
  234. SkBackingFit::kApprox, 100, 100, GrColorType::kRGBA_8888, p3));
  235. SkASSERT(rtc);
  236. for (int j = 0; j < kDrawsPerLoop; ++j) {
  237. SkColor c = r.nextU();
  238. std::unique_ptr<GrDrawOp> op = nullptr;
  239. switch (fMode) {
  240. case kBaseline_Mode:
  241. op = pool->allocate<Op>(SkColorToPremulGrColor(c));
  242. break;
  243. case kShader_Mode:
  244. op = pool->allocate<Op>(SkColorToUnpremulGrColor(c), xform);
  245. break;
  246. case kHalf_Mode:
  247. case kFloat_Mode: {
  248. SkColor4f c4f = SkColor4f::FromColor(c);
  249. c4f = xform->apply(c4f);
  250. op = pool->allocate<Op>(c4f, fMode);
  251. }
  252. }
  253. rtc->priv().testingOnly_addDrawOp(std::move(op));
  254. }
  255. context->flush();
  256. }
  257. }
  258. private:
  259. SkString fName;
  260. Mode fMode;
  261. typedef Benchmark INHERITED;
  262. };
  263. DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
  264. DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
  265. DEF_BENCH(return new VertexColorSpaceBench(kHalf_Mode, "half"));
  266. DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));