blob: b88dfdd7de78aded4efaf356b2d06a279bfc79f0 [file] [log] [blame]
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001/*
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
Ethan Nicholasae9633b2019-05-24 12:46:34 -04008#include "include/core/SkPoint3.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "src/sksl/SkSLCompiler.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040010#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/sksl/SkSLInterpreter.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040012#include "src/utils/SkJSON.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040013
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "tests/Test.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040015
Ethan Nicholas746035a2019-04-23 13:31:09 -040016void test(skiatest::Reporter* r, const char* src, SkSL::Interpreter::Value* in, int expectedCount,
17 SkSL::Interpreter::Value* expected) {
18 SkSL::Compiler compiler;
19 SkSL::Program::Settings settings;
20 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
21 SkSL::Program::kGeneric_Kind,
22 SkSL::String(src), settings);
23 REPORTER_ASSERT(r, program);
24 if (program) {
25 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
26 REPORTER_ASSERT(r, !compiler.errorCount());
27 if (compiler.errorCount() > 0) {
28 printf("%s\n%s", src, compiler.errorText().c_str());
29 return;
30 }
31 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
32 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
Ethan Nicholas444aa122019-05-07 14:02:41 -040033 std::unique_ptr<SkSL::Interpreter::Value[]> out =
34 std::unique_ptr<SkSL::Interpreter::Value[]>(new SkSL::Interpreter::Value[expectedCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040035 interpreter.run(*main, in, out.get());
36 bool valid = !memcmp(out.get(), expected, sizeof(SkSL::Interpreter::Value) * expectedCount);
Ethan Nicholas746035a2019-04-23 13:31:09 -040037 if (!valid) {
38 printf("for program: %s\n", src);
39 printf(" expected (");
40 const char* separator = "";
41 for (int i = 0; i < expectedCount; ++i) {
42 printf("%s%f", separator, expected[i].fFloat);
43 separator = ", ";
44 }
45 printf("), but received (");
46 separator = "";
47 for (int i = 0; i < expectedCount; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040048 printf("%s%f", separator, out.get()[i].fFloat);
Ethan Nicholas746035a2019-04-23 13:31:09 -040049 separator = ", ";
50 }
51 printf(")\n");
52 }
53 REPORTER_ASSERT(r, valid);
54 } else {
55 printf("%s\n%s", src, compiler.errorText().c_str());
56 }
57}
58
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059void test(skiatest::Reporter* r, const char* src, float inR, float inG, float inB, float inA,
60 float expectedR, float expectedG, float expectedB, float expectedA) {
61 SkSL::Compiler compiler;
62 SkSL::Program::Settings settings;
63 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
Ethan Nicholas746035a2019-04-23 13:31:09 -040064 SkSL::Program::kGeneric_Kind,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040065 SkSL::String(src), settings);
66 REPORTER_ASSERT(r, program);
67 if (program) {
68 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
69 REPORTER_ASSERT(r, !compiler.errorCount());
70 if (compiler.errorCount() > 0) {
71 printf("%s\n%s", src, compiler.errorText().c_str());
72 return;
73 }
74 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
75 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
76 float inoutColor[4] = { inR, inG, inB, inA };
77 interpreter.run(*main, (SkSL::Interpreter::Value*) inoutColor, nullptr);
78 if (inoutColor[0] != expectedR || inoutColor[1] != expectedG ||
79 inoutColor[2] != expectedB || inoutColor[3] != expectedA) {
80 printf("for program: %s\n", src);
81 printf(" expected (%f, %f, %f, %f), but received (%f, %f, %f, %f)\n", expectedR,
82 expectedG, expectedB, expectedA, inoutColor[0], inoutColor[1], inoutColor[2],
83 inoutColor[3]);
Mike Kleinb6a6f082019-05-17 14:56:39 -050084 interpreter.disassemble(*main);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040085 }
86 REPORTER_ASSERT(r, inoutColor[0] == expectedR);
87 REPORTER_ASSERT(r, inoutColor[1] == expectedG);
88 REPORTER_ASSERT(r, inoutColor[2] == expectedB);
89 REPORTER_ASSERT(r, inoutColor[3] == expectedA);
90 } else {
91 printf("%s\n%s", src, compiler.errorText().c_str());
92 }
93}
94
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040095DEF_TEST(SkSLInterpreterAdd, r) {
96 test(r, "void main(inout half4 color) { color.r = color.r + color.g; }", 0.25, 0.75, 0, 0, 1,
97 0.75, 0, 0);
98 test(r, "void main(inout half4 color) { color += half4(1, 2, 3, 4); }", 4, 3, 2, 1, 5, 5, 5, 5);
99 test(r, "void main(inout half4 color) { half4 c = color; color += c; }", 0.25, 0.5, 0.75, 1,
100 0.5, 1, 1.5, 2);
101 test(r, "void main(inout half4 color) { int a = 1; int b = 3; color.r = a + b; }", 1, 2, 3, 4,
102 4, 2, 3, 4);
103}
104
105DEF_TEST(SkSLInterpreterSubtract, r) {
106 test(r, "void main(inout half4 color) { color.r = color.r - color.g; }", 1, 0.75, 0, 0, 0.25,
107 0.75, 0, 0);
108 test(r, "void main(inout half4 color) { color -= half4(1, 2, 3, 4); }", 5, 5, 5, 5, 4, 3, 2, 1);
109 test(r, "void main(inout half4 color) { half4 c = color; color -= c; }", 4, 3, 2, 1,
110 0, 0, 0, 0);
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400111 test(r, "void main(inout half4 color) { color.x = -color.x; }", 4, 3, 2, 1, -4, 3, 2, 1);
112 test(r, "void main(inout half4 color) { color = -color; }", 4, 3, 2, 1, -4, -3, -2, -1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400113 test(r, "void main(inout half4 color) { int a = 3; int b = 1; color.r = a - b; }", 0, 0, 0, 0,
114 2, 0, 0, 0);
115}
116
117DEF_TEST(SkSLInterpreterMultiply, r) {
118 test(r, "void main(inout half4 color) { color.r = color.r * color.g; }", 2, 3, 0, 0, 6, 3, 0,
119 0);
120 test(r, "void main(inout half4 color) { color *= half4(1, 2, 3, 4); }", 2, 3, 4, 5, 2, 6, 12,
121 20);
122 test(r, "void main(inout half4 color) { half4 c = color; color *= c; }", 4, 3, 2, 1,
123 16, 9, 4, 1);
124 test(r, "void main(inout half4 color) { int a = 3; int b = -2; color.r = a * b; }", 0, 0, 0, 0,
125 -6, 0, 0, 0);
126}
127
128DEF_TEST(SkSLInterpreterDivide, r) {
129 test(r, "void main(inout half4 color) { color.r = color.r / color.g; }", 1, 2, 0, 0, 0.5, 2, 0,
130 0);
131 test(r, "void main(inout half4 color) { color /= half4(1, 2, 3, 4); }", 12, 12, 12, 12, 12, 6,
132 4, 3);
133 test(r, "void main(inout half4 color) { half4 c = color; color /= c; }", 4, 3, 2, 1,
134 1, 1, 1, 1);
135 test(r, "void main(inout half4 color) { int a = 8; int b = -2; color.r = a / b; }", 0, 0, 0, 0,
136 -4, 0, 0, 0);
137}
138
139DEF_TEST(SkSLInterpreterRemainder, r) {
Brian Osman3b41baf2019-05-08 09:24:46 -0400140 test(r, "void main(inout half4 color) { color.r = color.r % color.g; }", 3.125, 2, 0, 0,
141 1.125, 2, 0, 0);
142 test(r, "void main(inout half4 color) { color %= half4(1, 2, 3, 4); }", 9.5, 9.5, 9.5, 9.5,
143 0.5, 1.5, 0.5, 1.5);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400144 test(r, "void main(inout half4 color) { int a = 8; int b = 3; a %= b; color.r = a; }", 0, 0, 0,
145 0, 2, 0, 0, 0);
146 test(r, "void main(inout half4 color) { int a = 8; int b = 3; color.r = a % b; }", 0, 0, 0, 0,
147 2, 0, 0, 0);
148 test(r, "void main(inout half4 color) { int2 a = int2(8, 10); a %= 6; color.rg = a; }", 0, 0, 0,
149 0, 2, 4, 0, 0);
150}
151
Brian Osman4e93feb2019-05-16 15:38:00 -0400152DEF_TEST(SkSLInterpreterTernary, r) {
153 test(r, "void main(inout half4 color) { color.r = color.g > color.b ? color.g : color.b; }",
154 0, 1, 2, 0, 2, 1, 2, 0);
155 test(r, "void main(inout half4 color) { color.r = color.g > color.b ? color.g : color.b; }",
156 0, 3, 2, 0, 3, 3, 2, 0);
157}
158
Brian Osman41672152019-05-14 13:37:30 -0400159DEF_TEST(SkSLInterpreterCast, r) {
160 SkSL::Interpreter::Value input[2];
161 SkSL::Interpreter::Value expected[2];
162
163 input[0].fSigned = 3;
164 input[1].fSigned = -5;
165 expected[0].fFloat = 3.0f;
166 expected[1].fFloat = -5.0f;
167 test(r, "float main(int x) { return float (x); }", input, 1, expected);
168 test(r, "float2 main(int2 x) { return float2(x); }", input, 2, expected);
169
170 input[0].fUnsigned = 3;
171 input[1].fUnsigned = 5;
172 expected[0].fFloat = 3.0f;
173 expected[1].fFloat = 5.0f;
174 test(r, "float main(uint x) { return float (x); }", input, 1, expected);
175 test(r, "float2 main(uint2 x) { return float2(x); }", input, 2, expected);
176
177 input[0].fFloat = 3.0f;
178 input[1].fFloat = -5.0f;
179 expected[0].fSigned = 3;
180 expected[1].fSigned = -5;
181 test(r, "int main(float x) { return int (x); }", input, 1, expected);
182 test(r, "int2 main(float2 x) { return int2(x); }", input, 2, expected);
Brian Osmanc51d7912019-05-22 15:16:16 -0700183
184 input[0].fSigned = 3;
185 expected[0].fFloat = 3.0f;
186 expected[1].fFloat = 3.0f;
187 test(r, "float2 main(int x) { return float2(x); }", input, 2, expected);
Brian Osman41672152019-05-14 13:37:30 -0400188}
189
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190DEF_TEST(SkSLInterpreterIf, r) {
191 test(r, "void main(inout half4 color) { if (color.r > color.g) color.a = 1; }", 5, 3, 0, 0,
192 5, 3, 0, 1);
193 test(r, "void main(inout half4 color) { if (color.r > color.g) color.a = 1; }", 5, 5, 0, 0,
194 5, 5, 0, 0);
195 test(r, "void main(inout half4 color) { if (color.r > color.g) color.a = 1; }", 5, 6, 0, 0,
196 5, 6, 0, 0);
197 test(r, "void main(inout half4 color) { if (color.r < color.g) color.a = 1; }", 3, 5, 0, 0,
198 3, 5, 0, 1);
199 test(r, "void main(inout half4 color) { if (color.r < color.g) color.a = 1; }", 5, 5, 0, 0,
200 5, 5, 0, 0);
201 test(r, "void main(inout half4 color) { if (color.r < color.g) color.a = 1; }", 6, 5, 0, 0,
202 6, 5, 0, 0);
203 test(r, "void main(inout half4 color) { if (color.r >= color.g) color.a = 1; }", 5, 3, 0, 0,
204 5, 3, 0, 1);
205 test(r, "void main(inout half4 color) { if (color.r >= color.g) color.a = 1; }", 5, 5, 0, 0,
206 5, 5, 0, 1);
207 test(r, "void main(inout half4 color) { if (color.r >= color.g) color.a = 1; }", 5, 6, 0, 0,
208 5, 6, 0, 0);
209 test(r, "void main(inout half4 color) { if (color.r <= color.g) color.a = 1; }", 3, 5, 0, 0,
210 3, 5, 0, 1);
211 test(r, "void main(inout half4 color) { if (color.r <= color.g) color.a = 1; }", 5, 5, 0, 0,
212 5, 5, 0, 1);
213 test(r, "void main(inout half4 color) { if (color.r <= color.g) color.a = 1; }", 6, 5, 0, 0,
214 6, 5, 0, 0);
215 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; }", 2, 2, 0, 0,
216 2, 2, 0, 1);
217 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; }", 2, -2, 0, 0,
218 2, -2, 0, 0);
219 test(r, "void main(inout half4 color) { if (color.r != color.g) color.a = 1; }", 2, 2, 0, 0,
220 2, 2, 0, 0);
221 test(r, "void main(inout half4 color) { if (color.r != color.g) color.a = 1; }", 2, -2, 0, 0,
222 2, -2, 0, 1);
223 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; else "
224 "color.a = 2; }", 1, 1, 0, 0, 1, 1, 0, 1);
225 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; else "
226 "color.a = 2; }", 2, -2, 0, 0, 2, -2, 0, 2);
227}
228
229DEF_TEST(SkSLInterpreterWhile, r) {
230 test(r, "void main(inout half4 color) { while (color.r < 1) color.r += 0.25; }", 0, 0, 0, 0, 1,
231 0, 0, 0);
232 test(r, "void main(inout half4 color) { while (color.r > 1) color.r += 0.25; }", 0, 0, 0, 0, 0,
233 0, 0, 0);
234 test(r, "void main(inout half4 color) { while (true) { color.r += 0.5; "
235 "if (color.r > 1) break; } }", 0, 0, 0, 0, 1.5, 0, 0, 0);
236 test(r, "void main(inout half4 color) { while (color.r < 10) { color.r += 0.5; "
237 "if (color.r < 5) continue; break; } }", 0, 0, 0, 0, 5, 0, 0, 0);
238}
239
240DEF_TEST(SkSLInterpreterDo, r) {
241 test(r, "void main(inout half4 color) { do color.r += 0.25; while (color.r < 1); }", 0, 0, 0, 0,
242 1, 0, 0, 0);
243 test(r, "void main(inout half4 color) { do color.r += 0.25; while (color.r > 1); }", 0, 0, 0, 0,
244 0.25, 0, 0, 0);
245 test(r, "void main(inout half4 color) { do { color.r += 0.5; if (color.r > 1) break; } while "
246 "(true); }", 0, 0, 0, 0, 1.5, 0, 0, 0);
247 test(r, "void main(inout half4 color) {do { color.r += 0.5; if (color.r < 5) "
248 "continue; if (color.r >= 5) break; } while (true); }", 0, 0, 0, 0, 5, 0, 0, 0);
Brian Osman44d44762019-05-13 14:19:12 -0400249 test(r, "void main(inout half4 color) { do { color.r += 0.5; } while (false); }",
250 0, 0, 0, 0, 0.5, 0, 0, 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400251}
252
253DEF_TEST(SkSLInterpreterFor, r) {
254 test(r, "void main(inout half4 color) { for (int i = 1; i <= 10; ++i) color.r += i; }", 0, 0, 0,
255 0, 55, 0, 0, 0);
256 test(r,
257 "void main(inout half4 color) {"
258 " for (int i = 1; i <= 10; ++i)"
259 " for (int j = i; j <= 10; ++j)"
260 " color.r += j;"
261 "}",
262 0, 0, 0, 0,
263 385, 0, 0, 0);
264 test(r,
265 "void main(inout half4 color) {"
266 " for (int i = 1; i <= 10; ++i)"
267 " for (int j = 1; ; ++j) {"
268 " if (i == j) continue;"
269 " if (j > 10) break;"
270 " color.r += j;"
271 " }"
272 "}",
273 0, 0, 0, 0,
274 495, 0, 0, 0);
275}
276
Brian Osmanf3fa6002019-05-17 14:26:53 -0400277DEF_TEST(SkSLInterpreterPrefixPostfix, r) {
278 test(r, "void main(inout half4 color) { color.r = ++color.g; }", 1, 2, 3, 4, 3, 3, 3, 4);
279 test(r, "void main(inout half4 color) { color.r = color.g++; }", 1, 2, 3, 4, 2, 3, 3, 4);
280}
281
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400282DEF_TEST(SkSLInterpreterSwizzle, r) {
283 test(r, "void main(inout half4 color) { color = color.abgr; }", 1, 2, 3, 4, 4, 3, 2, 1);
284 test(r, "void main(inout half4 color) { color.rgb = half4(5, 6, 7, 8).bbg; }", 1, 2, 3, 4, 7, 7,
285 6, 4);
286 test(r, "void main(inout half4 color) { color.bgr = int3(5, 6, 7); }", 1, 2, 3, 4, 7, 6,
287 5, 4);
288}
289
290DEF_TEST(SkSLInterpreterGlobal, r) {
291 test(r, "int x; void main(inout half4 color) { x = 10; color.b = x; }", 1, 2, 3, 4, 1, 2, 10,
292 4);
Brian Osmanb7451292019-05-15 13:02:13 -0400293 test(r, "float4 x; void main(inout float4 color) { x = color * 2; color = x; }",
294 1, 2, 3, 4, 2, 4, 6, 8);
295 test(r, "float4 x; void main(inout float4 color) { x = float4(5, 6, 7, 8); color = x.wzyx; }",
296 1, 2, 3, 4, 8, 7, 6, 5);
Brian Osman1091f022019-05-16 09:42:16 -0400297 test(r, "float4 x; void main(inout float4 color) { x.wzyx = float4(5, 6, 7, 8); color = x; }",
298 1, 2, 3, 4, 8, 7, 6, 5);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400299}
Ethan Nicholas746035a2019-04-23 13:31:09 -0400300
301DEF_TEST(SkSLInterpreterGeneric, r) {
302 float value1 = 5;
303 float expected1 = 25;
304 test(r, "float main(float x) { return x * x; }", (SkSL::Interpreter::Value*) &value1, 1,
305 (SkSL::Interpreter::Value*) &expected1);
306 float value2[2] = { 5, 25 };
307 float expected2[2] = { 25, 625 };
308 test(r, "float2 main(float x, float y) { return float2(x * x, y * y); }",
309 (SkSL::Interpreter::Value*) &value2, 2,
310 (SkSL::Interpreter::Value*) expected2);
311}
Brian Osmand369a5e2019-05-09 13:13:25 -0400312
313DEF_TEST(SkSLInterpreterSetInputs, r) {
314 const char* src = R"(
315 layout(ctype=float) in uniform float x;
316 float main(float y) { return x + y; }
317 )";
318
319 SkSL::Compiler compiler;
320 SkSL::Program::Settings settings;
321 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
322 SkSL::Program::kGeneric_Kind,
323 SkSL::String(src), settings);
324 REPORTER_ASSERT(r, program);
325
326 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
327 REPORTER_ASSERT(r, !compiler.errorCount());
328
329 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
330
331 float x = 1.0f;
332 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode),
333 (SkSL::Interpreter::Value*)&x);
334 float out = 0.0f;
335 float in = 2.0f;
336 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
337 REPORTER_ASSERT(r, out == 3.0f);
338
339 // External updates should be ignored
340 x = 3.0f;
341 out = 0.0f;
342 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
343 REPORTER_ASSERT(r, out == 3.0f);
344
345 // Updating inputs should affect subsequent calls to run
346 out = 0.0f;
347 interpreter.setInputs((SkSL::Interpreter::Value*)&x);
348 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
349 REPORTER_ASSERT(r, out == 5.0f);
350}
Brian Osman226668a2019-05-14 16:47:30 -0400351
Brian Osman07c117b2019-05-23 12:51:06 -0700352DEF_TEST(SkSLInterpreterCompound, r) {
353 struct RectAndColor { SkIRect fRect; SkColor4f fColor; };
354 struct ManyRects { int fNumRects; RectAndColor fRects[4]; };
355
356 const char* src =
357 // Some struct definitions
358 "struct Point { int x; int y; };\n"
359 "struct Rect { Point p0; Point p1; };\n"
360 "struct RectAndColor { Rect r; float4 color; };\n"
361
362 // Structs as globals, parameters, return values
363 "RectAndColor temp;\n"
364 "int rect_height(Rect r) { return r.p1.y - r.p0.y; }\n"
365 "RectAndColor make_blue_rect(int w, int h) {\n"
366 " temp.r.p0.x = temp.r.p0.y = 0;\n"
367 " temp.r.p1.x = w; temp.r.p1.y = h;\n"
368 " temp.color = float4(0, 1, 0, 1);\n"
369 " return temp;\n"
370 "}\n"
371
372 // Initialization and assignment of types larger than 4 slots
373 "RectAndColor init_big(RectAndColor r) { RectAndColor s = r; return s; }\n"
374 "RectAndColor copy_big(RectAndColor r) { RectAndColor s; s = r; return s; }\n"
375
376 // Same for arrays, including some non-constant indexing
377 "float tempFloats[8];\n"
378 "int median(int a[15]) { return a[7]; }\n"
379 "float[8] sums(float a[8]) {\n"
380 " float tempFloats[8];\n"
381 " tempFloats[0] = a[0];\n"
382 " for (int i = 1; i < 8; ++i) { tempFloats[i] = tempFloats[i - 1] + a[i]; }\n"
383 " return tempFloats;\n"
384 "}\n"
385
386 // Uniforms, array-of-structs, dynamic indices
387 "in uniform Rect gRects[4];\n"
388 "Rect get_rect(int i) { return gRects[i]; }\n"
389
390 // Kitchen sink (swizzles, inout, SoAoS)
391 "struct ManyRects { int numRects; RectAndColor rects[4]; };\n"
392 "void fill_rects(inout ManyRects mr) {\n"
393 " for (int i = 0; i < mr.numRects; ++i) {\n"
394 " mr.rects[i].r = gRects[i];\n"
395 " float b = mr.rects[i].r.p1.y;\n"
396 " mr.rects[i].color = float4(b, b, b, b);\n"
397 " }\n"
398 "}\n";
399
400 SkSL::Compiler compiler;
401 SkSL::Program::Settings settings;
402 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
403 SkSL::Program::kGeneric_Kind,
404 SkSL::String(src), settings);
405 REPORTER_ASSERT(r, program);
406
407 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
408 REPORTER_ASSERT(r, !compiler.errorCount());
409
410 auto rect_height = byteCode->getFunction("rect_height"),
411 make_blue_rect = byteCode->getFunction("make_blue_rect"),
412 median = byteCode->getFunction("median"),
413 sums = byteCode->getFunction("sums"),
414 get_rect = byteCode->getFunction("get_rect"),
415 fill_rects = byteCode->getFunction("fill_rects");
416
417 SkIRect gRects[4] = { { 1,2,3,4 }, { 5,6,7,8 }, { 9,10,11,12 }, { 13,14,15,16 } };
418
419 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode),
420 (SkSL::Interpreter::Value*)gRects);
421
422 {
423 SkIRect in = SkIRect::MakeXYWH(10, 10, 20, 30);
424 int out = 0;
425 interpreter.run(*rect_height,
426 (SkSL::Interpreter::Value*)&in,
427 (SkSL::Interpreter::Value*)&out);
428 REPORTER_ASSERT(r, out == 30);
429 }
430
431 {
432 int in[2] = { 15, 25 };
433 RectAndColor out;
434 interpreter.run(*make_blue_rect,
435 (SkSL::Interpreter::Value*)in,
436 (SkSL::Interpreter::Value*)&out);
437 REPORTER_ASSERT(r, out.fRect.width() == 15);
438 REPORTER_ASSERT(r, out.fRect.height() == 25);
439 SkColor4f blue = { 0.0f, 1.0f, 0.0f, 1.0f };
440 REPORTER_ASSERT(r, out.fColor == blue);
441 }
442
443 {
444 int in[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
445 int out = 0;
446 interpreter.run(*median,
447 (SkSL::Interpreter::Value*)in,
448 (SkSL::Interpreter::Value*)&out);
449 REPORTER_ASSERT(r, out == 8);
450 }
451
452 {
453 float in[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
454 float out[8] = { 0 };
455 interpreter.run(*sums,
456 (SkSL::Interpreter::Value*)in,
457 (SkSL::Interpreter::Value*)out);
458 for (int i = 0; i < 8; ++i) {
459 REPORTER_ASSERT(r, out[i] == static_cast<float>((i + 1) * (i + 2) / 2));
460 }
461 }
462
463 {
464 int in = 2;
465 SkIRect out = SkIRect::MakeEmpty();
466 interpreter.run(*get_rect,
467 (SkSL::Interpreter::Value*)&in,
468 (SkSL::Interpreter::Value*)&out);
469 REPORTER_ASSERT(r, out == gRects[2]);
470 }
471
472 {
473 ManyRects in;
474 memset(&in, 0, sizeof(in));
475 in.fNumRects = 2;
476 interpreter.run(*fill_rects,
477 (SkSL::Interpreter::Value*)&in,
478 nullptr);
479 ManyRects expected;
480 memset(&expected, 0, sizeof(expected));
481 expected.fNumRects = 2;
482 for (int i = 0; i < 2; ++i) {
483 expected.fRects[i].fRect = gRects[i];
484 float c = gRects[i].fBottom;
485 expected.fRects[i].fColor = { c, c, c, c };
486 }
487 REPORTER_ASSERT(r, memcmp(&in, &expected, sizeof(in)) == 0);
488 }
489}
Ethan Nicholas91164d12019-05-15 15:29:54 -0400490
Brian Osman226668a2019-05-14 16:47:30 -0400491DEF_TEST(SkSLInterpreterFunctions, r) {
492 const char* src =
493 "float sqr(float x) { return x * x; }\n"
494 // Forward declared
495 "float sub(float x, float y);\n"
496 "float main(float x) { return sub(sqr(x), x); }\n"
497 "float sub(float x, float y) { return x - y; }\n"
498
499 // Different signatures
500 "float dot(float2 a, float2 b) { return a.x*b.x + a.y*b.y; }\n"
501 "float dot(float3 a, float3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
502 "float dot3_test(float x) { return dot(float3(x, x + 1, x + 2), float3(1, -1, 2)); }\n"
503 "float dot2_test(float x) { return dot(float2(x, x + 1), float2(1, -1)); }\n"
Brian Osman4e93feb2019-05-16 15:38:00 -0400504 "int fib(int i) { return (i < 2) ? 1 : fib(i - 1) + fib(i - 2); }";
Brian Osman226668a2019-05-14 16:47:30 -0400505
506 SkSL::Compiler compiler;
507 SkSL::Program::Settings settings;
508 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
509 SkSL::Program::kGeneric_Kind,
510 SkSL::String(src), settings);
511 REPORTER_ASSERT(r, program);
512
513 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
514 REPORTER_ASSERT(r, !compiler.errorCount());
515
516 auto sub = byteCode->getFunction("sub");
517 auto sqr = byteCode->getFunction("sqr");
518 auto main = byteCode->getFunction("main");
519 auto tan = byteCode->getFunction("tan");
520 auto dot3 = byteCode->getFunction("dot3_test");
521 auto dot2 = byteCode->getFunction("dot2_test");
522 auto fib = byteCode->getFunction("fib");
523
524 REPORTER_ASSERT(r, sub);
525 REPORTER_ASSERT(r, sqr);
526 REPORTER_ASSERT(r, main);
527 REPORTER_ASSERT(r, !tan);
528 REPORTER_ASSERT(r, dot3);
529 REPORTER_ASSERT(r, dot2);
530 REPORTER_ASSERT(r, fib);
531
532 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode), nullptr);
533 float out = 0.0f;
534 float in = 3.0f;
535 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
536 REPORTER_ASSERT(r, out = 6.0f);
537
538 interpreter.run(*dot3, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
539 REPORTER_ASSERT(r, out = 9.0f);
540
541 interpreter.run(*dot2, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
542 REPORTER_ASSERT(r, out = -1.0f);
543
544 int fibIn = 6;
545 int fibOut = 0;
546 interpreter.run(*fib, (SkSL::Interpreter::Value*)&fibIn, (SkSL::Interpreter::Value*)&fibOut);
547 REPORTER_ASSERT(r, fibOut == 13);
548}
Ethan Nicholas91164d12019-05-15 15:29:54 -0400549
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400550DEF_TEST(SkSLInterpreterMathFunctions, r) {
551 SkSL::Interpreter::Value value, expected;
552
553 value = 0.0f; expected = 0.0f;
554 test(r, "float main(float x) { return sin(x); }", &value, 1, &expected);
555 test(r, "float main(float x) { return tan(x); }", &value, 1, &expected);
556
557 value = 0.0f; expected = 1.0f;
558 test(r, "float main(float x) { return cos(x); }", &value, 1, &expected);
559
560 value = 25.0f; expected = 5.0f;
561 test(r, "float main(float x) { return sqrt(x); }", &value, 1, &expected);
562}
563
564DEF_TEST(SkSLInterpreterMix, r) {
565 SkSL::Interpreter::Value value, expected;
566
567 value = 0.5f; expected = 0.0f;
568 test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
569 value = 0.75f; expected = 5.0f;
570 test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
571 value = 2.0f; expected = 30.0f;
572 test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
573
574 SkSL::Interpreter::Value valueVectors[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f },
575 expectedVector[] = { 3.0f, 4.0f, 5.0f, 6.0f };
576 test(r, "float4 main(float4 x, float4 y) { return mix(x, y, 0.5); }", valueVectors, 4,
577 expectedVector);
578}
579
580DEF_TEST(SkSLInterpreterCross, r) {
581 SkSL::Interpreter::Value args[] = { 1.0f, 4.0f, -6.0f, -2.0f, 7.0f, -3.0f };
582 SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(args[0].fFloat,
583 args[1].fFloat,
584 args[2].fFloat),
585 SkPoint3::Make(args[3].fFloat,
586 args[4].fFloat,
587 args[5].fFloat));
588 SkSL::Interpreter::Value expected[] = { cross.fX, cross.fY, cross.fZ };
589 test(r, "float3 main(float3 x, float3 y) { return cross(x, y); }", args, 3, expected);
590}
591
592DEF_TEST(SkSLInterpreterDot, r) {
593 SkSL::Interpreter::Value args[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
594 SkSL::Interpreter::Value expected = args[0].fFloat * args[2].fFloat +
595 args[1].fFloat * args[3].fFloat;
596 test(r, "float main(float2 x, float2 y) { return dot(x, y); }", args, 1, &expected);
597
598 expected = args[0].fFloat * args[3].fFloat +
599 args[1].fFloat * args[4].fFloat +
600 args[2].fFloat * args[5].fFloat;
601 test(r, "float main(float3 x, float3 y) { return dot(x, y); }", args, 1, &expected);
602
603 expected = args[0].fFloat * args[4].fFloat +
604 args[1].fFloat * args[5].fFloat +
605 args[2].fFloat * args[6].fFloat +
606 args[3].fFloat * args[7].fFloat;
607 test(r, "float main(float4 x, float4 y) { return dot(x, y); }", args, 1, &expected);
608}
609
Ethan Nicholas91164d12019-05-15 15:29:54 -0400610static const SkSL::Type& type_of(const skjson::Value* value, SkSL::Compiler* compiler) {
611 switch (value->getType()) {
612 case skjson::Value::Type::kNumber: {
613 float f = *value->as<skjson::NumberValue>();
614 if (f == (float) (int) f) {
615 return *compiler->context().fInt_Type;
616 }
617 return *compiler->context().fFloat_Type;
618 }
619 case skjson::Value::Type::kBool:
620 return *compiler->context().fBool_Type;
621 default:
622 return *compiler->context().fVoid_Type;
623 }
624}
625
626class JSONExternalValue : public SkSL::ExternalValue {
627public:
628 JSONExternalValue(const char* name, const skjson::Value* value, SkSL::Compiler* compiler)
629 : INHERITED(name, type_of(value, compiler))
630 , fValue(*value)
631 , fCompiler(*compiler) {}
632
633 bool canRead() const override {
634 return type() != *fCompiler.context().fVoid_Type;
635 }
636
637 void read(void* target) override {
638 if (type() == *fCompiler.context().fInt_Type) {
639 *(int*) target = *fValue.as<skjson::NumberValue>();
640 } else if (type() == *fCompiler.context().fFloat_Type) {
641 *(float*) target = *fValue.as<skjson::NumberValue>();
642 } else if (type() == *fCompiler.context().fBool_Type) {
643 *(bool*) target = *fValue.as<skjson::BoolValue>();
644 } else {
645 SkASSERT(false);
646 }
647 }
648
649 SkSL::ExternalValue* getChild(const char* name) const override {
650 if (fValue.getType() == skjson::Value::Type::kObject) {
651 const skjson::Value& v = fValue.as<skjson::ObjectValue>()[name];
652 return (SkSL::ExternalValue*) fCompiler.takeOwnership(std::unique_ptr<Symbol>(
653 new JSONExternalValue(name, &v, &fCompiler)));
654 }
655 return nullptr;
656 }
657
658private:
659 const skjson::Value& fValue;
660 SkSL::Compiler& fCompiler;
661
662 typedef SkSL::ExternalValue INHERITED;
663};
664
665class PointerExternalValue : public SkSL::ExternalValue {
666public:
667 PointerExternalValue(const char* name, const SkSL::Type& type, void* data, size_t size)
668 : INHERITED(name, type)
669 , fData(data)
670 , fSize(size) {}
671
672 bool canRead() const override {
673 return true;
674 }
675
676 bool canWrite() const override {
677 return true;
678 }
679
680 void read(void* target) override {
681 memcpy(target, fData, fSize);
682 }
683
684 void write(void* src) override {
685 memcpy(fData, src, fSize);
686 }
687
688
689private:
690 void* fData;
691 size_t fSize;
692
693 typedef SkSL::ExternalValue INHERITED;
694};
695
696DEF_TEST(SkSLInterpreterExternalValues, r) {
697 const char* json = "{ \"value1\": 12, \"child\": { \"value2\": true, \"value3\": 5.5 } }";
698 skjson::DOM dom(json, strlen(json));
699 SkSL::Compiler compiler;
700 SkSL::Program::Settings settings;
701 const char* src = "float main() {"
702 " outValue = 152;"
703 " if (root.child.value2)"
704 " return root.value1 * root.child.value3;"
705 " return -1;"
706 "}";
707 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
708 std::unique_ptr<SkSL::Symbol>(new JSONExternalValue("root", &dom.root(), &compiler))));
709 int32_t outValue = -1;
710 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
711 std::unique_ptr<SkSL::Symbol>(new PointerExternalValue("outValue",
712 *compiler.context().fInt_Type,
713 &outValue,
714 sizeof(outValue)))));
715 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
716 SkSL::Program::kGeneric_Kind,
717 SkSL::String(src), settings);
718 REPORTER_ASSERT(r, program);
719 if (program) {
720 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
721 REPORTER_ASSERT(r, !compiler.errorCount());
722 if (compiler.errorCount() > 0) {
723 printf("%s\n%s", src, compiler.errorText().c_str());
724 return;
725 }
726 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
727 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
728 SkSL::Interpreter::Value out;
729 interpreter.run(*main, nullptr, &out);
730 REPORTER_ASSERT(r, out.fFloat == 66.0);
731 REPORTER_ASSERT(r, outValue == 152);
732 } else {
733 printf("%s\n%s", src, compiler.errorText().c_str());
734 }
735}
736
737DEF_TEST(SkSLInterpreterExternalValuesVector, r) {
738 SkSL::Compiler compiler;
739 SkSL::Program::Settings settings;
740 const char* src = "void main() {"
741 " value *= 2;"
742 "}";
743 int32_t value[4] = { 1, 2, 3, 4 };
744 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
745 std::unique_ptr<SkSL::Symbol>(new PointerExternalValue("value",
746 *compiler.context().fInt4_Type,
747 value,
748 sizeof(value)))));
749 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
750 SkSL::String(src),
751 settings);
752 REPORTER_ASSERT(r, program);
753 if (program) {
754 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
755 REPORTER_ASSERT(r, !compiler.errorCount());
756 if (compiler.errorCount() > 0) {
757 printf("%s\n%s", src, compiler.errorText().c_str());
758 return;
759 }
760 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
761 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
762 SkSL::Interpreter::Value out;
763 interpreter.run(*main, nullptr, &out);
764 REPORTER_ASSERT(r, value[0] == 2);
765 REPORTER_ASSERT(r, value[1] == 4);
766 REPORTER_ASSERT(r, value[2] == 6);
767 REPORTER_ASSERT(r, value[3] == 8);
768 } else {
769 printf("%s\n%s", src, compiler.errorText().c_str());
770 }
771}
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400772
773class FunctionExternalValue : public SkSL::ExternalValue {
774public:
775 FunctionExternalValue(const char* name, float(*function)(float), SkSL::Compiler& compiler)
776 : INHERITED(name, *compiler.context().fFloat_Type)
777 , fCompiler(compiler)
778 , fFunction(function) {}
779
780 bool canCall() const override {
781 return true;
782 }
783
784 int callParameterCount() const override {
785 return 1;
786 }
787
788 void getCallParameterTypes(const SkSL::Type** outTypes) const override {
789 outTypes[0] = fCompiler.context().fFloat_Type.get();
790 }
791
792 void call(SkSL::Interpreter::Value* arguments, SkSL::Interpreter::Value* outReturn) override {
793 outReturn[0].fFloat = fFunction(arguments[0].fFloat);
794 }
795
796private:
797 SkSL::Compiler& fCompiler;
798
799 float (*fFunction)(float);
800
801 typedef SkSL::ExternalValue INHERITED;
802};
803
804DEF_TEST(SkSLInterpreterExternalValuesCall, r) {
805 SkSL::Compiler compiler;
806 SkSL::Program::Settings settings;
807 const char* src = "float main() {"
808 " return external(25);"
809 "}";
810 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
811 std::unique_ptr<SkSL::Symbol>(new FunctionExternalValue("external",
812 [] (float x) {
813 return (float) sqrt(x);
814 },
815 compiler))));
816 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
817 SkSL::String(src),
818 settings);
819 REPORTER_ASSERT(r, program);
820 if (program) {
821 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
822 REPORTER_ASSERT(r, !compiler.errorCount());
823 if (compiler.errorCount() > 0) {
824 printf("%s\n%s", src, compiler.errorText().c_str());
825 return;
826 }
827 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
828 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
829 SkSL::Interpreter::Value out;
830 interpreter.run(*main, nullptr, &out);
831 REPORTER_ASSERT(r, out.fFloat == 5.0);
832 } else {
833 printf("%s\n%s", src, compiler.errorText().c_str());
834 }
835}
836
837class VectorFunctionExternalValue : public SkSL::ExternalValue {
838public:
839 VectorFunctionExternalValue(const char* name, void(*function)(float[4], float[4]),
840 SkSL::Compiler& compiler)
841 : INHERITED(name, *compiler.context().fFloat4_Type)
842 , fCompiler(compiler)
843 , fFunction(function) {}
844
845 bool canCall() const override {
846 return true;
847 }
848
849 int callParameterCount() const override {
850 return 1;
851 }
852
853 void getCallParameterTypes(const SkSL::Type** outTypes) const override {
854 outTypes[0] = fCompiler.context().fFloat4_Type.get();
855 }
856
857 void call(SkSL::Interpreter::Value* arguments, SkSL::Interpreter::Value* outReturn) override {
858 fFunction((float*) arguments, (float*) outReturn);
859 }
860
861private:
862 SkSL::Compiler& fCompiler;
863
864 void (*fFunction)(float[4], float[4]);
865
866 typedef SkSL::ExternalValue INHERITED;
867};
868
869
870DEF_TEST(SkSLInterpreterExternalValuesVectorCall, r) {
871 SkSL::Compiler compiler;
872 SkSL::Program::Settings settings;
873 const char* src = "float4 main() {"
874 " return external(float4(1, 4, 9, 16));"
875 "}";
876 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
877 std::unique_ptr<SkSL::Symbol>(new VectorFunctionExternalValue("external",
878 [] (float in[4], float out[4]) {
879 out[0] = sqrt(in[0]);
880 out[1] = sqrt(in[1]);
881 out[2] = sqrt(in[2]);
882 out[3] = sqrt(in[3]);
883 },
884 compiler))));
885 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
886 SkSL::String(src),
887 settings);
888 REPORTER_ASSERT(r, program);
889 if (program) {
890 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
891 REPORTER_ASSERT(r, !compiler.errorCount());
892 if (compiler.errorCount() > 0) {
893 printf("%s\n%s", src, compiler.errorText().c_str());
894 return;
895 }
896 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
897 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
898 SkSL::Interpreter::Value out[4];
899 interpreter.run(*main, nullptr, out);
900 REPORTER_ASSERT(r, out[0].fFloat == 1.0);
901 REPORTER_ASSERT(r, out[1].fFloat == 2.0);
902 REPORTER_ASSERT(r, out[2].fFloat == 3.0);
903 REPORTER_ASSERT(r, out[3].fFloat == 4.0);
904 } else {
905 printf("%s\n%s", src, compiler.errorText().c_str());
906 }
907}