• 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 "include/private/SkSLProgramKind.h"
11 #include "src/base/SkArenaAlloc.h"
12 #include "src/core/SkRasterPipeline.h"
13 #include "src/sksl/SkSLCompiler.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/SkRPDebugTrace.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(SkSL::ShaderCapsFactory::Default());
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.append_constant_color(&alloc, startingColor);
54     SkSL::SkRPDebugTrace 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(SkSLRasterPipelineCodeGeneratorIfElseTest,r)106 DEF_TEST(SkSLRasterPipelineCodeGeneratorIfElseTest, r) {
107     // Add in your SkSL here.
108     test(r,
109          R"__SkSL__(
110              const half4 colorWhite = half4(1);
111 
112              half4 ifElseTest(half4 colorBlue, half4 colorGreen, half4 colorRed) {
113                  half4 result = half4(0);
114                  if (colorWhite != colorBlue) {    // TRUE
115                      if (colorGreen == colorRed) { // FALSE
116                          result = colorRed;
117                      } else {
118                          result = colorGreen;
119                      }
120                  } else {
121                      if (colorRed != colorGreen) { // TRUE, but in a false branch
122                          result = colorBlue;
123                      } else {                      // FALSE, and in a false branch
124                          result = colorWhite;
125                      }
126                  }
127                  if (colorRed == colorBlue) { // FALSE
128                      return colorWhite;
129                  }
130                  if (colorRed != colorGreen) { // TRUE
131                      return result;
132                  }
133                  if (colorRed == colorWhite) { // FALSE
134                      return colorBlue;
135                  }
136                  return colorRed;
137              }
138 
139              half4 main(half4) {
140                  return ifElseTest(colorWhite.00b1, colorWhite.0g01, colorWhite.r001);
141              }
142          )__SkSL__",
143          /*uniforms=*/{},
144          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
145          /*expectedResult=*/SkColor4f{0.0f, 1.0f, 0.0f, 1.0f});
146 }
147 
DEF_TEST(SkSLRasterPipelineCodeGeneratorTernaryTest,r)148 DEF_TEST(SkSLRasterPipelineCodeGeneratorTernaryTest, r) {
149     // Add in your SkSL here.
150     test(r,
151          R"__SkSL__(
152              half4 main(half4 colorWhite) {
153                  half4 colorBlue  = colorWhite.00ba,
154                        colorGreen = colorWhite.0g0a,
155                        colorRed   = colorWhite.r00a;
156                  // This ternary matches the initial if-else block inside IfElseTest.
157                  half4 result;
158                  result = (colorWhite != colorBlue)                              // TRUE
159                             ? (colorGreen == colorRed ? colorRed : colorGreen)   // FALSE
160                             : (colorRed != colorGreen ? colorBlue : colorWhite); // in false branch
161 
162                  // This ternary matches the second portion of IfElseTest.
163                  return colorRed == colorBlue  ? colorWhite :
164                         colorRed != colorGreen ? result :     // TRUE
165                         colorRed == colorWhite ? colorBlue :
166                                                  colorRed;
167              }
168          )__SkSL__",
169          /*uniforms=*/{},
170          /*startingColor=*/SkColor4f{1.0, 1.0, 1.0, 1.0},
171          /*expectedResult=*/SkColor4f{0.0f, 1.0f, 0.0f, 1.0f});
172 }
173 
DEF_TEST(SkSLRasterPipelineCodeGeneratorNestedTernaryTest,r)174 DEF_TEST(SkSLRasterPipelineCodeGeneratorNestedTernaryTest, r) {
175     // Add in your SkSL here.
176     test(r,
177          R"__SkSL__(
178              half4 main(half4) {
179                  half three = 3, one = 1, two = 2;
180                  half result = (three > (one > two ? 2.0 : 5.0)) ? 1.0 : 0.499;
181                  return half4(result);
182              }
183          )__SkSL__",
184          /*uniforms=*/{},
185          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
186          /*expectedResult=*/SkColor4f{0.499f, 0.499f, 0.499f, 0.499f});
187 }
188 
DEF_TEST(SkSLRasterPipelineCodeGeneratorArithmeticTest,r)189 DEF_TEST(SkSLRasterPipelineCodeGeneratorArithmeticTest, r) {
190     test(r,
191          R"__SkSL__(
192             half4 main(half4) {
193                 const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
194 
195                 half a = 3.0, b = 4.0, c = a + b - 2.0;
196                 if (a*a + b*b == c*c*c/5.0) {
197                     int A = 3, B = 4, C = A + B - 2;
198                     if (A*A + B*B == C*C*C/5) {
199                         return colorGreen;
200                     }
201                 }
202 
203                 return colorRed;
204             }
205          )__SkSL__",
206          /*uniforms=*/{},
207          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
208          /*expectedResult=*/SkColor4f{0.0f, 1.0f, 0.0f, 1.0f});
209 }
210 
DEF_TEST(SkSLRasterPipelineCodeGeneratorCoercedTypeTest,r)211 DEF_TEST(SkSLRasterPipelineCodeGeneratorCoercedTypeTest, r) {
212     static constexpr float kUniforms[] = {0.0, 1.0, 0.0, 1.0,
213                                           1.0, 0.0, 0.0, 1.0};
214     test(r,
215          R"__SkSL__(
216              uniform half4 colorGreen;
217              uniform float4 colorRed;
218              half4 main(half4 color) {
219                  return ((colorGreen + colorRed) == float4(1.0, 1.0, 0.0, 2.0)) ? colorGreen
220                                                                                 : colorGreen.gr01;
221              }
222          )__SkSL__",
223          kUniforms,
224          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
225          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
226 }
227 
DEF_TEST(SkSLRasterPipelineCodeGeneratorIdentitySwizzle,r)228 DEF_TEST(SkSLRasterPipelineCodeGeneratorIdentitySwizzle, r) {
229     static constexpr float kUniforms[] = {0.0, 1.0, 0.0, 1.0,
230                                           1.0, 0.0, 0.0, 1.0};
231     test(r,
232          R"__SkSL__(
233             uniform half4 colorGreen, colorRed;
234             half4 main(vec4 color) {
235                 return (color.r   == 0.5             &&
236                         color.rg  == half2(0.5, 1.0) &&
237                         color.rgb == half3(0.5, 1.0, 0.0)) ? colorGreen : colorRed;
238             }
239          )__SkSL__",
240          kUniforms,
241          /*startingColor=*/SkColor4f{0.5, 1.0, 0.0, 0.25},
242          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
243 
244 }
245 
DEF_TEST(SkSLRasterPipelineCodeGeneratorBitwiseNotTest,r)246 DEF_TEST(SkSLRasterPipelineCodeGeneratorBitwiseNotTest, r) {
247     static constexpr int32_t kUniforms[] = { 0,  12,  3456,  4567890,
248                                             ~0, ~12, ~3456, ~4567890};
249     test(r,
250          R"__SkSL__(
251             uniform int4 value, expected;
252             const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
253 
254             half4 main(vec4) {
255                 return (~value.x    == expected.x     &&
256                         ~value.xy   == expected.xy    &&
257                         ~value.xyz  == expected.xyz   &&
258                         ~value.xyzw == expected.xyzw) ? colorGreen : colorRed;
259             }
260          )__SkSL__",
261          SkSpan((const float*)kUniforms, std::size(kUniforms)),
262          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
263          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
264 }
265 
DEF_TEST(SkSLRasterPipelineCodeGeneratorComparisonIntrinsicTest,r)266 DEF_TEST(SkSLRasterPipelineCodeGeneratorComparisonIntrinsicTest, r) {
267     test(r,
268          R"__SkSL__(
269             half4 main(vec4) {
270                 const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
271                 half4 a = half4(1, 2, 0, 1),
272                       b = half4(2, 2, 1, 0);
273                 int3  c = int3(1111, 3333, 5555),
274                       d = int3(1111, 5555, 3333);
275                 uint2 e = uint2(1111111111u, 222),
276                       f = uint2(3333333333u, 222);
277                 return (lessThan(a, b)         == bool4(true, false, true, false)  &&
278                         lessThan(c, d)         == bool3(false, true, false)        &&
279                         lessThan(e, f)         == bool2(true, false)               &&
280                         greaterThan(a, b)      == bool4(false, false, false, true) &&
281                         greaterThan(c, d)      == bool3(false, false, true)        &&
282                         greaterThan(e, f)      == bool2(false, false)              &&
283                         lessThanEqual(a, b)    == bool4(true, true, true, false)   &&
284                         lessThanEqual(c, d)    == bool3(true, true, false)         &&
285                         lessThanEqual(e, f)    == bool2(true, true)                &&
286                         greaterThanEqual(a, b) == bool4(false, true, false, true)  &&
287                         greaterThanEqual(c, d) == bool3(true, false, true)         &&
288                         greaterThanEqual(e, f) == bool2(false, true)               &&
289                         equal(a, b)            == bool4(false, true, false, false) &&
290                         equal(c, d)            == bool3(true, false, false)        &&
291                         equal(e, f)            == bool2(false, true)               &&
292                         notEqual(a, b)         == bool4(true, false, true, true)   &&
293                         notEqual(c, d)         == bool3(false, true, true)         &&
294                         notEqual(e, f)         == bool2(true, false)               &&
295                         max(a, b)              == half4(2, 2, 1, 1)                &&
296                         max(c, d)              == int3(1111, 5555, 5555)           &&
297                         max(e, f)              == uint2(3333333333u, 222)          &&
298                         max(a, 1)              == half4(1, 2, 1, 1)                &&
299                         max(c, 3333)           == int3(3333, 3333, 5555)           &&
300                         max(e, 7777)           == uint2(1111111111u, 7777)         &&
301                         min(a, b)              == half4(1, 2, 0, 0)                &&
302                         min(c, d)              == int3(1111, 3333, 3333)           &&
303                         min(e, f)              == uint2(1111111111u, 222)          &&
304                         min(a, 1)              == half4(1, 1, 0, 1)                &&
305                         min(c, 3333)           == int3(1111, 3333, 3333)           &&
306                         min(e, 7777)           == uint2(7777, 222)) ? colorGreen : colorRed;
307             }
308          )__SkSL__",
309          /*uniforms=*/{},
310          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
311          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
312 }
313