SkSLInterpreterBench.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright 2019 Google LLC
  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/utils/SkRandom.h"
  9. #include "src/sksl/SkSLByteCode.h"
  10. #include "src/sksl/SkSLCompiler.h"
  11. // Benchmarks the interpreter with a function that has a color-filter style signature
  12. class SkSLInterpreterCFBench : public Benchmark {
  13. public:
  14. SkSLInterpreterCFBench(SkSL::String name, int pixels, bool striped, const char* src)
  15. : fName(SkStringPrintf("sksl_interp_cf_%d_%d_%s", pixels, striped ? 1 : 0, name.c_str()))
  16. , fSrc(src)
  17. , fCount(pixels)
  18. , fStriped(striped) {}
  19. protected:
  20. const char* onGetName() override {
  21. return fName.c_str();
  22. }
  23. bool isSuitableFor(Backend backend) override {
  24. return backend == kNonRendering_Backend;
  25. }
  26. void onDelayedSetup() override {
  27. SkSL::Compiler compiler;
  28. SkSL::Program::Settings settings;
  29. auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind, fSrc, settings);
  30. SkASSERT(compiler.errorCount() == 0);
  31. fByteCode = compiler.toByteCode(*program);
  32. SkASSERT(compiler.errorCount() == 0);
  33. fMain = fByteCode->getFunction("main");
  34. SkRandom rnd;
  35. fPixels.resize(fCount * 4);
  36. for (float& c : fPixels) {
  37. c = rnd.nextF();
  38. }
  39. }
  40. void onDraw(int loops, SkCanvas*) override {
  41. for (int i = 0; i < loops; i++) {
  42. if (fStriped) {
  43. float* args[] = {
  44. fPixels.data() + 0 * fCount,
  45. fPixels.data() + 1 * fCount,
  46. fPixels.data() + 2 * fCount,
  47. fPixels.data() + 3 * fCount,
  48. };
  49. SkAssertResult(fByteCode->runStriped(fMain, args, 4, fCount,
  50. nullptr, 0, nullptr, 0));
  51. } else {
  52. SkAssertResult(fByteCode->run(fMain, fPixels.data(), nullptr, fCount, nullptr, 0));
  53. }
  54. }
  55. }
  56. private:
  57. SkString fName;
  58. SkSL::String fSrc;
  59. std::unique_ptr<SkSL::ByteCode> fByteCode;
  60. const SkSL::ByteCodeFunction* fMain;
  61. int fCount;
  62. bool fStriped;
  63. std::vector<float> fPixels;
  64. typedef Benchmark INHERITED;
  65. };
  66. ///////////////////////////////////////////////////////////////////////////////
  67. const char* kLumaToAlphaSrc = R"(
  68. void main(inout float4 color) {
  69. color.a = color.r*0.3 + color.g*0.6 + color.b*0.1;
  70. color.r = 0;
  71. color.g = 0;
  72. color.b = 0;
  73. }
  74. )";
  75. const char* kHighContrastFilterSrc = R"(
  76. half ucontrast_Stage2;
  77. half hue2rgb_Stage2(half p, half q, half t) {
  78. if (t < 0) t += 1;
  79. if (t > 1) t -= 1;
  80. return (t < 1 / 6.) ? p + (q - p) * 6 * t
  81. : (t < 1 / 2.) ? q
  82. : (t < 2 / 3.) ? p + (q - p) * (2 / 3. - t) * 6
  83. : p;
  84. }
  85. half max(half a, half b) { return a > b ? a : b; }
  86. half min(half a, half b) { return a < b ? a : b; }
  87. void main(inout half4 color) {
  88. ucontrast_Stage2 = 0.2;
  89. // HighContrastFilter
  90. half nonZeroAlpha = max(color.a, 0.0001);
  91. color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);
  92. color.rgb = color.rgb * color.rgb;
  93. half fmax = max(color.r, max(color.g, color.b));
  94. half fmin = min(color.r, min(color.g, color.b));
  95. half l = (fmax + fmin) / 2;
  96. half h;
  97. half s;
  98. if (fmax == fmin) {
  99. h = 0;
  100. s = 0;
  101. } else {
  102. half d = fmax - fmin;
  103. s = l > 0.5 ? d / (2 - fmax - fmin) : d / (fmax + fmin);
  104. if (color.r >= color.g && color.r >= color.b) {
  105. h = (color.g - color.b) / d + (color.g < color.b ? 6 : 0);
  106. } else if (color.g >= color.b) {
  107. h = (color.b - color.r) / d + 2;
  108. } else {
  109. h = (color.r - color.g) / d + 4;
  110. }
  111. }
  112. h /= 6;
  113. l = 1.0 - l;
  114. if (s == 0) {
  115. color = half4(l, l, l, 0);
  116. } else {
  117. half q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  118. half p = 2 * l - q;
  119. color.r = hue2rgb_Stage2(p, q, h + 1 / 3.);
  120. color.g = hue2rgb_Stage2(p, q, h);
  121. color.b = hue2rgb_Stage2(p, q, h - 1 / 3.);
  122. }
  123. if (ucontrast_Stage2 != 0) {
  124. half m = (1 + ucontrast_Stage2) / (1 - ucontrast_Stage2);
  125. half off = (-0.5 * m + 0.5);
  126. color = m * color + off;
  127. }
  128. // color = saturate(color);
  129. color.rgb = sqrt(color.rgb);
  130. color.rgb *= color.a;
  131. }
  132. )";
  133. DEF_BENCH(return new SkSLInterpreterCFBench("lumaToAlpha", 256, false, kLumaToAlphaSrc));
  134. DEF_BENCH(return new SkSLInterpreterCFBench("lumaToAlpha", 256, true, kLumaToAlphaSrc));
  135. DEF_BENCH(return new SkSLInterpreterCFBench("hcf", 256, false, kHighContrastFilterSrc));
  136. DEF_BENCH(return new SkSLInterpreterCFBench("hcf", 256, true, kHighContrastFilterSrc));
  137. class SkSLInterpreterSortBench : public Benchmark {
  138. public:
  139. SkSLInterpreterSortBench(int groups, int values, const char* src)
  140. : fName(SkStringPrintf("sksl_interp_sort_%dx%d", groups, values))
  141. , fCode(src)
  142. , fGroups(groups)
  143. , fValues(values) {
  144. }
  145. protected:
  146. const char* onGetName() override {
  147. return fName.c_str();
  148. }
  149. bool isSuitableFor(Backend backend) override {
  150. return backend == kNonRendering_Backend;
  151. }
  152. void onDelayedSetup() override {
  153. SkSL::Compiler compiler;
  154. SkSL::Program::Settings settings;
  155. auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind, fCode, settings);
  156. SkASSERT(compiler.errorCount() == 0);
  157. fByteCode = compiler.toByteCode(*program);
  158. SkASSERT(compiler.errorCount() == 0);
  159. fMain = fByteCode->getFunction("main");
  160. fSrc.resize(fGroups * fValues);
  161. fDst.resize(fGroups * fValues);
  162. SkRandom rnd;
  163. for (float& x : fSrc) {
  164. x = rnd.nextF();
  165. }
  166. // Trigger one run now to check correctness
  167. SkAssertResult(fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0));
  168. for (int i = 0; i < fGroups; ++i) {
  169. for (int j = 1; j < fValues; ++j) {
  170. SkASSERT(fDst[i * fValues + j] >= fDst[i * fValues + j - 1]);
  171. }
  172. }
  173. }
  174. void onDraw(int loops, SkCanvas*) override {
  175. for (int i = 0; i < loops; i++) {
  176. SkAssertResult(fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0));
  177. }
  178. }
  179. private:
  180. SkString fName;
  181. SkSL::String fCode;
  182. std::unique_ptr<SkSL::ByteCode> fByteCode;
  183. const SkSL::ByteCodeFunction* fMain;
  184. int fGroups;
  185. int fValues;
  186. std::vector<float> fSrc;
  187. std::vector<float> fDst;
  188. typedef Benchmark INHERITED;
  189. };
  190. // Currently, this exceeds the interpreter's stack. Consider it a test case for some eventual
  191. // bounds checking.
  192. #if 0
  193. DEF_BENCH(return new SkSLInterpreterSortBench(1024, 32, R"(
  194. float[32] main(float v[32]) {
  195. for (int i = 1; i < 32; ++i) {
  196. for (int j = i; j > 0 && v[j-1] > v[j]; --j) {
  197. float t = v[j];
  198. v[j] = v[j-1];
  199. v[j-1] = t;
  200. }
  201. }
  202. return v;
  203. }
  204. )"));
  205. #endif