• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 
8 #include "include/core/SkColor.h"
9 #include "include/core/SkTypes.h"
10 #include "src/base/SkArenaAlloc.h"
11 #include "src/core/SkRasterPipeline.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLProgramKind.h"
14 #include "src/sksl/SkSLProgramSettings.h"
15 #include "src/sksl/SkSLUtil.h"
16 #include "src/sksl/codegen/SkSLRasterPipelineBuilder.h"
17 #include "src/sksl/codegen/SkSLRasterPipelineCodeGenerator.h"
18 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
19 #include "src/sksl/ir/SkSLProgram.h"
20 #include "src/sksl/tracing/SkSLDebugTracePriv.h"
21 #include "tests/Test.h"
22 
23 #include <memory>
24 #include <optional>
25 #include <string>
26 
27 //#define DUMP_PROGRAMS 1
28 #if defined(DUMP_PROGRAMS)
29 #include "src/core/SkStreamPriv.h"
30 #endif
31 
test(skiatest::Reporter * r,const char * src,SkSpan<const float> uniforms,SkColor4f startingColor,std::optional<SkColor4f> expectedResult)32 static void test(skiatest::Reporter* r,
33                  const char* src,
34                  SkSpan<const float> uniforms,
35                  SkColor4f startingColor,
36                  std::optional<SkColor4f> expectedResult) {
37     SkSL::Compiler compiler;
38     SkSL::ProgramSettings settings;
39     settings.fMaxVersionAllowed = SkSL::Version::k300;
40     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
41             SkSL::ProgramKind::kRuntimeColorFilter, std::string(src), settings);
42     if (!program) {
43         ERRORF(r, "Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
44         return;
45     }
46     const SkSL::FunctionDeclaration* main = program->getFunction("main");
47     if (!main) {
48         ERRORF(r, "Program must have a 'main' function");
49         return;
50     }
51     SkArenaAlloc alloc(/*firstHeapAllocation=*/1000);
52     SkRasterPipeline pipeline(&alloc);
53     pipeline.appendConstantColor(&alloc, startingColor);
54     SkSL::DebugTracePriv debugTrace;
55     std::unique_ptr<SkSL::RP::Program> rasterProg =
56             SkSL::MakeRasterPipelineProgram(*program, *main->definition(), &debugTrace);
57     if (!rasterProg && !expectedResult.has_value()) {
58         // We didn't get a program, as expected. Test passes.
59         return;
60     }
61     if (!rasterProg && expectedResult.has_value()) {
62         ERRORF(r, "MakeRasterPipelineProgram failed");
63         return;
64     }
65     if (rasterProg && !expectedResult.has_value()) {
66         ERRORF(r, "MakeRasterPipelineProgram should have failed, but didn't");
67         return;
68     }
69 
70 #if defined(DUMP_PROGRAMS)
71     // Dump the program instructions via SkDebugf.
72     SkDebugf("-----\n\n");
73     SkDebugfStream stream;
74     rasterProg->dump(&stream);
75     SkDebugf("\n-----\n\n");
76 #endif
77 
78     // Append the SkSL program to the raster pipeline.
79     rasterProg->appendStages(&pipeline, &alloc, /*callbacks=*/nullptr, uniforms);
80 
81     // Move the float values from RGBA into an 8888 memory buffer.
82     uint32_t out[SkRasterPipeline_kMaxStride_highp] = {};
83     SkRasterPipeline_MemoryCtx outCtx{/*pixels=*/out, /*stride=*/SkRasterPipeline_kMaxStride_highp};
84     pipeline.append(SkRasterPipelineOp::store_8888, &outCtx);
85     pipeline.run(0, 0, 1, 1);
86 
87     // Make sure the first pixel (exclusively) of `out` matches RGBA.
88     uint32_t expected = expectedResult->toBytes_RGBA();
89     REPORTER_ASSERT(r, out[0] == expected,
90                     "Got:%02X%02X%02X%02X Expected:%02X%02X%02X%02X",
91                     (out[0] >> 24) & 0xFF,
92                     (out[0] >> 16) & 0xFF,
93                     (out[0] >> 8) & 0xFF,
94                     out[0] & 0xFF,
95                     (expected >> 24) & 0xFF,
96                     (expected >> 16) & 0xFF,
97                     (expected >> 8) & 0xFF,
98                     expected & 0xFF);
99 
100     // Make sure the rest of the pixels are untouched.
101     for (size_t i = 1; i < std::size(out); ++i) {
102         REPORTER_ASSERT(r, out[i] == 0);
103     }
104 }
105 
DEF_TEST(SkSLRasterPipelineCodeGeneratorNestedTernaryTest,r)106 DEF_TEST(SkSLRasterPipelineCodeGeneratorNestedTernaryTest, r) {
107     // Add in your SkSL here.
108     test(r,
109          R"__SkSL__(
110              half4 main(half4) {
111                  half three = 3, one = 1, two = 2;
112                  half result = (three > (one > two ? 2.0 : 5.0)) ? 1.0 : 0.499;
113                  return half4(result);
114              }
115          )__SkSL__",
116          /*uniforms=*/{},
117          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
118          /*expectedResult=*/SkColor4f{0.499f, 0.499f, 0.499f, 0.499f});
119 }
120 
DEF_TEST(SkSLRasterPipelineCodeGeneratorArithmeticTest,r)121 DEF_TEST(SkSLRasterPipelineCodeGeneratorArithmeticTest, r) {
122     test(r,
123          R"__SkSL__(
124             half4 main(half4) {
125                 const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
126 
127                 half a = 3.0, b = 4.0, c = a + b - 2.0;
128                 if (a*a + b*b == c*c*c/5.0) {
129                     int A = 3, B = 4, C = A + B - 2;
130                     if (A*A + B*B == C*C*C/5) {
131                         return colorGreen;
132                     }
133                 }
134 
135                 return colorRed;
136             }
137          )__SkSL__",
138          /*uniforms=*/{},
139          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
140          /*expectedResult=*/SkColor4f{0.0f, 1.0f, 0.0f, 1.0f});
141 }
142 
DEF_TEST(SkSLRasterPipelineCodeGeneratorCoercedTypeTest,r)143 DEF_TEST(SkSLRasterPipelineCodeGeneratorCoercedTypeTest, r) {
144     static constexpr float kUniforms[] = {0.0, 1.0, 0.0, 1.0,
145                                           1.0, 0.0, 0.0, 1.0};
146     test(r,
147          R"__SkSL__(
148              uniform half4 colorGreen;
149              uniform float4 colorRed;
150              half4 main(half4 color) {
151                  return ((colorGreen + colorRed) == float4(1.0, 1.0, 0.0, 2.0)) ? colorGreen
152                                                                                 : colorGreen.gr01;
153              }
154          )__SkSL__",
155          kUniforms,
156          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
157          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
158 }
159 
DEF_TEST(SkSLRasterPipelineCodeGeneratorIdentitySwizzle,r)160 DEF_TEST(SkSLRasterPipelineCodeGeneratorIdentitySwizzle, r) {
161     static constexpr float kUniforms[] = {0.0, 1.0, 0.0, 1.0,
162                                           1.0, 0.0, 0.0, 1.0};
163     test(r,
164          R"__SkSL__(
165 
166 uniform half4 colorGreen, colorRed;
167 
168 const int SEVEN = 7, TEN = 10;
169 const half4x4 MATRIXFIVE = half4x4(5);
170 
171 noinline bool verify_const_globals(int seven, int ten, half4x4 matrixFive) {
172     return seven == 7 && ten == 10 && matrixFive == half4x4(5);
173 }
174 
175 half4 main(float4) {
176     return verify_const_globals(SEVEN, TEN, MATRIXFIVE) ? colorGreen : colorRed;
177 }
178 
179          )__SkSL__",
180          kUniforms,
181          /*startingColor=*/SkColor4f{0.5, 1.0, 0.0, 0.25},
182          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
183 
184 }
185 
DEF_TEST(SkSLRasterPipelineCodeGeneratorBitwiseNotTest,r)186 DEF_TEST(SkSLRasterPipelineCodeGeneratorBitwiseNotTest, r) {
187     static constexpr int32_t kUniforms[] = { 0,  12,  3456,  4567890,
188                                             ~0, ~12, ~3456, ~4567890};
189     test(r,
190          R"__SkSL__(
191             uniform int4 value, expected;
192             const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
193 
194             half4 main(vec4) {
195                 return (~value.x    == expected.x     &&
196                         ~value.xy   == expected.xy    &&
197                         ~value.xyz  == expected.xyz   &&
198                         ~value.xyzw == expected.xyzw) ? colorGreen : colorRed;
199             }
200          )__SkSL__",
201          SkSpan((const float*)kUniforms, std::size(kUniforms)),
202          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
203          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
204 }
205 
DEF_TEST(SkSLRasterPipelineCodeGeneratorComparisonIntrinsicTest,r)206 DEF_TEST(SkSLRasterPipelineCodeGeneratorComparisonIntrinsicTest, r) {
207     test(r,
208          R"__SkSL__(
209             half4 main(vec4) {
210                 const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
211                 half4 a = half4(1, 2, 0, 1),
212                       b = half4(2, 2, 1, 0);
213                 int3  c = int3(1111, 3333, 5555),
214                       d = int3(1111, 5555, 3333);
215                 uint2 e = uint2(1111111111u, 222),
216                       f = uint2(3333333333u, 222);
217                 return (lessThan(a, b)         == bool4(true, false, true, false)  &&
218                         lessThan(c, d)         == bool3(false, true, false)        &&
219                         lessThan(e, f)         == bool2(true, false)               &&
220                         greaterThan(a, b)      == bool4(false, false, false, true) &&
221                         greaterThan(c, d)      == bool3(false, false, true)        &&
222                         greaterThan(e, f)      == bool2(false, false)              &&
223                         lessThanEqual(a, b)    == bool4(true, true, true, false)   &&
224                         lessThanEqual(c, d)    == bool3(true, true, false)         &&
225                         lessThanEqual(e, f)    == bool2(true, true)                &&
226                         greaterThanEqual(a, b) == bool4(false, true, false, true)  &&
227                         greaterThanEqual(c, d) == bool3(true, false, true)         &&
228                         greaterThanEqual(e, f) == bool2(false, true)               &&
229                         equal(a, b)            == bool4(false, true, false, false) &&
230                         equal(c, d)            == bool3(true, false, false)        &&
231                         equal(e, f)            == bool2(false, true)               &&
232                         notEqual(a, b)         == bool4(true, false, true, true)   &&
233                         notEqual(c, d)         == bool3(false, true, true)         &&
234                         notEqual(e, f)         == bool2(true, false)               &&
235                         max(a, b)              == half4(2, 2, 1, 1)                &&
236                         max(c, d)              == int3(1111, 5555, 5555)           &&
237                         max(e, f)              == uint2(3333333333u, 222)          &&
238                         max(a, 1)              == half4(1, 2, 1, 1)                &&
239                         max(c, 3333)           == int3(3333, 3333, 5555)           &&
240                         max(e, 7777)           == uint2(1111111111u, 7777)         &&
241                         min(a, b)              == half4(1, 2, 0, 0)                &&
242                         min(c, d)              == int3(1111, 3333, 3333)           &&
243                         min(e, f)              == uint2(1111111111u, 222)          &&
244                         min(a, 1)              == half4(1, 1, 0, 1)                &&
245                         min(c, 3333)           == int3(1111, 3333, 3333)           &&
246                         min(e, 7777)           == uint2(7777, 222)) ? colorGreen : colorRed;
247             }
248          )__SkSL__",
249          /*uniforms=*/{},
250          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
251          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
252 }
253