| Ethan Nicholas | 40679c3 | 2019-05-31 17:06:53 -0400 | [diff] [blame] | 1 | /* |
| Ethan Nicholas | fc99416 | 2019-06-06 10:04:27 -0400 | [diff] [blame] | 2 | * Copyright 2019 Google LLC |
| Ethan Nicholas | 40679c3 | 2019-05-31 17:06:53 -0400 | [diff] [blame] | 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" |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 8 | #include "bench/ResultsWriter.h" |
| 9 | #include "bench/SkSLBench.h" |
| Ethan Nicholas | 40679c3 | 2019-05-31 17:06:53 -0400 | [diff] [blame] | 10 | #include "src/sksl/SkSLCompiler.h" |
| 11 | |
| 12 | class SkSLBench : public Benchmark { |
| 13 | public: |
| 14 | SkSLBench(SkSL::String name, const char* src) |
| 15 | : fName("sksl_" + name) |
| 16 | , fSrc(src) {} |
| 17 | |
| 18 | protected: |
| 19 | const char* onGetName() override { |
| 20 | return fName.c_str(); |
| 21 | } |
| 22 | |
| 23 | bool isSuitableFor(Backend backend) override { |
| 24 | return backend == kNonRendering_Backend; |
| 25 | } |
| 26 | |
| 27 | void onDraw(int loops, SkCanvas*) override { |
| 28 | for (int i = 0; i < loops; i++) { |
| 29 | std::unique_ptr<SkSL::Program> program = fCompiler.convertProgram( |
| 30 | SkSL::Program::kFragment_Kind, |
| 31 | fSrc, |
| 32 | fSettings); |
| 33 | if (!fCompiler.errorCount()) { |
| 34 | fCompiler.optimize(*program); |
| 35 | } else { |
| 36 | printf("%s\n", fCompiler.errorText().c_str()); |
| 37 | SK_ABORT("shader compilation failed"); |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | private: |
| 43 | SkSL::String fName; |
| 44 | SkSL::String fSrc; |
| 45 | SkSL::Compiler fCompiler; |
| 46 | SkSL::Program::Settings fSettings; |
| 47 | |
| 48 | typedef Benchmark INHERITED; |
| 49 | }; |
| 50 | |
| 51 | /////////////////////////////////////////////////////////////////////////////// |
| 52 | |
| 53 | DEF_BENCH(return new SkSLBench("tiny", "void main() { sk_FragColor = half4(1); }"); ) |
| 54 | DEF_BENCH(return new SkSLBench("huge", R"( |
| 55 | uniform half2 uDstTextureUpperLeft_Stage1; |
| 56 | uniform half2 uDstTextureCoordScale_Stage1; |
| 57 | uniform sampler2D uDstTextureSampler_Stage1; |
| 58 | noperspective in half4 vQuadEdge_Stage0; |
| 59 | noperspective in half4 vinColor_Stage0; |
| 60 | out half4 sk_FragColor; |
| 61 | half luminance_Stage1(half3 color) { |
| 62 | return dot(half3(0.3, 0.59, 0.11), color); |
| 63 | } |
| 64 | |
| 65 | half3 set_luminance_Stage1(half3 hueSat, half alpha, half3 lumColor) { |
| 66 | half diff = luminance_Stage1(lumColor - hueSat); |
| 67 | half3 outColor = hueSat + diff; |
| 68 | half outLum = luminance_Stage1(outColor); |
| 69 | half minComp = min(min(outColor.r, outColor.g), outColor.b); |
| 70 | half maxComp = max(max(outColor.r, outColor.g), outColor.b); |
| 71 | if (minComp < 0.0 && outLum != minComp) { |
| 72 | outColor = outLum + ((outColor - half3(outLum, outLum, outLum)) * outLum) / |
| 73 | (outLum - minComp); |
| 74 | } |
| 75 | if (maxComp > alpha && maxComp != outLum) { |
| 76 | outColor = outLum +((outColor - half3(outLum, outLum, outLum)) * (alpha - outLum)) / |
| 77 | (maxComp - outLum); |
| 78 | } |
| 79 | return outColor; |
| 80 | } |
| 81 | |
| 82 | void main() { |
| 83 | half4 outputColor_Stage0; |
| 84 | half4 outputCoverage_Stage0; |
| 85 | { // Stage 0, QuadEdge |
| 86 | outputColor_Stage0 = vinColor_Stage0; |
| 87 | half edgeAlpha; |
| 88 | half2 duvdx = half2(dFdx(vQuadEdge_Stage0.xy)); |
| 89 | half2 duvdy = half2(dFdy(vQuadEdge_Stage0.xy)); |
| 90 | if (vQuadEdge_Stage0.z > 0.0 && vQuadEdge_Stage0.w > 0.0) { |
| 91 | edgeAlpha = min(min(vQuadEdge_Stage0.z, vQuadEdge_Stage0.w) + 0.5, 1.0); |
| 92 | } else { |
| 93 | half2 gF = half2(2.0 * vQuadEdge_Stage0.x * duvdx.x - duvdx.y, |
| 94 | 2.0 * vQuadEdge_Stage0.x * duvdy.x - duvdy.y); |
| 95 | edgeAlpha = (vQuadEdge_Stage0.x*vQuadEdge_Stage0.x - vQuadEdge_Stage0.y); |
| 96 | edgeAlpha = saturate(0.5 - edgeAlpha / length(gF)); |
| 97 | } |
| 98 | outputCoverage_Stage0 = half4(edgeAlpha); |
| 99 | } |
| 100 | { // Xfer Processor: Custom Xfermode |
| 101 | if (all(lessThanEqual(outputCoverage_Stage0.rgb, half3(0)))) { |
| 102 | discard; |
| 103 | } |
| 104 | // Read color from copy of the destination. |
| 105 | half2 _dstTexCoord = (half2(sk_FragCoord.xy) - uDstTextureUpperLeft_Stage1) * |
| 106 | uDstTextureCoordScale_Stage1; |
| 107 | _dstTexCoord.y = 1.0 - _dstTexCoord.y; |
| Ethan Nicholas | 1386366 | 2019-07-29 13:05:15 -0400 | [diff] [blame] | 108 | half4 _dstColor = sample(uDstTextureSampler_Stage1, _dstTexCoord); |
| Ethan Nicholas | 40679c3 | 2019-05-31 17:06:53 -0400 | [diff] [blame] | 109 | sk_FragColor.a = outputColor_Stage0.a + (1.0 - outputColor_Stage0.a) * _dstColor.a; |
| 110 | half4 srcDstAlpha = outputColor_Stage0 * _dstColor.a; |
| 111 | sk_FragColor.rgb = set_luminance_Stage1(_dstColor.rgb * outputColor_Stage0.a, |
| 112 | srcDstAlpha.a, srcDstAlpha.rgb); |
| 113 | sk_FragColor.rgb += (1.0 - outputColor_Stage0.a) * _dstColor.rgb + (1.0 - _dstColor.a) * |
| 114 | outputColor_Stage0.rgb; |
| 115 | sk_FragColor = outputCoverage_Stage0 * sk_FragColor + |
| 116 | (half4(1.0) - outputCoverage_Stage0) * _dstColor; |
| 117 | } |
| 118 | } |
| 119 | )"); ) |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 120 | |
| Brian Osman | 24b8a8c | 2020-07-09 10:04:33 -0400 | [diff] [blame] | 121 | #if defined(SK_BUILD_FOR_UNIX) |
| 122 | |
| 123 | #include <malloc.h> |
| 124 | |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 125 | // These benchmarks aren't timed, they produce memory usage statistics. They run standalone, and |
| 126 | // directly add their results to the nanobench log. |
| 127 | void RunSkSLMemoryBenchmarks(NanoJSONResultsWriter* log) { |
| Brian Osman | 24b8a8c | 2020-07-09 10:04:33 -0400 | [diff] [blame] | 128 | auto heap_bytes_used = []() { return mallinfo().uordblks; }; |
| 129 | auto bench = [log](const char* name, int bytes) { |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 130 | log->beginObject(name); // test |
| 131 | log->beginObject("meta"); // config |
| Brian Osman | 24b8a8c | 2020-07-09 10:04:33 -0400 | [diff] [blame] | 132 | log->appendS32("bytes", bytes); // sub_result |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 133 | log->endObject(); // config |
| 134 | log->endObject(); // test |
| 135 | }; |
| 136 | |
| 137 | { |
| Brian Osman | 24b8a8c | 2020-07-09 10:04:33 -0400 | [diff] [blame] | 138 | int before = heap_bytes_used(); |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 139 | SkSL::Compiler compiler; |
| Brian Osman | 24b8a8c | 2020-07-09 10:04:33 -0400 | [diff] [blame] | 140 | int after = heap_bytes_used(); |
| 141 | bench("sksl_compiler_baseline", after - before); |
| Brian Osman | 68870aa | 2020-07-08 14:12:43 -0400 | [diff] [blame] | 142 | } |
| 143 | } |
| Brian Osman | 24b8a8c | 2020-07-09 10:04:33 -0400 | [diff] [blame] | 144 | |
| 145 | #else |
| 146 | |
| 147 | void RunSkSLMemoryBenchmarks(NanoJSONResultsWriter*) {} |
| 148 | |
| 149 | #endif |