blob: 5307a439a8250d730d38295cb41d98a9048f60f6 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLCompiler.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -04009#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/sksl/SkSLInterpreter.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040011#include "src/utils/SkJSON.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "tests/Test.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040014
Ethan Nicholas746035a2019-04-23 13:31:09 -040015void test(skiatest::Reporter* r, const char* src, SkSL::Interpreter::Value* in, int expectedCount,
16 SkSL::Interpreter::Value* expected) {
17 SkSL::Compiler compiler;
18 SkSL::Program::Settings settings;
19 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
20 SkSL::Program::kGeneric_Kind,
21 SkSL::String(src), settings);
22 REPORTER_ASSERT(r, program);
23 if (program) {
24 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
25 REPORTER_ASSERT(r, !compiler.errorCount());
26 if (compiler.errorCount() > 0) {
27 printf("%s\n%s", src, compiler.errorText().c_str());
28 return;
29 }
30 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
31 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
Ethan Nicholas444aa122019-05-07 14:02:41 -040032 std::unique_ptr<SkSL::Interpreter::Value[]> out =
33 std::unique_ptr<SkSL::Interpreter::Value[]>(new SkSL::Interpreter::Value[expectedCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040034 interpreter.run(*main, in, out.get());
35 bool valid = !memcmp(out.get(), expected, sizeof(SkSL::Interpreter::Value) * expectedCount);
Ethan Nicholas746035a2019-04-23 13:31:09 -040036 if (!valid) {
37 printf("for program: %s\n", src);
38 printf(" expected (");
39 const char* separator = "";
40 for (int i = 0; i < expectedCount; ++i) {
41 printf("%s%f", separator, expected[i].fFloat);
42 separator = ", ";
43 }
44 printf("), but received (");
45 separator = "";
46 for (int i = 0; i < expectedCount; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040047 printf("%s%f", separator, out.get()[i].fFloat);
Ethan Nicholas746035a2019-04-23 13:31:09 -040048 separator = ", ";
49 }
50 printf(")\n");
51 }
52 REPORTER_ASSERT(r, valid);
53 } else {
54 printf("%s\n%s", src, compiler.errorText().c_str());
55 }
56}
57
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040058void test(skiatest::Reporter* r, const char* src, float inR, float inG, float inB, float inA,
59 float expectedR, float expectedG, float expectedB, float expectedA) {
60 SkSL::Compiler compiler;
61 SkSL::Program::Settings settings;
62 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
Ethan Nicholas746035a2019-04-23 13:31:09 -040063 SkSL::Program::kGeneric_Kind,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040064 SkSL::String(src), settings);
65 REPORTER_ASSERT(r, program);
66 if (program) {
67 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
68 REPORTER_ASSERT(r, !compiler.errorCount());
69 if (compiler.errorCount() > 0) {
70 printf("%s\n%s", src, compiler.errorText().c_str());
71 return;
72 }
73 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
74 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
75 float inoutColor[4] = { inR, inG, inB, inA };
76 interpreter.run(*main, (SkSL::Interpreter::Value*) inoutColor, nullptr);
77 if (inoutColor[0] != expectedR || inoutColor[1] != expectedG ||
78 inoutColor[2] != expectedB || inoutColor[3] != expectedA) {
79 printf("for program: %s\n", src);
80 printf(" expected (%f, %f, %f, %f), but received (%f, %f, %f, %f)\n", expectedR,
81 expectedG, expectedB, expectedA, inoutColor[0], inoutColor[1], inoutColor[2],
82 inoutColor[3]);
Mike Kleinb6a6f082019-05-17 14:56:39 -050083 interpreter.disassemble(*main);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040084 }
85 REPORTER_ASSERT(r, inoutColor[0] == expectedR);
86 REPORTER_ASSERT(r, inoutColor[1] == expectedG);
87 REPORTER_ASSERT(r, inoutColor[2] == expectedB);
88 REPORTER_ASSERT(r, inoutColor[3] == expectedA);
89 } else {
90 printf("%s\n%s", src, compiler.errorText().c_str());
91 }
92}
93
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094DEF_TEST(SkSLInterpreterAdd, r) {
95 test(r, "void main(inout half4 color) { color.r = color.r + color.g; }", 0.25, 0.75, 0, 0, 1,
96 0.75, 0, 0);
97 test(r, "void main(inout half4 color) { color += half4(1, 2, 3, 4); }", 4, 3, 2, 1, 5, 5, 5, 5);
98 test(r, "void main(inout half4 color) { half4 c = color; color += c; }", 0.25, 0.5, 0.75, 1,
99 0.5, 1, 1.5, 2);
100 test(r, "void main(inout half4 color) { int a = 1; int b = 3; color.r = a + b; }", 1, 2, 3, 4,
101 4, 2, 3, 4);
102}
103
104DEF_TEST(SkSLInterpreterSubtract, r) {
105 test(r, "void main(inout half4 color) { color.r = color.r - color.g; }", 1, 0.75, 0, 0, 0.25,
106 0.75, 0, 0);
107 test(r, "void main(inout half4 color) { color -= half4(1, 2, 3, 4); }", 5, 5, 5, 5, 4, 3, 2, 1);
108 test(r, "void main(inout half4 color) { half4 c = color; color -= c; }", 4, 3, 2, 1,
109 0, 0, 0, 0);
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400110 test(r, "void main(inout half4 color) { color.x = -color.x; }", 4, 3, 2, 1, -4, 3, 2, 1);
111 test(r, "void main(inout half4 color) { color = -color; }", 4, 3, 2, 1, -4, -3, -2, -1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400112 test(r, "void main(inout half4 color) { int a = 3; int b = 1; color.r = a - b; }", 0, 0, 0, 0,
113 2, 0, 0, 0);
114}
115
116DEF_TEST(SkSLInterpreterMultiply, r) {
117 test(r, "void main(inout half4 color) { color.r = color.r * color.g; }", 2, 3, 0, 0, 6, 3, 0,
118 0);
119 test(r, "void main(inout half4 color) { color *= half4(1, 2, 3, 4); }", 2, 3, 4, 5, 2, 6, 12,
120 20);
121 test(r, "void main(inout half4 color) { half4 c = color; color *= c; }", 4, 3, 2, 1,
122 16, 9, 4, 1);
123 test(r, "void main(inout half4 color) { int a = 3; int b = -2; color.r = a * b; }", 0, 0, 0, 0,
124 -6, 0, 0, 0);
125}
126
127DEF_TEST(SkSLInterpreterDivide, r) {
128 test(r, "void main(inout half4 color) { color.r = color.r / color.g; }", 1, 2, 0, 0, 0.5, 2, 0,
129 0);
130 test(r, "void main(inout half4 color) { color /= half4(1, 2, 3, 4); }", 12, 12, 12, 12, 12, 6,
131 4, 3);
132 test(r, "void main(inout half4 color) { half4 c = color; color /= c; }", 4, 3, 2, 1,
133 1, 1, 1, 1);
134 test(r, "void main(inout half4 color) { int a = 8; int b = -2; color.r = a / b; }", 0, 0, 0, 0,
135 -4, 0, 0, 0);
136}
137
138DEF_TEST(SkSLInterpreterRemainder, r) {
Brian Osman3b41baf2019-05-08 09:24:46 -0400139 test(r, "void main(inout half4 color) { color.r = color.r % color.g; }", 3.125, 2, 0, 0,
140 1.125, 2, 0, 0);
141 test(r, "void main(inout half4 color) { color %= half4(1, 2, 3, 4); }", 9.5, 9.5, 9.5, 9.5,
142 0.5, 1.5, 0.5, 1.5);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400143 test(r, "void main(inout half4 color) { int a = 8; int b = 3; a %= b; color.r = a; }", 0, 0, 0,
144 0, 2, 0, 0, 0);
145 test(r, "void main(inout half4 color) { int a = 8; int b = 3; color.r = a % b; }", 0, 0, 0, 0,
146 2, 0, 0, 0);
147 test(r, "void main(inout half4 color) { int2 a = int2(8, 10); a %= 6; color.rg = a; }", 0, 0, 0,
148 0, 2, 4, 0, 0);
149}
150
Brian Osman4e93feb2019-05-16 15:38:00 -0400151DEF_TEST(SkSLInterpreterTernary, r) {
152 test(r, "void main(inout half4 color) { color.r = color.g > color.b ? color.g : color.b; }",
153 0, 1, 2, 0, 2, 1, 2, 0);
154 test(r, "void main(inout half4 color) { color.r = color.g > color.b ? color.g : color.b; }",
155 0, 3, 2, 0, 3, 3, 2, 0);
156}
157
Brian Osman41672152019-05-14 13:37:30 -0400158DEF_TEST(SkSLInterpreterCast, r) {
159 SkSL::Interpreter::Value input[2];
160 SkSL::Interpreter::Value expected[2];
161
162 input[0].fSigned = 3;
163 input[1].fSigned = -5;
164 expected[0].fFloat = 3.0f;
165 expected[1].fFloat = -5.0f;
166 test(r, "float main(int x) { return float (x); }", input, 1, expected);
167 test(r, "float2 main(int2 x) { return float2(x); }", input, 2, expected);
168
169 input[0].fUnsigned = 3;
170 input[1].fUnsigned = 5;
171 expected[0].fFloat = 3.0f;
172 expected[1].fFloat = 5.0f;
173 test(r, "float main(uint x) { return float (x); }", input, 1, expected);
174 test(r, "float2 main(uint2 x) { return float2(x); }", input, 2, expected);
175
176 input[0].fFloat = 3.0f;
177 input[1].fFloat = -5.0f;
178 expected[0].fSigned = 3;
179 expected[1].fSigned = -5;
180 test(r, "int main(float x) { return int (x); }", input, 1, expected);
181 test(r, "int2 main(float2 x) { return int2(x); }", input, 2, expected);
182}
183
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184DEF_TEST(SkSLInterpreterIf, r) {
185 test(r, "void main(inout half4 color) { if (color.r > color.g) color.a = 1; }", 5, 3, 0, 0,
186 5, 3, 0, 1);
187 test(r, "void main(inout half4 color) { if (color.r > color.g) color.a = 1; }", 5, 5, 0, 0,
188 5, 5, 0, 0);
189 test(r, "void main(inout half4 color) { if (color.r > color.g) color.a = 1; }", 5, 6, 0, 0,
190 5, 6, 0, 0);
191 test(r, "void main(inout half4 color) { if (color.r < color.g) color.a = 1; }", 3, 5, 0, 0,
192 3, 5, 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; }", 6, 5, 0, 0,
196 6, 5, 0, 0);
197 test(r, "void main(inout half4 color) { if (color.r >= color.g) color.a = 1; }", 5, 3, 0, 0,
198 5, 3, 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, 1);
201 test(r, "void main(inout half4 color) { if (color.r >= color.g) color.a = 1; }", 5, 6, 0, 0,
202 5, 6, 0, 0);
203 test(r, "void main(inout half4 color) { if (color.r <= color.g) color.a = 1; }", 3, 5, 0, 0,
204 3, 5, 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; }", 6, 5, 0, 0,
208 6, 5, 0, 0);
209 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; }", 2, 2, 0, 0,
210 2, 2, 0, 1);
211 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; }", 2, -2, 0, 0,
212 2, -2, 0, 0);
213 test(r, "void main(inout half4 color) { if (color.r != color.g) color.a = 1; }", 2, 2, 0, 0,
214 2, 2, 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; else "
218 "color.a = 2; }", 1, 1, 0, 0, 1, 1, 0, 1);
219 test(r, "void main(inout half4 color) { if (color.r == color.g) color.a = 1; else "
220 "color.a = 2; }", 2, -2, 0, 0, 2, -2, 0, 2);
221}
222
223DEF_TEST(SkSLInterpreterWhile, r) {
224 test(r, "void main(inout half4 color) { while (color.r < 1) color.r += 0.25; }", 0, 0, 0, 0, 1,
225 0, 0, 0);
226 test(r, "void main(inout half4 color) { while (color.r > 1) color.r += 0.25; }", 0, 0, 0, 0, 0,
227 0, 0, 0);
228 test(r, "void main(inout half4 color) { while (true) { color.r += 0.5; "
229 "if (color.r > 1) break; } }", 0, 0, 0, 0, 1.5, 0, 0, 0);
230 test(r, "void main(inout half4 color) { while (color.r < 10) { color.r += 0.5; "
231 "if (color.r < 5) continue; break; } }", 0, 0, 0, 0, 5, 0, 0, 0);
232}
233
234DEF_TEST(SkSLInterpreterDo, r) {
235 test(r, "void main(inout half4 color) { do color.r += 0.25; while (color.r < 1); }", 0, 0, 0, 0,
236 1, 0, 0, 0);
237 test(r, "void main(inout half4 color) { do color.r += 0.25; while (color.r > 1); }", 0, 0, 0, 0,
238 0.25, 0, 0, 0);
239 test(r, "void main(inout half4 color) { do { color.r += 0.5; if (color.r > 1) break; } while "
240 "(true); }", 0, 0, 0, 0, 1.5, 0, 0, 0);
241 test(r, "void main(inout half4 color) {do { color.r += 0.5; if (color.r < 5) "
242 "continue; if (color.r >= 5) break; } while (true); }", 0, 0, 0, 0, 5, 0, 0, 0);
Brian Osman44d44762019-05-13 14:19:12 -0400243 test(r, "void main(inout half4 color) { do { color.r += 0.5; } while (false); }",
244 0, 0, 0, 0, 0.5, 0, 0, 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400245}
246
247DEF_TEST(SkSLInterpreterFor, r) {
248 test(r, "void main(inout half4 color) { for (int i = 1; i <= 10; ++i) color.r += i; }", 0, 0, 0,
249 0, 55, 0, 0, 0);
250 test(r,
251 "void main(inout half4 color) {"
252 " for (int i = 1; i <= 10; ++i)"
253 " for (int j = i; j <= 10; ++j)"
254 " color.r += j;"
255 "}",
256 0, 0, 0, 0,
257 385, 0, 0, 0);
258 test(r,
259 "void main(inout half4 color) {"
260 " for (int i = 1; i <= 10; ++i)"
261 " for (int j = 1; ; ++j) {"
262 " if (i == j) continue;"
263 " if (j > 10) break;"
264 " color.r += j;"
265 " }"
266 "}",
267 0, 0, 0, 0,
268 495, 0, 0, 0);
269}
270
Brian Osmanf3fa6002019-05-17 14:26:53 -0400271DEF_TEST(SkSLInterpreterPrefixPostfix, r) {
272 test(r, "void main(inout half4 color) { color.r = ++color.g; }", 1, 2, 3, 4, 3, 3, 3, 4);
273 test(r, "void main(inout half4 color) { color.r = color.g++; }", 1, 2, 3, 4, 2, 3, 3, 4);
274}
275
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400276DEF_TEST(SkSLInterpreterSwizzle, r) {
277 test(r, "void main(inout half4 color) { color = color.abgr; }", 1, 2, 3, 4, 4, 3, 2, 1);
278 test(r, "void main(inout half4 color) { color.rgb = half4(5, 6, 7, 8).bbg; }", 1, 2, 3, 4, 7, 7,
279 6, 4);
280 test(r, "void main(inout half4 color) { color.bgr = int3(5, 6, 7); }", 1, 2, 3, 4, 7, 6,
281 5, 4);
282}
283
284DEF_TEST(SkSLInterpreterGlobal, r) {
285 test(r, "int x; void main(inout half4 color) { x = 10; color.b = x; }", 1, 2, 3, 4, 1, 2, 10,
286 4);
Brian Osmanb7451292019-05-15 13:02:13 -0400287 test(r, "float4 x; void main(inout float4 color) { x = color * 2; color = x; }",
288 1, 2, 3, 4, 2, 4, 6, 8);
289 test(r, "float4 x; void main(inout float4 color) { x = float4(5, 6, 7, 8); color = x.wzyx; }",
290 1, 2, 3, 4, 8, 7, 6, 5);
Brian Osman1091f022019-05-16 09:42:16 -0400291 test(r, "float4 x; void main(inout float4 color) { x.wzyx = float4(5, 6, 7, 8); color = x; }",
292 1, 2, 3, 4, 8, 7, 6, 5);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400293}
Ethan Nicholas746035a2019-04-23 13:31:09 -0400294
295DEF_TEST(SkSLInterpreterGeneric, r) {
296 float value1 = 5;
297 float expected1 = 25;
298 test(r, "float main(float x) { return x * x; }", (SkSL::Interpreter::Value*) &value1, 1,
299 (SkSL::Interpreter::Value*) &expected1);
300 float value2[2] = { 5, 25 };
301 float expected2[2] = { 25, 625 };
302 test(r, "float2 main(float x, float y) { return float2(x * x, y * y); }",
303 (SkSL::Interpreter::Value*) &value2, 2,
304 (SkSL::Interpreter::Value*) expected2);
305}
Brian Osmand369a5e2019-05-09 13:13:25 -0400306
307DEF_TEST(SkSLInterpreterSetInputs, r) {
308 const char* src = R"(
309 layout(ctype=float) in uniform float x;
310 float main(float y) { return x + y; }
311 )";
312
313 SkSL::Compiler compiler;
314 SkSL::Program::Settings settings;
315 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
316 SkSL::Program::kGeneric_Kind,
317 SkSL::String(src), settings);
318 REPORTER_ASSERT(r, program);
319
320 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
321 REPORTER_ASSERT(r, !compiler.errorCount());
322
323 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
324
325 float x = 1.0f;
326 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode),
327 (SkSL::Interpreter::Value*)&x);
328 float out = 0.0f;
329 float in = 2.0f;
330 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
331 REPORTER_ASSERT(r, out == 3.0f);
332
333 // External updates should be ignored
334 x = 3.0f;
335 out = 0.0f;
336 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
337 REPORTER_ASSERT(r, out == 3.0f);
338
339 // Updating inputs should affect subsequent calls to run
340 out = 0.0f;
341 interpreter.setInputs((SkSL::Interpreter::Value*)&x);
342 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
343 REPORTER_ASSERT(r, out == 5.0f);
344}
Brian Osman226668a2019-05-14 16:47:30 -0400345
Ethan Nicholas91164d12019-05-15 15:29:54 -0400346
Brian Osman226668a2019-05-14 16:47:30 -0400347DEF_TEST(SkSLInterpreterFunctions, r) {
348 const char* src =
349 "float sqr(float x) { return x * x; }\n"
350 // Forward declared
351 "float sub(float x, float y);\n"
352 "float main(float x) { return sub(sqr(x), x); }\n"
353 "float sub(float x, float y) { return x - y; }\n"
354
355 // Different signatures
356 "float dot(float2 a, float2 b) { return a.x*b.x + a.y*b.y; }\n"
357 "float dot(float3 a, float3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
358 "float dot3_test(float x) { return dot(float3(x, x + 1, x + 2), float3(1, -1, 2)); }\n"
359 "float dot2_test(float x) { return dot(float2(x, x + 1), float2(1, -1)); }\n"
Brian Osman4e93feb2019-05-16 15:38:00 -0400360 "int fib(int i) { return (i < 2) ? 1 : fib(i - 1) + fib(i - 2); }";
Brian Osman226668a2019-05-14 16:47:30 -0400361
362 SkSL::Compiler compiler;
363 SkSL::Program::Settings settings;
364 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
365 SkSL::Program::kGeneric_Kind,
366 SkSL::String(src), settings);
367 REPORTER_ASSERT(r, program);
368
369 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
370 REPORTER_ASSERT(r, !compiler.errorCount());
371
372 auto sub = byteCode->getFunction("sub");
373 auto sqr = byteCode->getFunction("sqr");
374 auto main = byteCode->getFunction("main");
375 auto tan = byteCode->getFunction("tan");
376 auto dot3 = byteCode->getFunction("dot3_test");
377 auto dot2 = byteCode->getFunction("dot2_test");
378 auto fib = byteCode->getFunction("fib");
379
380 REPORTER_ASSERT(r, sub);
381 REPORTER_ASSERT(r, sqr);
382 REPORTER_ASSERT(r, main);
383 REPORTER_ASSERT(r, !tan);
384 REPORTER_ASSERT(r, dot3);
385 REPORTER_ASSERT(r, dot2);
386 REPORTER_ASSERT(r, fib);
387
388 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode), nullptr);
389 float out = 0.0f;
390 float in = 3.0f;
391 interpreter.run(*main, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
392 REPORTER_ASSERT(r, out = 6.0f);
393
394 interpreter.run(*dot3, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
395 REPORTER_ASSERT(r, out = 9.0f);
396
397 interpreter.run(*dot2, (SkSL::Interpreter::Value*)&in, (SkSL::Interpreter::Value*)&out);
398 REPORTER_ASSERT(r, out = -1.0f);
399
400 int fibIn = 6;
401 int fibOut = 0;
402 interpreter.run(*fib, (SkSL::Interpreter::Value*)&fibIn, (SkSL::Interpreter::Value*)&fibOut);
403 REPORTER_ASSERT(r, fibOut == 13);
404}
Ethan Nicholas91164d12019-05-15 15:29:54 -0400405
406static const SkSL::Type& type_of(const skjson::Value* value, SkSL::Compiler* compiler) {
407 switch (value->getType()) {
408 case skjson::Value::Type::kNumber: {
409 float f = *value->as<skjson::NumberValue>();
410 if (f == (float) (int) f) {
411 return *compiler->context().fInt_Type;
412 }
413 return *compiler->context().fFloat_Type;
414 }
415 case skjson::Value::Type::kBool:
416 return *compiler->context().fBool_Type;
417 default:
418 return *compiler->context().fVoid_Type;
419 }
420}
421
422class JSONExternalValue : public SkSL::ExternalValue {
423public:
424 JSONExternalValue(const char* name, const skjson::Value* value, SkSL::Compiler* compiler)
425 : INHERITED(name, type_of(value, compiler))
426 , fValue(*value)
427 , fCompiler(*compiler) {}
428
429 bool canRead() const override {
430 return type() != *fCompiler.context().fVoid_Type;
431 }
432
433 void read(void* target) override {
434 if (type() == *fCompiler.context().fInt_Type) {
435 *(int*) target = *fValue.as<skjson::NumberValue>();
436 } else if (type() == *fCompiler.context().fFloat_Type) {
437 *(float*) target = *fValue.as<skjson::NumberValue>();
438 } else if (type() == *fCompiler.context().fBool_Type) {
439 *(bool*) target = *fValue.as<skjson::BoolValue>();
440 } else {
441 SkASSERT(false);
442 }
443 }
444
445 SkSL::ExternalValue* getChild(const char* name) const override {
446 if (fValue.getType() == skjson::Value::Type::kObject) {
447 const skjson::Value& v = fValue.as<skjson::ObjectValue>()[name];
448 return (SkSL::ExternalValue*) fCompiler.takeOwnership(std::unique_ptr<Symbol>(
449 new JSONExternalValue(name, &v, &fCompiler)));
450 }
451 return nullptr;
452 }
453
454private:
455 const skjson::Value& fValue;
456 SkSL::Compiler& fCompiler;
457
458 typedef SkSL::ExternalValue INHERITED;
459};
460
461class PointerExternalValue : public SkSL::ExternalValue {
462public:
463 PointerExternalValue(const char* name, const SkSL::Type& type, void* data, size_t size)
464 : INHERITED(name, type)
465 , fData(data)
466 , fSize(size) {}
467
468 bool canRead() const override {
469 return true;
470 }
471
472 bool canWrite() const override {
473 return true;
474 }
475
476 void read(void* target) override {
477 memcpy(target, fData, fSize);
478 }
479
480 void write(void* src) override {
481 memcpy(fData, src, fSize);
482 }
483
484
485private:
486 void* fData;
487 size_t fSize;
488
489 typedef SkSL::ExternalValue INHERITED;
490};
491
492DEF_TEST(SkSLInterpreterExternalValues, r) {
493 const char* json = "{ \"value1\": 12, \"child\": { \"value2\": true, \"value3\": 5.5 } }";
494 skjson::DOM dom(json, strlen(json));
495 SkSL::Compiler compiler;
496 SkSL::Program::Settings settings;
497 const char* src = "float main() {"
498 " outValue = 152;"
499 " if (root.child.value2)"
500 " return root.value1 * root.child.value3;"
501 " return -1;"
502 "}";
503 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
504 std::unique_ptr<SkSL::Symbol>(new JSONExternalValue("root", &dom.root(), &compiler))));
505 int32_t outValue = -1;
506 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
507 std::unique_ptr<SkSL::Symbol>(new PointerExternalValue("outValue",
508 *compiler.context().fInt_Type,
509 &outValue,
510 sizeof(outValue)))));
511 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
512 SkSL::Program::kGeneric_Kind,
513 SkSL::String(src), settings);
514 REPORTER_ASSERT(r, program);
515 if (program) {
516 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
517 REPORTER_ASSERT(r, !compiler.errorCount());
518 if (compiler.errorCount() > 0) {
519 printf("%s\n%s", src, compiler.errorText().c_str());
520 return;
521 }
522 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
523 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
524 SkSL::Interpreter::Value out;
525 interpreter.run(*main, nullptr, &out);
526 REPORTER_ASSERT(r, out.fFloat == 66.0);
527 REPORTER_ASSERT(r, outValue == 152);
528 } else {
529 printf("%s\n%s", src, compiler.errorText().c_str());
530 }
531}
532
533DEF_TEST(SkSLInterpreterExternalValuesVector, r) {
534 SkSL::Compiler compiler;
535 SkSL::Program::Settings settings;
536 const char* src = "void main() {"
537 " value *= 2;"
538 "}";
539 int32_t value[4] = { 1, 2, 3, 4 };
540 compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
541 std::unique_ptr<SkSL::Symbol>(new PointerExternalValue("value",
542 *compiler.context().fInt4_Type,
543 value,
544 sizeof(value)))));
545 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
546 SkSL::String(src),
547 settings);
548 REPORTER_ASSERT(r, program);
549 if (program) {
550 std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
551 REPORTER_ASSERT(r, !compiler.errorCount());
552 if (compiler.errorCount() > 0) {
553 printf("%s\n%s", src, compiler.errorText().c_str());
554 return;
555 }
556 SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
557 SkSL::Interpreter interpreter(std::move(program), std::move(byteCode));
558 SkSL::Interpreter::Value out;
559 interpreter.run(*main, nullptr, &out);
560 REPORTER_ASSERT(r, value[0] == 2);
561 REPORTER_ASSERT(r, value[1] == 4);
562 REPORTER_ASSERT(r, value[2] == 6);
563 REPORTER_ASSERT(r, value[3] == 8);
564 } else {
565 printf("%s\n%s", src, compiler.errorText().c_str());
566 }
567}