1 /*
2 * Copyright 2020 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/gpu/GrDirectContext.h"
9 #include "include/private/SkSLDefines.h"
10 #include "include/private/SkSLIRNode.h"
11 #include "include/private/SkSLModifiers.h"
12 #include "include/private/SkSLProgramElement.h"
13 #include "include/private/SkSLProgramKind.h"
14 #include "include/private/SkSLStatement.h"
15 #include "include/private/base/SkTArray.h"
16 #include "include/sksl/DSL.h"
17 #include "include/sksl/DSLBlock.h"
18 #include "include/sksl/DSLCore.h"
19 #include "include/sksl/DSLExpression.h"
20 #include "include/sksl/DSLFunction.h"
21 #include "include/sksl/DSLLayout.h"
22 #include "include/sksl/DSLModifiers.h"
23 #include "include/sksl/DSLStatement.h"
24 #include "include/sksl/DSLType.h"
25 #include "include/sksl/DSLVar.h"
26 #include "include/sksl/SkSLErrorReporter.h"
27 #include "include/sksl/SkSLPosition.h"
28 #include "src/gpu/ganesh/GrDirectContextPriv.h"
29 #include "src/gpu/ganesh/GrGpu.h"
30 #include "src/sksl/SkSLCompiler.h"
31 #include "src/sksl/SkSLProgramSettings.h"
32 #include "src/sksl/SkSLThreadContext.h"
33 #include "src/sksl/dsl/priv/DSLWriter.h"
34 #include "src/sksl/ir/SkSLBlock.h"
35 #include "src/sksl/ir/SkSLExpression.h"
36 #include "src/sksl/ir/SkSLProgram.h"
37 #include "tests/Test.h"
38
39 #include <ctype.h>
40 #include <cstdint>
41 #include <cstdlib>
42 #include <limits>
43 #include <memory>
44 #include <string>
45 #include <string_view>
46 #include <utility>
47 #include <vector>
48
49 struct GrContextOptions;
50
51 using namespace SkSL::dsl;
52
default_settings()53 SkSL::ProgramSettings default_settings() {
54 return SkSL::ProgramSettings{};
55 }
56
57 /**
58 * Issues an automatic Start() and End().
59 */
60 class AutoDSLContext {
61 public:
AutoDSLContext(GrGpu * gpu,SkSL::ProgramSettings settings=default_settings (),SkSL::ProgramKind kind=SkSL::ProgramKind::kFragment)62 AutoDSLContext(GrGpu* gpu, SkSL::ProgramSettings settings = default_settings(),
63 SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment) {
64 Start(gpu->shaderCompiler(), kind, settings);
65 }
66
~AutoDSLContext()67 ~AutoDSLContext() {
68 End();
69 }
70 };
71
72 class ExpectError : public SkSL::ErrorReporter {
73 public:
ExpectError(skiatest::Reporter * reporter,const char * msg)74 ExpectError(skiatest::Reporter* reporter, const char* msg)
75 : fMsg(msg)
76 , fReporter(reporter)
77 , fOldReporter(&GetErrorReporter()) {
78 SetErrorReporter(this);
79 }
80
~ExpectError()81 ~ExpectError() override {
82 REPORTER_ASSERT(fReporter, !fMsg,
83 "Error mismatch: expected:\n%s\nbut no error occurred\n", fMsg);
84 SetErrorReporter(fOldReporter);
85 }
86
handleError(std::string_view msg,SkSL::Position pos)87 void handleError(std::string_view msg, SkSL::Position pos) override {
88 REPORTER_ASSERT(fReporter, fMsg, "Received unexpected extra error: %.*s\n",
89 (int)msg.length(), msg.data());
90 REPORTER_ASSERT(fReporter, !fMsg || msg == fMsg,
91 "Error mismatch: expected:\n%s\nbut received:\n%.*s", fMsg, (int)msg.length(),
92 msg.data());
93 fMsg = nullptr;
94 }
95
96 private:
97 const char* fMsg;
98 skiatest::Reporter* fReporter;
99 ErrorReporter* fOldReporter;
100 };
101
whitespace_insensitive_compare(const char * a,const char * b)102 static bool whitespace_insensitive_compare(const char* a, const char* b) {
103 for (;;) {
104 while (isspace(*a)) {
105 ++a;
106 }
107 while (isspace(*b)) {
108 ++b;
109 }
110 if (*a != *b) {
111 return false;
112 }
113 if (*a == 0) {
114 return true;
115 }
116 ++a;
117 ++b;
118 }
119 }
120
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLStartup,r,ctxInfo)121 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLStartup, r, ctxInfo) {
122 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
123 Expression e1 = 1;
124 REPORTER_ASSERT(r, e1.release()->description() == "1");
125 Expression e2 = 1.0;
126 REPORTER_ASSERT(r, e2.release()->description() == "1.0");
127 Expression e3 = true;
128 REPORTER_ASSERT(r, e3.release()->description() == "true");
129 Var a(kInt_Type, "a");
130 Expression e4 = a;
131 REPORTER_ASSERT(r, e4.release()->description() == "a");
132
133 REPORTER_ASSERT(r, whitespace_insensitive_compare("", ""));
134 REPORTER_ASSERT(r, !whitespace_insensitive_compare("", "a"));
135 REPORTER_ASSERT(r, !whitespace_insensitive_compare("a", ""));
136 REPORTER_ASSERT(r, whitespace_insensitive_compare("a", "a"));
137 REPORTER_ASSERT(r, whitespace_insensitive_compare("abc", "abc"));
138 REPORTER_ASSERT(r, whitespace_insensitive_compare("abc", " abc "));
139 REPORTER_ASSERT(r, whitespace_insensitive_compare("a b c ", "\n\n\nabc"));
140 REPORTER_ASSERT(r, !whitespace_insensitive_compare("a b c d", "\n\n\nabc"));
141 }
142
stringize(DSLStatement & stmt)143 static std::string stringize(DSLStatement& stmt) { return stmt.release()->description(); }
stringize(DSLExpression & expr)144 static std::string stringize(DSLExpression& expr) { return expr.release()->description(); }
stringize(DSLBlock & blck)145 static std::string stringize(DSLBlock& blck) { return blck.release()->description(); }
stringize(SkSL::IRNode & node)146 static std::string stringize(SkSL::IRNode& node) { return node.description(); }
stringize(SkSL::Program & program)147 static std::string stringize(SkSL::Program& program) { return program.description(); }
148
149 template <typename T>
expect_equal(skiatest::Reporter * r,int lineNumber,T & input,const char * expected)150 static void expect_equal(skiatest::Reporter* r, int lineNumber, T& input, const char* expected) {
151 std::string actual = stringize(input);
152 if (!whitespace_insensitive_compare(expected, actual.c_str())) {
153 ERRORF(r, "(Failed on line %d)\nExpected: %s\n Actual: %s\n",
154 lineNumber, expected, actual.c_str());
155 }
156 }
157
158 template <typename T>
expect_equal(skiatest::Reporter * r,int lineNumber,T && dsl,const char * expected)159 static void expect_equal(skiatest::Reporter* r, int lineNumber, T&& dsl, const char* expected) {
160 // This overload allows temporary values to be passed to expect_equal.
161 return expect_equal(r, lineNumber, dsl, expected);
162 }
163
164 #define EXPECT_EQUAL(a, b) expect_equal(r, __LINE__, (a), (b))
165
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFlags,r,ctxInfo)166 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFlags, r, ctxInfo) {
167 {
168 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
169 EXPECT_EQUAL(All(GreaterThan(Float4(1), Float4(0))), "true");
170
171 Var x(kInt_Type, "x");
172 EXPECT_EQUAL(Declare(x), "int x;");
173 }
174
175 {
176 SkSL::ProgramSettings settings = default_settings();
177 settings.fAllowNarrowingConversions = true;
178 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), settings,
179 SkSL::ProgramKind::kFragment);
180 Var x(kHalf_Type, "x");
181 Var y(kFloat_Type, "y");
182 EXPECT_EQUAL(x.assign(y), "x = half(y)");
183 }
184 }
185
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFloat,r,ctxInfo)186 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFloat, r, ctxInfo) {
187 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
188 Expression e1 = Float(std::numeric_limits<float>::max());
189
190 // We can't use stof here, because old versions of libc++ can throw out_of_range on edge case
191 // inputs like these. (This causes test failure on old Android devices.)
192 REPORTER_ASSERT(r, std::strtof(e1.release()->description().c_str(), nullptr) ==
193 std::numeric_limits<float>::max());
194
195 Expression e2 = Float(std::numeric_limits<float>::min());
196 REPORTER_ASSERT(r, std::strtof(e2.release()->description().c_str(), nullptr) ==
197 std::numeric_limits<float>::min());
198
199 EXPECT_EQUAL(Float2(0),
200 "float2(0.0)");
201 EXPECT_EQUAL(Float2(-0.5, 1),
202 "float2(-0.5, 1.0)");
203 EXPECT_EQUAL(Float3(0.75),
204 "float3(0.75)");
205 EXPECT_EQUAL(Float3(Float2(0, 1), -2),
206 "float3(0.0, 1.0, -2.0)");
207 EXPECT_EQUAL(Float3(0, 1, 2),
208 "float3(0.0, 1.0, 2.0)");
209 EXPECT_EQUAL(Float4(0),
210 "float4(0.0)");
211 EXPECT_EQUAL(Float4(Float2(0, 1), Float2(2, 3)),
212 "float4(0.0, 1.0, 2.0, 3.0)");
213 EXPECT_EQUAL(Float4(0, 1, Float2(2, 3)),
214 "float4(0.0, 1.0, 2.0, 3.0)");
215 EXPECT_EQUAL(Float4(0, 1, 2, 3),
216 "float4(0.0, 1.0, 2.0, 3.0)");
217
218 DSLVar x(kFloat_Type, "x");
219 EXPECT_EQUAL(x.assign(1.0), "x = 1.0");
220 EXPECT_EQUAL(x.assign(1.0f), "x = 1.0");
221
222 DSLVar y(kFloat2_Type, "y");
223 EXPECT_EQUAL(y.x().assign(1.0), "y.x = 1.0");
224 EXPECT_EQUAL(y.x().assign(1.0f), "y.x = 1.0");
225
226 {
227 ExpectError error(r, "value is out of range for type 'float': inf");
228 Float(std::numeric_limits<float>::infinity()).release();
229 }
230
231 {
232 ExpectError error(r, "value is out of range for type 'float': nan");
233 Float(std::numeric_limits<float>::quiet_NaN()).release();
234 }
235
236 {
237 ExpectError error(r, "'float4' is not a valid parameter to 'float2' constructor; use '.xy' "
238 "instead");
239 Float2(Float4(1)).release();
240 }
241
242 {
243 ExpectError error(r, "invalid arguments to 'float4' constructor (expected 4 scalars, but "
244 "found 3)");
245 Float4(Float3(1)).release();
246 }
247 }
248
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLHalf,r,ctxInfo)249 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLHalf, r, ctxInfo) {
250 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
251
252 // We can't use stof here, because old versions of libc++ can throw out_of_range on edge case
253 // inputs like these. (This causes test failure on old Android devices.)
254 Expression e1 = Half(std::numeric_limits<float>::max());
255 REPORTER_ASSERT(r, std::strtof(e1.release()->description().c_str(), nullptr) ==
256 std::numeric_limits<float>::max());
257
258 Expression e2 = Half(std::numeric_limits<float>::min());
259 REPORTER_ASSERT(r, std::strtof(e2.release()->description().c_str(), nullptr) ==
260 std::numeric_limits<float>::min());
261
262 EXPECT_EQUAL(Half2(0),
263 "half2(0.0)");
264 EXPECT_EQUAL(Half2(-0.5, 1),
265 "half2(-0.5, 1.0)");
266 EXPECT_EQUAL(Half3(0.75),
267 "half3(0.75)");
268 EXPECT_EQUAL(Half3(Half2(0, 1), -2),
269 "half3(0.0, 1.0, -2.0)");
270 EXPECT_EQUAL(Half3(0, 1, 2),
271 "half3(0.0, 1.0, 2.0)");
272 EXPECT_EQUAL(Half4(0),
273 "half4(0.0)");
274 EXPECT_EQUAL(Half4(Half2(0, 1), Half2(2, 3)),
275 "half4(0.0, 1.0, 2.0, 3.0)");
276 EXPECT_EQUAL(Half4(0, 1, Half2(2, 3)),
277 "half4(0.0, 1.0, 2.0, 3.0)");
278 EXPECT_EQUAL(Half4(0, 1, 2, 3),
279 "half4(0.0, 1.0, 2.0, 3.0)");
280
281 {
282 ExpectError error(r, "value is out of range for type 'half': inf");
283 Half(std::numeric_limits<float>::infinity()).release();
284 }
285
286 {
287 ExpectError error(r, "value is out of range for type 'half': nan");
288 Half(std::numeric_limits<float>::quiet_NaN()).release();
289 }
290
291 {
292 ExpectError error(r, "'half4' is not a valid parameter to 'half2' constructor; use '.xy' "
293 "instead");
294 Half2(Half4(1)).release();
295 }
296
297 {
298 ExpectError error(r, "invalid arguments to 'half4' constructor (expected 4 scalars, but "
299 "found 3)");
300 Half4(Half3(1)).release();
301 }
302 }
303
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLInt,r,ctxInfo)304 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLInt, r, ctxInfo) {
305 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
306
307 EXPECT_EQUAL(Int(std::numeric_limits<int32_t>::max()),
308 "2147483647");
309 EXPECT_EQUAL(Int2(std::numeric_limits<int32_t>::min()),
310 "int2(-2147483648)");
311 EXPECT_EQUAL(Int2(0, 1),
312 "int2(0, 1)");
313 EXPECT_EQUAL(Int3(0),
314 "int3(0)");
315 EXPECT_EQUAL(Int3(Int2(0, 1), -2),
316 "int3(0, 1, -2)");
317 EXPECT_EQUAL(Int3(0, 1, 2),
318 "int3(0, 1, 2)");
319 EXPECT_EQUAL(Int4(0),
320 "int4(0)");
321 EXPECT_EQUAL(Int4(Int2(0, 1), Int2(2, 3)),
322 "int4(0, 1, 2, 3)");
323 EXPECT_EQUAL(Int4(0, 1, Int2(2, 3)),
324 "int4(0, 1, 2, 3)");
325 EXPECT_EQUAL(Int4(0, 1, 2, 3),
326 "int4(0, 1, 2, 3)");
327
328 {
329 ExpectError error(r, "'int4' is not a valid parameter to 'int2' constructor; use '.xy' "
330 "instead");
331 Int2(Int4(1)).release();
332 }
333
334 {
335 ExpectError error(r, "invalid arguments to 'int4' constructor (expected 4 scalars, but "
336 "found 3)");
337 Int4(Int3(1)).release();
338 }
339 }
340
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLUInt,r,ctxInfo)341 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLUInt, r, ctxInfo) {
342 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
343
344 EXPECT_EQUAL(UInt(std::numeric_limits<uint32_t>::max()),
345 "4294967295");
346 EXPECT_EQUAL(UInt2(std::numeric_limits<uint32_t>::min()),
347 "uint2(0)");
348 EXPECT_EQUAL(UInt2(0, 1),
349 "uint2(0, 1)");
350 EXPECT_EQUAL(UInt3(0),
351 "uint3(0)");
352 EXPECT_EQUAL(UInt3(0, 1, 2),
353 "uint3(0, 1, 2)");
354 EXPECT_EQUAL(UInt4(0),
355 "uint4(0)");
356 EXPECT_EQUAL(UInt4(UInt2(0, 1), UInt2(2, 3)),
357 "uint4(0, 1, 2, 3)");
358 EXPECT_EQUAL(UInt4(0, 1, UInt2(2, 3)),
359 "uint4(0, 1, 2, 3)");
360 EXPECT_EQUAL(UInt4(0, 1, 2, 3),
361 "uint4(0, 1, 2, 3)");
362
363 {
364 ExpectError error(r, "value is out of range for type 'uint': -2");
365 UInt3(UInt2(0, 1), -2).release();
366 }
367
368 {
369 ExpectError error(r, "'uint4' is not a valid parameter to 'uint2' constructor; use '.xy' "
370 "instead");
371 UInt2(UInt4(1)).release();
372 }
373
374 {
375 ExpectError error(r, "invalid arguments to 'uint4' constructor (expected 4 scalars, but "
376 "found 3)");
377 UInt4(UInt3(1)).release();
378 }
379 }
380
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLShort,r,ctxInfo)381 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLShort, r, ctxInfo) {
382 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
383
384 EXPECT_EQUAL(Short(std::numeric_limits<int16_t>::max()),
385 "32767");
386 EXPECT_EQUAL(Short2(std::numeric_limits<int16_t>::min()),
387 "short2(-32768)");
388 EXPECT_EQUAL(Short2(0, 1),
389 "short2(0, 1)");
390 EXPECT_EQUAL(Short3(0),
391 "short3(0)");
392 EXPECT_EQUAL(Short3(Short2(0, 1), -2),
393 "short3(0, 1, -2)");
394 EXPECT_EQUAL(Short3(0, 1, 2),
395 "short3(0, 1, 2)");
396 EXPECT_EQUAL(Short4(0),
397 "short4(0)");
398 EXPECT_EQUAL(Short4(Short2(0, 1), Short2(2, 3)),
399 "short4(0, 1, 2, 3)");
400 EXPECT_EQUAL(Short4(0, 1, Short2(2, 3)),
401 "short4(0, 1, 2, 3)");
402 EXPECT_EQUAL(Short4(0, 1, 2, 3),
403 "short4(0, 1, 2, 3)");
404
405 {
406 ExpectError error(r, "'short4' is not a valid parameter to 'short2' constructor; use '.xy' "
407 "instead");
408 Short2(Short4(1)).release();
409 }
410
411 {
412 ExpectError error(r, "invalid arguments to 'short4' constructor (expected 4 scalars, but "
413 "found 3)");
414 Short4(Short3(1)).release();
415 }
416 }
417
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLUShort,r,ctxInfo)418 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLUShort, r, ctxInfo) {
419 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
420
421 EXPECT_EQUAL(UShort(std::numeric_limits<uint16_t>::max()),
422 "65535");
423 EXPECT_EQUAL(UShort2(std::numeric_limits<uint16_t>::min()),
424 "ushort2(0)");
425 EXPECT_EQUAL(UShort2(0, 1),
426 "ushort2(0, 1)");
427 EXPECT_EQUAL(UShort3(0),
428 "ushort3(0)");
429 EXPECT_EQUAL(UShort3(0, 1, 2),
430 "ushort3(0, 1, 2)");
431 EXPECT_EQUAL(UShort4(0),
432 "ushort4(0)");
433 EXPECT_EQUAL(UShort4(UShort2(0, 1), UShort2(2, 3)),
434 "ushort4(0, 1, 2, 3)");
435 EXPECT_EQUAL(UShort4(0, 1, UShort2(2, 3)),
436 "ushort4(0, 1, 2, 3)");
437 EXPECT_EQUAL(UShort4(0, 1, 2, 3),
438 "ushort4(0, 1, 2, 3)");
439
440 {
441 ExpectError error(r, "value is out of range for type 'ushort': -2");
442 UShort3(UShort2(0, 1), -2).release();
443 }
444
445 {
446 ExpectError error(r, "'ushort4' is not a valid parameter to 'ushort2' constructor; use "
447 "'.xy' instead");
448 UShort2(UShort4(1)).release();
449 }
450
451 {
452 ExpectError error(r, "invalid arguments to 'ushort4' constructor (expected 4 scalars, but "
453 "found 3)");
454 UShort4(UShort3(1)).release();
455 }
456 }
457
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBool,r,ctxInfo)458 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBool, r, ctxInfo) {
459 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
460
461 EXPECT_EQUAL(Bool2(false),
462 "bool2(false)");
463 EXPECT_EQUAL(Bool2(false, true),
464 "bool2(false, true)");
465 EXPECT_EQUAL(Bool3(false),
466 "bool3(false)");
467 EXPECT_EQUAL(Bool3(Bool2(false, true), false),
468 "bool3(false, true, false)");
469 EXPECT_EQUAL(Bool3(false, true, false),
470 "bool3(false, true, false)");
471 EXPECT_EQUAL(Bool4(false),
472 "bool4(false)");
473 EXPECT_EQUAL(Bool4(Bool2(false, true), Bool2(false, true)),
474 "bool4(false, true, false, true)");
475 EXPECT_EQUAL(Bool4(false, true, Bool2(false, true)),
476 "bool4(false, true, false, true)");
477 EXPECT_EQUAL(Bool4(false, true, false, true),
478 "bool4(false, true, false, true)");
479
480 {
481 ExpectError error(r, "'bool4' is not a valid parameter to 'bool2' constructor; use '.xy' "
482 "instead");
483 Bool2(Bool4(true)).release();
484 }
485
486 {
487 ExpectError error(r, "invalid arguments to 'bool4' constructor (expected 4 scalars, but "
488 "found 3)");
489 Bool4(Bool3(true)).release();
490 }
491 }
492
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLType,r,ctxInfo)493 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLType, r, ctxInfo) {
494 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
495 REPORTER_ASSERT(r, DSLType(kBool_Type).isBoolean());
496 REPORTER_ASSERT(r, !DSLType(kBool_Type).isNumber());
497 REPORTER_ASSERT(r, !DSLType(kBool_Type).isFloat());
498 REPORTER_ASSERT(r, !DSLType(kBool_Type).isSigned());
499 REPORTER_ASSERT(r, !DSLType(kBool_Type).isUnsigned());
500 REPORTER_ASSERT(r, !DSLType(kBool_Type).isInteger());
501 REPORTER_ASSERT(r, DSLType(kBool_Type).isScalar());
502 REPORTER_ASSERT(r, !DSLType(kBool_Type).isVector());
503 REPORTER_ASSERT(r, !DSLType(kBool_Type).isMatrix());
504 REPORTER_ASSERT(r, !DSLType(kBool_Type).isArray());
505 REPORTER_ASSERT(r, !DSLType(kBool_Type).isStruct());
506
507 REPORTER_ASSERT(r, !DSLType(kInt_Type).isBoolean());
508 REPORTER_ASSERT(r, DSLType(kInt_Type).isNumber());
509 REPORTER_ASSERT(r, !DSLType(kInt_Type).isFloat());
510 REPORTER_ASSERT(r, DSLType(kInt_Type).isSigned());
511 REPORTER_ASSERT(r, !DSLType(kInt_Type).isUnsigned());
512 REPORTER_ASSERT(r, DSLType(kInt_Type).isInteger());
513 REPORTER_ASSERT(r, DSLType(kInt_Type).isScalar());
514 REPORTER_ASSERT(r, !DSLType(kInt_Type).isVector());
515 REPORTER_ASSERT(r, !DSLType(kInt_Type).isMatrix());
516 REPORTER_ASSERT(r, !DSLType(kInt_Type).isArray());
517 REPORTER_ASSERT(r, !DSLType(kInt_Type).isStruct());
518
519 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isBoolean());
520 REPORTER_ASSERT(r, DSLType(kUInt_Type).isNumber());
521 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isFloat());
522 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isSigned());
523 REPORTER_ASSERT(r, DSLType(kUInt_Type).isUnsigned());
524 REPORTER_ASSERT(r, DSLType(kUInt_Type).isInteger());
525 REPORTER_ASSERT(r, DSLType(kUInt_Type).isScalar());
526 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isVector());
527 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isMatrix());
528 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isArray());
529 REPORTER_ASSERT(r, !DSLType(kUInt_Type).isStruct());
530
531 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isBoolean());
532 REPORTER_ASSERT(r, DSLType(kFloat_Type).isNumber());
533 REPORTER_ASSERT(r, DSLType(kFloat_Type).isFloat());
534 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isSigned());
535 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isUnsigned());
536 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isInteger());
537 REPORTER_ASSERT(r, DSLType(kFloat_Type).isScalar());
538 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isVector());
539 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isMatrix());
540 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isArray());
541 REPORTER_ASSERT(r, !DSLType(kFloat_Type).isStruct());
542
543 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isBoolean());
544 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isNumber());
545 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isFloat());
546 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isSigned());
547 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isUnsigned());
548 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isInteger());
549 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isScalar());
550 REPORTER_ASSERT(r, DSLType(kFloat2_Type).isVector());
551 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isMatrix());
552 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isArray());
553 REPORTER_ASSERT(r, !DSLType(kFloat2_Type).isStruct());
554
555 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isBoolean());
556 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isNumber());
557 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isFloat());
558 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isSigned());
559 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isUnsigned());
560 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isInteger());
561 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isScalar());
562 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isVector());
563 REPORTER_ASSERT(r, DSLType(kHalf2x2_Type).isMatrix());
564 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isArray());
565 REPORTER_ASSERT(r, !DSLType(kHalf2x2_Type).isStruct());
566
567 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isBoolean());
568 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isNumber());
569 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isFloat());
570 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isSigned());
571 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isUnsigned());
572 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isInteger());
573 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isScalar());
574 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isVector());
575 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isMatrix());
576 REPORTER_ASSERT(r, DSLType(Array(kFloat_Type, 2)).isArray());
577 REPORTER_ASSERT(r, !DSLType(Array(kFloat_Type, 2)).isStruct());
578
579 Var x(kFloat_Type, "x");
580 DSLExpression e = x + 1;
581 REPORTER_ASSERT(r, e.type().isFloat());
582 e.release();
583
584 {
585 ExpectError error(r, "array size must be positive");
586 Array(kFloat_Type, -1);
587 }
588
589 {
590 ExpectError error(r, "multi-dimensional arrays are not supported");
591 Array(Array(kFloat_Type, 2), 2);
592 }
593 }
594
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMatrices,r,ctxInfo)595 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMatrices, r, ctxInfo) {
596 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
597 Var f22(kFloat2x2_Type, "f22");
598 EXPECT_EQUAL(f22.assign(Float2x2(1)), "f22 = float2x2(1.0)");
599 Var f32(kFloat3x2_Type, "f32");
600 EXPECT_EQUAL(f32.assign(Float3x2(1, 2, 3, 4, 5, 6)),
601 "f32 = float3x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)");
602 Var f42(kFloat4x2_Type, "f42");
603 EXPECT_EQUAL(f42.assign(Float4x2(Float4(1, 2, 3, 4), 5, 6, 7, 8)),
604 "f42 = float4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)");
605 Var f23(kFloat2x3_Type, "f23");
606 EXPECT_EQUAL(f23.assign(Float2x3(1, Float2(2, 3), 4, Float2(5, 6))),
607 "f23 = float2x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)");
608 Var f33(kFloat3x3_Type, "f33");
609 EXPECT_EQUAL(f33.assign(Float3x3(Float3(1, 2, 3), 4, Float2(5, 6), 7, 8, 9)),
610 "f33 = float3x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)");
611 Var f43(kFloat4x3_Type, "f43");
612 EXPECT_EQUAL(f43.assign(Float4x3(Float4(1, 2, 3, 4), Float4(5, 6, 7, 8), Float4(9, 10, 11,12))),
613 "f43 = float4x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0)");
614 Var f24(kFloat2x4_Type, "f24");
615 EXPECT_EQUAL(f24.assign(Float2x4(1, 2, 3, 4, 5, 6, 7, 8)),
616 "f24 = float2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)");
617 Var f34(kFloat3x4_Type, "f34");
618 EXPECT_EQUAL(f34.assign(Float3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, Float3(10, 11, 12))),
619 "f34 = float3x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0)");
620 Var f44(kFloat4x4_Type, "f44");
621 EXPECT_EQUAL(f44.assign(Float4x4(1)), "f44 = float4x4(1.0)");
622
623 Var h22(kHalf2x2_Type, "h22");
624 EXPECT_EQUAL(h22.assign(Half2x2(1)), "h22 = half2x2(1.0)");
625 Var h32(kHalf3x2_Type, "h32");
626 EXPECT_EQUAL(h32.assign(Half3x2(1, 2, 3, 4, 5, 6)),
627 "h32 = half3x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)");
628 Var h42(kHalf4x2_Type, "h42");
629 EXPECT_EQUAL(h42.assign(Half4x2(Half4(1, 2, 3, 4), 5, 6, 7, 8)),
630 "h42 = half4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)");
631 Var h23(kHalf2x3_Type, "h23");
632 EXPECT_EQUAL(h23.assign(Half2x3(1, Half2(2, 3), 4, Half2(5, 6))),
633 "h23 = half2x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)");
634 Var h33(kHalf3x3_Type, "h33");
635 EXPECT_EQUAL(h33.assign(Half3x3(Half3(1, 2, 3), 4, Half2(5, 6), 7, 8, 9)),
636 "h33 = half3x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)");
637 Var h43(kHalf4x3_Type, "h43");
638 EXPECT_EQUAL(h43.assign(Half4x3(Half4(1, 2, 3, 4), Half4(5, 6, 7, 8), Half4(9, 10, 11, 12))),
639 "h43 = half4x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0)");
640 Var h24(kHalf2x4_Type, "h24");
641 EXPECT_EQUAL(h24.assign(Half2x4(1, 2, 3, 4, 5, 6, 7, 8)),
642 "h24 = half2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)");
643 Var h34(kHalf3x4_Type, "h34");
644 EXPECT_EQUAL(h34.assign(Half3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, Half3(10, 11, 12))),
645 "h34 = half3x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0)");
646 Var h44(kHalf4x4_Type, "h44");
647 EXPECT_EQUAL(h44.assign(Half4x4(1)), "h44 = half4x4(1.0)");
648
649 EXPECT_EQUAL(f22 * 2, "f22 * 2.0");
650 EXPECT_EQUAL(f22 == Float2x2(1), "f22 == float2x2(1.0)");
651 EXPECT_EQUAL(h42[0][1], "h42[0].y");
652 EXPECT_EQUAL(f43 * Float4(0), "float3(0.0)");
653 EXPECT_EQUAL(h23 * 2, "h23 * 2.0");
654 EXPECT_EQUAL(Inverse(f44), "inverse(f44)");
655
656 {
657 ExpectError error(r, "invalid arguments to 'float3x3' constructor (expected 9 scalars, but "
658 "found 2)");
659 DSLExpression(Float3x3(Float2(1))).release();
660 }
661
662 {
663 ExpectError error(r, "invalid arguments to 'half2x2' constructor (expected 4 scalars, but "
664 "found 5)");
665 DSLExpression(Half2x2(1, 2, 3, 4, 5)).release();
666 }
667
668 {
669 ExpectError error(r, "type mismatch: '*' cannot operate on 'float4x3', 'float3'");
670 DSLExpression(f43 * Float3(1)).release();
671 }
672
673 {
674 ExpectError error(r, "type mismatch: '=' cannot operate on 'float4x3', 'float3x3'");
675 DSLExpression(f43.assign(f33)).release();
676 }
677
678 {
679 ExpectError error(r, "type mismatch: '=' cannot operate on 'half2x2', 'float2x2'");
680 DSLExpression(h22.assign(f22)).release();
681 }
682
683 {
684 ExpectError error(r, "no match for inverse(float4x3)");
685 DSLExpression(Inverse(f43)).release();
686 }
687 }
688
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLPlus,r,ctxInfo)689 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLPlus, r, ctxInfo) {
690 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
691 Var a(kFloat_Type, "a"), b(kFloat_Type, "b");
692
693 EXPECT_EQUAL(a + b,
694 "a + b");
695 EXPECT_EQUAL(a + 1,
696 "a + 1.0");
697 EXPECT_EQUAL(0.5 + a + -99,
698 "(0.5 + a) + -99.0");
699 EXPECT_EQUAL(a += b + 1,
700 "a += b + 1.0");
701 EXPECT_EQUAL(+a,
702 "a");
703 EXPECT_EQUAL(+(a + b),
704 "a + b");
705
706 {
707 ExpectError error(r, "type mismatch: '+' cannot operate on 'bool2', 'float'");
708 DSLExpression((Bool2(true) + a)).release();
709 }
710
711 {
712 ExpectError error(r, "type mismatch: '+=' cannot operate on 'float', 'bool2'");
713 DSLExpression((a += Bool2(true))).release();
714 }
715
716 {
717 ExpectError error(r, "cannot assign to this expression");
718 DSLExpression((1.0 += a)).release();
719 }
720
721 {
722 ExpectError error(r, "'+' cannot operate on 'bool'");
723 Var c(kBool_Type, "c");
724 DSLExpression(+c).release();
725 }
726 }
727
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMinus,r,ctxInfo)728 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMinus, r, ctxInfo) {
729 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
730 Var a(kInt_Type, "a"), b(kInt_Type, "b");
731
732 EXPECT_EQUAL(a - b,
733 "a - b");
734 EXPECT_EQUAL(a - 1,
735 "a - 1");
736 EXPECT_EQUAL(2 - a - b,
737 "(2 - a) - b");
738 EXPECT_EQUAL(a -= b + 1,
739 "a -= b + 1");
740 EXPECT_EQUAL(-a,
741 "-a");
742 EXPECT_EQUAL(-(a - b),
743 "-(a - b)");
744
745 {
746 ExpectError error(r, "type mismatch: '-' cannot operate on 'bool2', 'int'");
747 DSLExpression(Bool2(true) - a).release();
748 }
749
750 {
751 ExpectError error(r, "type mismatch: '-=' cannot operate on 'int', 'bool2'");
752 DSLExpression(a -= Bool2(true)).release();
753 }
754
755 {
756 ExpectError error(r, "cannot assign to this expression");
757 DSLExpression(1.0 -= a).release();
758 }
759
760 {
761 ExpectError error(r, "'-' cannot operate on 'bool'");
762 Var c(kBool_Type, "c");
763 DSLExpression(-c).release();
764 }
765 }
766
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMultiply,r,ctxInfo)767 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMultiply, r, ctxInfo) {
768 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
769 Var a(kFloat_Type, "a"), b(kFloat_Type, "b");
770
771 EXPECT_EQUAL(a * b,
772 "a * b");
773 EXPECT_EQUAL(a * 2,
774 "a * 2.0");
775 EXPECT_EQUAL(0.5 * a * -99,
776 "(0.5 * a) * -99.0");
777 EXPECT_EQUAL(a *= b + 1,
778 "a *= b + 1.0");
779
780 {
781 ExpectError error(r, "type mismatch: '*' cannot operate on 'bool2', 'float'");
782 DSLExpression(Bool2(true) * a).release();
783 }
784
785 {
786 ExpectError error(r, "type mismatch: '*=' cannot operate on 'float', 'bool2'");
787 DSLExpression(a *= Bool2(true)).release();
788 }
789
790 {
791 ExpectError error(r, "cannot assign to this expression");
792 DSLExpression(1.0 *= a).release();
793 }
794 }
795
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDivide,r,ctxInfo)796 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDivide, r, ctxInfo) {
797 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
798 Var a(kFloat_Type, "a"), b(kFloat_Type, "b");
799
800 EXPECT_EQUAL(a / b,
801 "a / b");
802 EXPECT_EQUAL(a / 2,
803 "a * 0.5");
804 EXPECT_EQUAL(0.5 / a / -100,
805 "(0.5 / a) * -0.01");
806 EXPECT_EQUAL(b / (a - 1),
807 "b / (a - 1.0)");
808 EXPECT_EQUAL(a /= b + 1,
809 "a /= b + 1.0");
810
811 {
812 ExpectError error(r, "type mismatch: '/' cannot operate on 'bool2', 'float'");
813 DSLExpression(Bool2(true) / a).release();
814 }
815
816 {
817 ExpectError error(r, "type mismatch: '/=' cannot operate on 'float', 'bool2'");
818 DSLExpression(a /= Bool2(true)).release();
819 }
820
821 {
822 ExpectError error(r, "cannot assign to this expression");
823 DSLExpression(1.0 /= a).release();
824 }
825
826 {
827 ExpectError error(r, "division by zero");
828 DSLExpression(a /= 0).release();
829 }
830
831 {
832 Var c(kFloat2_Type, "c");
833 ExpectError error(r, "division by zero");
834 DSLExpression(c /= Float2(Float(0), 1)).release();
835 }
836 }
837
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMod,r,ctxInfo)838 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLMod, r, ctxInfo) {
839 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
840 Var a(kInt_Type, "a"), b(kInt_Type, "b");
841 Expression e1 = a % b;
842 EXPECT_EQUAL(e1, "a % b");
843
844 Expression e2 = a % 2;
845 EXPECT_EQUAL(e2, "a % 2");
846
847 Expression e3 = 10 % a % -99;
848 EXPECT_EQUAL(e3, "(10 % a) % -99");
849
850 Expression e4 = a %= b + 1;
851 EXPECT_EQUAL(e4, "a %= b + 1");
852
853 {
854 ExpectError error(r, "type mismatch: '%' cannot operate on 'bool2', 'int'");
855 DSLExpression(Bool2(true) % a).release();
856 }
857
858 {
859 ExpectError error(r, "type mismatch: '%=' cannot operate on 'int', 'bool2'");
860 DSLExpression(a %= Bool2(true)).release();
861 }
862
863 {
864 ExpectError error(r, "cannot assign to this expression");
865 DSLExpression(1 %= a).release();
866 }
867
868 {
869 ExpectError error(r, "division by zero");
870 DSLExpression(a %= 0).release();
871 }
872
873 {
874 Var c(kInt2_Type, "c");
875 ExpectError error(r, "division by zero");
876 DSLExpression(c %= Int2(Int(0), 1)).release();
877 }
878 }
879
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLShl,r,ctxInfo)880 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLShl, r, ctxInfo) {
881 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
882 Var a(kInt_Type, "a"), b(kInt_Type, "b");
883 Expression e1 = a << b;
884 EXPECT_EQUAL(e1, "a << b");
885
886 Expression e2 = a << 1;
887 EXPECT_EQUAL(e2, "a << 1");
888
889 Expression e3 = 1 << a << 2;
890 EXPECT_EQUAL(e3, "(1 << a) << 2");
891
892 Expression e4 = a <<= b + 1;
893 EXPECT_EQUAL(e4, "a <<= b + 1");
894
895 {
896 ExpectError error(r, "type mismatch: '<<' cannot operate on 'bool2', 'int'");
897 DSLExpression(Bool2(true) << a).release();
898 }
899
900 {
901 ExpectError error(r, "type mismatch: '<<=' cannot operate on 'int', 'bool2'");
902 DSLExpression(a <<= Bool2(true)).release();
903 }
904
905 {
906 ExpectError error(r, "cannot assign to this expression");
907 DSLExpression(1 <<= a).release();
908 }
909 }
910
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLShr,r,ctxInfo)911 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLShr, r, ctxInfo) {
912 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
913 Var a(kInt_Type, "a"), b(kInt_Type, "b");
914 Expression e1 = a >> b;
915 EXPECT_EQUAL(e1, "a >> b");
916
917 Expression e2 = a >> 1;
918 EXPECT_EQUAL(e2, "a >> 1");
919
920 Expression e3 = 1 >> a >> 2;
921 EXPECT_EQUAL(e3, "(1 >> a) >> 2");
922
923 Expression e4 = a >>= b + 1;
924 EXPECT_EQUAL(e4, "a >>= b + 1");
925
926 {
927 ExpectError error(r, "type mismatch: '>>' cannot operate on 'bool2', 'int'");
928 DSLExpression(Bool2(true) >> a).release();
929 }
930
931 {
932 ExpectError error(r, "type mismatch: '>>=' cannot operate on 'int', 'bool2'");
933 DSLExpression(a >>= Bool2(true)).release();
934 }
935
936 {
937 ExpectError error(r, "cannot assign to this expression");
938 DSLExpression(1 >>= a).release();
939 }
940 }
941
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseAnd,r,ctxInfo)942 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseAnd, r, ctxInfo) {
943 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
944 Var a(kInt_Type, "a"), b(kInt_Type, "b");
945 Expression e1 = a & b;
946 EXPECT_EQUAL(e1, "a & b");
947
948 Expression e2 = a & 1;
949 EXPECT_EQUAL(e2, "a & 1");
950
951 Expression e3 = 1 & a & 2;
952 EXPECT_EQUAL(e3, "(1 & a) & 2");
953
954 Expression e4 = a &= b + 1;
955 EXPECT_EQUAL(e4, "a &= b + 1");
956
957 {
958 ExpectError error(r, "type mismatch: '&' cannot operate on 'bool2', 'int'");
959 DSLExpression(Bool2(true) & a).release();
960 }
961
962 {
963 ExpectError error(r, "type mismatch: '&=' cannot operate on 'int', 'bool2'");
964 DSLExpression(a &= Bool2(true)).release();
965 }
966
967 {
968 ExpectError error(r, "cannot assign to this expression");
969 DSLExpression(1 &= a).release();
970 }
971 }
972
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseOr,r,ctxInfo)973 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseOr, r, ctxInfo) {
974 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
975 Var a(kInt_Type, "a"), b(kInt_Type, "b");
976 Expression e1 = a | b;
977 EXPECT_EQUAL(e1, "a | b");
978
979 Expression e2 = a | 1;
980 EXPECT_EQUAL(e2, "a | 1");
981
982 Expression e3 = 1 | a | 2;
983 EXPECT_EQUAL(e3, "(1 | a) | 2");
984
985 Expression e4 = a |= b + 1;
986 EXPECT_EQUAL(e4, "a |= b + 1");
987
988 {
989 ExpectError error(r, "type mismatch: '|' cannot operate on 'bool2', 'int'");
990 DSLExpression(Bool2(true) | a).release();
991 }
992
993 {
994 ExpectError error(r, "type mismatch: '|=' cannot operate on 'int', 'bool2'");
995 DSLExpression(a |= Bool2(true)).release();
996 }
997
998 {
999 ExpectError error(r, "cannot assign to this expression");
1000 DSLExpression(1 |= a).release();
1001 }
1002 }
1003
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseXor,r,ctxInfo)1004 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseXor, r, ctxInfo) {
1005 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1006 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1007 Expression e1 = a ^ b;
1008 EXPECT_EQUAL(e1, "a ^ b");
1009
1010 Expression e2 = a ^ 1;
1011 EXPECT_EQUAL(e2, "a ^ 1");
1012
1013 Expression e3 = 1 ^ a ^ 2;
1014 EXPECT_EQUAL(e3, "(1 ^ a) ^ 2");
1015
1016 Expression e4 = a ^= b + 1;
1017 EXPECT_EQUAL(e4, "a ^= b + 1");
1018
1019 {
1020 ExpectError error(r, "type mismatch: '^' cannot operate on 'bool2', 'int'");
1021 DSLExpression(Bool2(true) ^ a).release();
1022 }
1023
1024 {
1025 ExpectError error(r, "type mismatch: '^=' cannot operate on 'int', 'bool2'");
1026 DSLExpression(a ^= Bool2(true)).release();
1027 }
1028
1029 {
1030 ExpectError error(r, "cannot assign to this expression");
1031 DSLExpression(1 ^= a).release();
1032 }
1033 }
1034
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalAnd,r,ctxInfo)1035 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalAnd, r, ctxInfo) {
1036 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1037 Var a(kBool_Type, "a"), b(kBool_Type, "b");
1038 Expression e1 = a && b;
1039 EXPECT_EQUAL(e1, "a && b");
1040
1041 Expression e2 = a && true && b;
1042 EXPECT_EQUAL(e2, "a && b");
1043
1044 Expression e3 = a && false && b;
1045 EXPECT_EQUAL(e3, "false");
1046
1047 {
1048 ExpectError error(r, "type mismatch: '&&' cannot operate on 'bool', 'int'");
1049 DSLExpression(a && 5).release();
1050 }
1051 }
1052
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalOr,r,ctxInfo)1053 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalOr, r, ctxInfo) {
1054 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1055 Var a(kBool_Type, "a"), b(kBool_Type, "b");
1056 Expression e1 = a || b;
1057 EXPECT_EQUAL(e1, "a || b");
1058
1059 Expression e2 = a || true || b;
1060 EXPECT_EQUAL(e2, "true");
1061
1062 Expression e3 = a || false || b;
1063 EXPECT_EQUAL(e3, "a || b");
1064
1065 {
1066 ExpectError error(r, "type mismatch: '||' cannot operate on 'bool', 'int'");
1067 DSLExpression(a || 5).release();
1068 }
1069 }
1070
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalXor,r,ctxInfo)1071 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalXor, r, ctxInfo) {
1072 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1073 Var a(kBool_Type, "a"), b(kBool_Type, "b");
1074 Expression e1 = LogicalXor(a, b);
1075 EXPECT_EQUAL(e1, "a ^^ b");
1076
1077 {
1078 ExpectError error(r, "type mismatch: '^^' cannot operate on 'bool', 'int'");
1079 DSLExpression(LogicalXor(a, 5)).release();
1080 }
1081 }
1082
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLComma,r,ctxInfo)1083 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLComma, r, ctxInfo) {
1084 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1085 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1086 Expression e1 = (a += b, b);
1087 EXPECT_EQUAL(e1, "(a += b, b)");
1088
1089 Expression e2 = (a += b, b += b, Int2(a));
1090 EXPECT_EQUAL(e2, "((a += b, b += b), int2(a))");
1091 }
1092
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLEqual,r,ctxInfo)1093 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLEqual, r, ctxInfo) {
1094 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1095 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1096 Expression e1 = a == b;
1097 EXPECT_EQUAL(e1, "a == b");
1098
1099 Expression e2 = a == 5;
1100 EXPECT_EQUAL(e2, "a == 5");
1101
1102 {
1103 ExpectError error(r, "type mismatch: '==' cannot operate on 'int', 'bool2'");
1104 DSLExpression(a == Bool2(true)).release();
1105 }
1106 }
1107
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLNotEqual,r,ctxInfo)1108 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLNotEqual, r, ctxInfo) {
1109 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1110 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1111 Expression e1 = a != b;
1112 EXPECT_EQUAL(e1, "a != b");
1113
1114 Expression e2 = a != 5;
1115 EXPECT_EQUAL(e2, "a != 5");
1116
1117 {
1118 ExpectError error(r, "type mismatch: '!=' cannot operate on 'int', 'bool2'");
1119 DSLExpression(a != Bool2(true)).release();
1120 }
1121 }
1122
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLGreaterThan,r,ctxInfo)1123 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLGreaterThan, r, ctxInfo) {
1124 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1125 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1126 Expression e1 = a > b;
1127 EXPECT_EQUAL(e1, "a > b");
1128
1129 Expression e2 = a > 5;
1130 EXPECT_EQUAL(e2, "a > 5");
1131
1132 {
1133 ExpectError error(r, "type mismatch: '>' cannot operate on 'int', 'bool2'");
1134 DSLExpression(a > Bool2(true)).release();
1135 }
1136 }
1137
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLGreaterThanOrEqual,r,ctxInfo)1138 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLGreaterThanOrEqual, r, ctxInfo) {
1139 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1140 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1141 Expression e1 = a >= b;
1142 EXPECT_EQUAL(e1, "a >= b");
1143
1144 Expression e2 = a >= 5;
1145 EXPECT_EQUAL(e2, "a >= 5");
1146
1147 {
1148 ExpectError error(r, "type mismatch: '>=' cannot operate on 'int', 'bool2'");
1149 DSLExpression(a >= Bool2(true)).release();
1150 }
1151 }
1152
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLessThan,r,ctxInfo)1153 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLessThan, r, ctxInfo) {
1154 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1155 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1156 Expression e1 = a < b;
1157 EXPECT_EQUAL(e1, "a < b");
1158
1159 Expression e2 = a < 5;
1160 EXPECT_EQUAL(e2, "a < 5");
1161
1162 {
1163 ExpectError error(r, "type mismatch: '<' cannot operate on 'int', 'bool2'");
1164 DSLExpression(a < Bool2(true)).release();
1165 }
1166 }
1167
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLessThanOrEqual,r,ctxInfo)1168 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLessThanOrEqual, r, ctxInfo) {
1169 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1170 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1171 Expression e1 = a <= b;
1172 EXPECT_EQUAL(e1, "a <= b");
1173
1174 Expression e2 = a <= 5;
1175 EXPECT_EQUAL(e2, "a <= 5");
1176
1177 {
1178 ExpectError error(r, "type mismatch: '<=' cannot operate on 'int', 'bool2'");
1179 DSLExpression(a <= Bool2(true)).release();
1180 }
1181 }
1182
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalNot,r,ctxInfo)1183 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLogicalNot, r, ctxInfo) {
1184 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1185 Var a(kInt_Type, "a"), b(kInt_Type, "b");
1186 Expression e1 = !(a <= b);
1187 EXPECT_EQUAL(e1, "!(a <= b)");
1188
1189 {
1190 ExpectError error(r, "'!' cannot operate on 'int'");
1191 DSLExpression(!a).release();
1192 }
1193 }
1194
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseNot,r,ctxInfo)1195 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBitwiseNot, r, ctxInfo) {
1196 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1197 Var a(kInt_Type, "a"), b(kBool_Type, "b");
1198 Expression e1 = ~a;
1199 EXPECT_EQUAL(e1, "~a");
1200
1201 {
1202 ExpectError error(r, "'~' cannot operate on 'bool'");
1203 DSLExpression(~b).release();
1204 }
1205 }
1206
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLIncrement,r,ctxInfo)1207 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLIncrement, r, ctxInfo) {
1208 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1209 Var a(kInt_Type, "a"), b(kBool_Type, "b");
1210 Expression e1 = ++a;
1211 EXPECT_EQUAL(e1, "++a");
1212
1213 Expression e2 = a++;
1214 EXPECT_EQUAL(e2, "a++");
1215
1216 {
1217 ExpectError error(r, "'++' cannot operate on 'bool'");
1218 DSLExpression(++b).release();
1219 }
1220
1221 {
1222 ExpectError error(r, "'++' cannot operate on 'bool'");
1223 DSLExpression(b++).release();
1224 }
1225
1226 {
1227 ExpectError error(r, "cannot assign to this expression");
1228 DSLExpression(++(a + 1)).release();
1229 }
1230
1231 {
1232 ExpectError error(r, "cannot assign to this expression");
1233 DSLExpression((a + 1)++).release();
1234 }
1235 }
1236
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDecrement,r,ctxInfo)1237 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDecrement, r, ctxInfo) {
1238 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1239 Var a(kInt_Type, "a"), b(kBool_Type, "b");
1240 Expression e1 = --a;
1241 EXPECT_EQUAL(e1, "--a");
1242
1243 Expression e2 = a--;
1244 EXPECT_EQUAL(e2, "a--");
1245
1246 {
1247 ExpectError error(r, "'--' cannot operate on 'bool'");
1248 DSLExpression(--b).release();
1249 }
1250
1251 {
1252 ExpectError error(r, "'--' cannot operate on 'bool'");
1253 DSLExpression(b--).release();
1254 }
1255
1256 {
1257 ExpectError error(r, "cannot assign to this expression");
1258 DSLExpression(--(a + 1)).release();
1259 }
1260
1261 {
1262 ExpectError error(r, "cannot assign to this expression");
1263 DSLExpression((a + 1)--).release();
1264 }
1265 }
1266
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLCall,r,ctxInfo)1267 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLCall, r, ctxInfo) {
1268 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1269 {
1270 DSLExpression sqrt(SkSL::ThreadContext::Compiler().convertIdentifier(SkSL::Position(),
1271 "sqrt"));
1272 SkTArray<DSLExpression> args;
1273 args.emplace_back(16);
1274 EXPECT_EQUAL(sqrt(std::move(args)), "4.0"); // sqrt(16) gets optimized to 4
1275 }
1276
1277 {
1278 DSLExpression pow(SkSL::ThreadContext::Compiler().convertIdentifier(SkSL::Position(),
1279 "pow"));
1280 DSLVar a(kFloat_Type, "a");
1281 DSLVar b(kFloat_Type, "b");
1282 SkTArray<DSLExpression> args;
1283 args.emplace_back(a);
1284 args.emplace_back(b);
1285 EXPECT_EQUAL(pow(std::move(args)), "pow(a, b)");
1286 }
1287 }
1288
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBlock,r,ctxInfo)1289 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBlock, r, ctxInfo) {
1290 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1291 EXPECT_EQUAL(Block(), "{ }");
1292 Var a(kInt_Type, "a", 1), b(kInt_Type, "b", 2);
1293 EXPECT_EQUAL(Block(Declare(a), Declare(b), a.assign(b)), "{ int a = 1; int b = 2; a = b; }");
1294
1295 EXPECT_EQUAL((If(a > 0, --a), ++b), "if (a > 0) --a; ++b;");
1296
1297 SkTArray<DSLStatement> statements;
1298 statements.push_back(a.assign(0));
1299 statements.push_back(++a);
1300 EXPECT_EQUAL(Block(std::move(statements)), "{ a = 0; ++a; }");
1301 }
1302
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBreak,r,ctxInfo)1303 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBreak, r, ctxInfo) {
1304 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1305 Var i(kInt_Type, "i", 0);
1306 DSLFunction(kVoid_Type, "success").define(
1307 For(Declare(i), i < 10, ++i, Block(
1308 If(i > 5, Break())
1309 ))
1310 );
1311 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
1312 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
1313 "void success() { for (int i = 0; i < 10; ++i) { if (i > 5) break; } }");
1314
1315 {
1316 ExpectError error(r, "break statement must be inside a loop or switch");
1317 DSLFunction(kVoid_Type, "fail").define(
1318 Break()
1319 );
1320 }
1321 }
1322
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLContinue,r,ctxInfo)1323 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLContinue, r, ctxInfo) {
1324 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1325 Var i(kInt_Type, "i", 0);
1326 DSLFunction(kVoid_Type, "success").define(
1327 For(Declare(i), i < 10, ++i, Block(
1328 If(i < 5, Continue())
1329 ))
1330 );
1331 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
1332 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
1333 "void success() { for (int i = 0; i < 10; ++i) { if (i < 5) continue; } }");
1334
1335 {
1336 ExpectError error(r, "continue statement must be inside a loop");
1337 DSLFunction(kVoid_Type, "fail").define(
1338 Continue()
1339 );
1340 }
1341 }
1342
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDeclare,r,ctxInfo)1343 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDeclare, r, ctxInfo) {
1344 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1345 {
1346 Var a(kHalf4_Type, "a"), b(kHalf4_Type, "b", Half4(1));
1347 EXPECT_EQUAL(Declare(a), "half4 a;");
1348 EXPECT_EQUAL(Declare(b), "half4 b = half4(1.0);");
1349 }
1350
1351 {
1352 DSLWriter::Reset();
1353 SkTArray<Var> vars;
1354 vars.push_back(Var(kBool_Type, "a", true));
1355 vars.push_back(Var(kFloat_Type, "b"));
1356 EXPECT_EQUAL(Declare(vars), "bool a = true; float b;");
1357 }
1358
1359 {
1360 DSLWriter::Reset();
1361 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().empty());
1362 GlobalVar a(kHalf4_Type, "a"), b(kHalf4_Type, "b", Half4(1));
1363 Declare(a);
1364 Declare(b);
1365 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
1366 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "half4 a;");
1367 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "half4 b = half4(1.0);");
1368 }
1369
1370 {
1371 DSLWriter::Reset();
1372 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().empty());
1373 SkTArray<GlobalVar> vars;
1374 vars.push_back(GlobalVar(kHalf4_Type, "a"));
1375 vars.push_back(GlobalVar(kHalf4_Type, "b", Half4(1)));
1376 Declare(vars);
1377 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
1378 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "half4 a;");
1379 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "half4 b = half4(1.0);");
1380 }
1381
1382 {
1383 DSLWriter::Reset();
1384 Var a(kHalf4_Type, "a", 1);
1385 ExpectError error(r, "expected 'half4', but found 'int'");
1386 Declare(a).release();
1387 }
1388
1389 {
1390 DSLWriter::Reset();
1391 Var a(kUniform_Modifier, kInt_Type, "a");
1392 ExpectError error(r, "'uniform' is not permitted here");
1393 Declare(a).release();
1394 }
1395 }
1396
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDeclareGlobal,r,ctxInfo)1397 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDeclareGlobal, r, ctxInfo) {
1398 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1399 DSLGlobalVar x(kInt_Type, "x", 0);
1400 Declare(x);
1401 DSLGlobalVar y(kUniform_Modifier, kFloat2_Type, "y");
1402 Declare(y);
1403 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
1404 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "int x = 0;");
1405 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "uniform float2 y;");
1406 }
1407
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDiscard,r,ctxInfo)1408 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDiscard, r, ctxInfo) {
1409 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1410 Var x(kFloat_Type, "x", 1);
1411 EXPECT_EQUAL(If(Sqrt(x) > 0, Discard()), "if (sqrt(x) > 0.0) discard;");
1412 }
1413
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDo,r,ctxInfo)1414 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLDo, r, ctxInfo) {
1415 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1416 Statement x = Do(Block(), true);
1417 EXPECT_EQUAL(x, "do {} while (true);");
1418
1419 Var a(kFloat_Type, "a"), b(kFloat_Type, "b");
1420 Statement y = Do(Block(a++, --b), a != b);
1421 EXPECT_EQUAL(y, "do { a++; --b; } while (a != b);");
1422
1423 {
1424 ExpectError error(r, "expected 'bool', but found 'int'");
1425 Do(Block(), 7).release();
1426 }
1427 }
1428
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFor,r,ctxInfo)1429 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFor, r, ctxInfo) {
1430 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1431 EXPECT_EQUAL(For(Statement(), Expression(), Expression(), Block()),
1432 "for (;;) {}");
1433
1434 Var i(kInt_Type, "i", 0);
1435 EXPECT_EQUAL(For(Declare(i), i < 10, ++i, i += 5),
1436 "for (int i = 0; i < 10; ++i) i += 5;");
1437
1438 Var j(kInt_Type, "j", 0);
1439 Var k(kInt_Type, "k", 10);
1440 EXPECT_EQUAL(For((Declare(j), Declare(k)), j < k, ++j, Block()), R"(
1441 {
1442 int j = 0;
1443 int k = 10;
1444 for (; j < k; ++j) {}
1445 }
1446 )");
1447
1448 {
1449 ExpectError error(r, "expected 'bool', but found 'int'");
1450 For(i.assign(0), i + 10, ++i, i += 5).release();
1451 }
1452
1453 {
1454 ExpectError error(r, "invalid for loop initializer");
1455 For(If(i == 0, i.assign(1)), i < 10, ++i, i += 5).release();
1456 }
1457 }
1458
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFunction,r,ctxInfo)1459 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLFunction, r, ctxInfo) {
1460 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1461 {
1462 DSLWriter::Reset();
1463 DSLParameter x(kFloat_Type, "x");
1464 DSLFunction sqr(kFloat_Type, "sqr", x);
1465 sqr.define(
1466 Return(x * x)
1467 );
1468 DSLVar a(kFloat2_Type, "a");
1469 EXPECT_EQUAL(sqr(a.x()), "sqr(a.x)");
1470 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
1471 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
1472 "float sqr(float x) { return x * x; }");
1473 }
1474
1475 {
1476 DSLWriter::Reset();
1477 DSLParameter x(kFloat2_Type, "x");
1478 DSLParameter y(kFloat2_Type, "y");
1479 DSLFunction squareSum(
1480 DSLModifiers(SkSL::Modifiers::kInline_Flag), kFloat2_Type, "SquareSum", x, y);
1481 squareSum.define(
1482 Return(x * x + y * y)
1483 );
1484 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
1485 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
1486 "inline float2 SquareSum(float2 x, float2 y) { return x * x + y * y; }");
1487 EXPECT_EQUAL(squareSum(Float2(1.0f, 2.0f), Float2(3.0f, 4.0f)),
1488 "SquareSum(float2(1.0, 2.0), float2(3.0, 4.0))");
1489 }
1490
1491 {
1492 DSLWriter::Reset();
1493 DSLParameter x(kFloat_Type, "x");
1494 DSLParameter y(kFloat_Type, "y");
1495 DSLFunction pair(kFloat2_Type, "pair", x, y);
1496 pair.define(
1497 Return(Float2(x, y))
1498 );
1499 Var varArg1(kFloat_Type, "varArg1");
1500 Var varArg2(kFloat_Type, "varArg2");
1501 EXPECT_EQUAL(pair(varArg1, varArg2), "pair(varArg1, varArg2)");
1502 }
1503
1504 {
1505 ExpectError error(r, "expected 'float', but found 'bool'");
1506 DSLWriter::Reset();
1507 DSLFunction(kFloat_Type, "broken").define(
1508 Return(true)
1509 );
1510 }
1511
1512 {
1513 ExpectError error(r, "expected function to return 'float'");
1514 DSLWriter::Reset();
1515 DSLFunction(kFloat_Type, "broken").define(
1516 Return()
1517 );
1518 }
1519
1520 {
1521 ExpectError error(r, "function 'broken' can exit without returning a value");
1522 DSLWriter::Reset();
1523 Var x(kFloat_Type, "x", 0);
1524 DSLFunction(kFloat_Type, "broken").define(
1525 Declare(x),
1526 If(x == 1, Return(x))
1527 );
1528 }
1529
1530 {
1531 ExpectError error(r, "may not return a value from a void function");
1532 DSLWriter::Reset();
1533 DSLFunction(kVoid_Type, "broken").define(
1534 Return(0)
1535 );
1536 }
1537
1538 {
1539 ExpectError error(r, "function 'broken' can exit without returning a value");
1540 DSLWriter::Reset();
1541 DSLFunction(kFloat_Type, "broken").define(
1542 );
1543 }
1544 }
1545
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLIf,r,ctxInfo)1546 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLIf, r, ctxInfo) {
1547 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1548 Var a(kFloat_Type, "a"), b(kFloat_Type, "b");
1549 Statement x = If(a > b, a -= b);
1550 EXPECT_EQUAL(x, "if (a > b) a -= b;");
1551
1552 Statement y = If(a > b, a -= b, b -= a);
1553 EXPECT_EQUAL(y, "if (a > b) a -= b; else b -= a;");
1554
1555 {
1556 ExpectError error(r, "expected 'bool', but found 'float'");
1557 If(a + b, a -= b).release();
1558 }
1559 }
1560
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLInterfaceBlock,r,ctxInfo)1561 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLInterfaceBlock, r, ctxInfo) {
1562 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1563 DSLExpression intf = InterfaceBlock(kUniform_Modifier, "InterfaceBlock1",
1564 {Field(kFloat_Type, "a"), Field(kInt_Type, "b")});
1565 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
1566 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
1567 "uniform InterfaceBlock1 { float a; int b; };");
1568 EXPECT_EQUAL(intf.field("a"), "a");
1569
1570 DSLExpression intf2 = InterfaceBlock(kUniform_Modifier, "InterfaceBlock2",
1571 {Field(kFloat2_Type, "x"), Field(kHalf2x2_Type, "y")},
1572 "blockVar");
1573 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
1574 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
1575 "uniform InterfaceBlock2 { float2 x; half2x2 y; } blockVar;");
1576 EXPECT_EQUAL(intf2.field("x"), "blockVar.x");
1577
1578 DSLExpression intf3 = InterfaceBlock(kUniform_Modifier, "InterfaceBlock3",
1579 {Field(kFloat_Type, "z")},
1580 "arrayVar", 4);
1581 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 3);
1582 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
1583 "uniform InterfaceBlock3 { float z; } arrayVar[4];");
1584 EXPECT_EQUAL(intf3[1].field("z"), "arrayVar[1].z");
1585
1586 DSLExpression intf4 = InterfaceBlock(
1587 kUniform_Modifier, "InterfaceBlock4",
1588 {Field(DSLLayout().builtin(123), kFloat_Type, "sk_Widget")},
1589 "intf");
1590 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 4);
1591 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
1592 "uniform InterfaceBlock4 { layout(builtin=123) float sk_Widget; } intf;");
1593 }
1594
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLReturn,r,ctxInfo)1595 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLReturn, r, ctxInfo) {
1596 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1597
1598 Statement x = Return();
1599 EXPECT_EQUAL(x, "return;");
1600
1601 Statement y = Return(true);
1602 EXPECT_EQUAL(y, "return true;");
1603 }
1604
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSelect,r,ctxInfo)1605 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSelect, r, ctxInfo) {
1606 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1607 Var a(kInt_Type, "a");
1608 Expression x = Select(a > 0, 1, -1);
1609 EXPECT_EQUAL(x, "a > 0 ? 1 : -1");
1610
1611 {
1612 ExpectError error(r, "expected 'bool', but found 'int'");
1613 Select(a, 1, -1).release();
1614 }
1615
1616 {
1617 ExpectError error(r, "ternary operator result mismatch: 'float2', 'float3'");
1618 Select(a > 0, Float2(1), Float3(1)).release();
1619 }
1620 }
1621
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSwitch,r,ctxInfo)1622 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSwitch, r, ctxInfo) {
1623 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1624
1625 Var a(kFloat_Type, "a"), b(kInt_Type, "b");
1626
1627 SkTArray<DSLStatement> caseStatements;
1628 caseStatements.push_back(a.assign(1));
1629 caseStatements.push_back(Continue());
1630 Statement x = Switch(b,
1631 Case(0, a.assign(0), Break()),
1632 Case(1, std::move(caseStatements)),
1633 Case(2, a.assign(2) /*Fallthrough*/),
1634 Default(Discard())
1635 );
1636 EXPECT_EQUAL(x, R"(
1637 switch (b) {
1638 case 0: a = 0.0; break;
1639 case 1: a = 1.0; continue;
1640 case 2: a = 2.0;
1641 default: discard;
1642 }
1643 )");
1644
1645 EXPECT_EQUAL(Switch(b),
1646 "switch (b) {}");
1647
1648 EXPECT_EQUAL(Switch(b, Default(), Case(0), Case(1)),
1649 "switch (b) { default: ; case 0: ; case 1: ; }");
1650
1651 {
1652 ExpectError error(r, "duplicate case value '0'");
1653 DSLStatement(Switch(0, Case(0), Case(0))).release();
1654 }
1655
1656 {
1657 ExpectError error(r, "duplicate default case");
1658 DSLStatement(Switch(0, Default(a.assign(0)), Default(a.assign(1)))).release();
1659 }
1660
1661 {
1662 ExpectError error(r, "case value must be a constant integer");
1663 Var c(kInt_Type, "c");
1664 DSLStatement(Switch(0, Case(c))).release();
1665 }
1666 }
1667
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSwizzle,r,ctxInfo)1668 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSwizzle, r, ctxInfo) {
1669 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1670 Var a(kFloat4_Type, "a");
1671
1672 EXPECT_EQUAL(a.x(),
1673 "a.x");
1674 EXPECT_EQUAL(a.y(),
1675 "a.y");
1676 EXPECT_EQUAL(a.z(),
1677 "a.z");
1678 EXPECT_EQUAL(a.w(),
1679 "a.w");
1680 EXPECT_EQUAL(a.r(),
1681 "a.x");
1682 EXPECT_EQUAL(a.g(),
1683 "a.y");
1684 EXPECT_EQUAL(a.b(),
1685 "a.z");
1686 EXPECT_EQUAL(a.a(),
1687 "a.w");
1688 EXPECT_EQUAL(Swizzle(a, R),
1689 "a.x");
1690 EXPECT_EQUAL(Swizzle(a, ZERO, G),
1691 "float2(0.0, a.y)");
1692 EXPECT_EQUAL(Swizzle(a, B, G, G),
1693 "a.zyy");
1694 EXPECT_EQUAL(Swizzle(a, R, G, B, ONE),
1695 "float4(a.xyz, 1.0)");
1696 EXPECT_EQUAL(Swizzle(a, B, G, R, ONE).r(),
1697 "a.z");
1698 }
1699
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLVarSwap,r,ctxInfo)1700 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLVarSwap, r, ctxInfo) {
1701 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1702
1703 // We should be able to convert `a` into a proper var by swapping it, even from within a scope.
1704 Var a;
1705 if (true)
1706 {
1707 Var(kInt_Type, "a").swap(a);
1708 }
1709
1710 EXPECT_EQUAL(Statement(Block(Declare(a), a.assign(123))),
1711 "{ int a; a = 123; }");
1712 }
1713
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLWhile,r,ctxInfo)1714 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLWhile, r, ctxInfo) {
1715 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1716 Statement x = While(true, Block());
1717 EXPECT_EQUAL(x, "for (; true;) {}");
1718
1719 Var a(kFloat_Type, "a"), b(kFloat_Type, "b");
1720 Statement y = While(a != b, Block(a++, --b));
1721 EXPECT_EQUAL(y, "for (; a != b;) { a++; --b; }");
1722
1723 {
1724 ExpectError error(r, "expected 'bool', but found 'int'");
1725 While(7, Block()).release();
1726 }
1727 }
1728
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLIndex,r,ctxInfo)1729 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLIndex, r, ctxInfo) {
1730 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1731 Var a(Array(kInt_Type, 5), "a"), b(kInt_Type, "b");
1732
1733 EXPECT_EQUAL(a[0], "a[0]");
1734 EXPECT_EQUAL(a[b], "a[b]");
1735
1736 {
1737 ExpectError error(r, "expected 'int', but found 'bool'");
1738 a[true].release();
1739 }
1740
1741 {
1742 ExpectError error(r, "expected array, but found 'int'");
1743 b[0].release();
1744 }
1745
1746 {
1747 ExpectError error(r, "index -1 out of range for 'int[5]'");
1748 a[-1].release();
1749 }
1750 }
1751
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBuiltins,r,ctxInfo)1752 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLBuiltins, r, ctxInfo) {
1753 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1754 // There is a Fract type on Mac which can conflict with our Fract builtin
1755 using SkSL::dsl::Fract;
1756 Var a(kHalf4_Type, "a"), b(kHalf4_Type, "b"), c(kHalf4_Type, "c");
1757 Var h3(kHalf3_Type, "h3");
1758 Var b4(kBool4_Type, "b4");
1759 EXPECT_EQUAL(Abs(a), "abs(a)");
1760 EXPECT_EQUAL(All(b4), "all(b4)");
1761 EXPECT_EQUAL(Any(b4), "any(b4)");
1762 EXPECT_EQUAL(Atan(a), "atan(a)");
1763 EXPECT_EQUAL(Atan(a, b), "atan(a, b)");
1764 EXPECT_EQUAL(Ceil(a), "ceil(a)");
1765 EXPECT_EQUAL(Clamp(a, 0, 1), "clamp(a, 0.0, 1.0)");
1766 EXPECT_EQUAL(Cos(a), "cos(a)");
1767 EXPECT_EQUAL(Cross(h3, h3), "cross(h3, h3)");
1768 EXPECT_EQUAL(Degrees(a), "degrees(a)");
1769 EXPECT_EQUAL(Distance(a, b), "distance(a, b)");
1770 EXPECT_EQUAL(Dot(a, b), "dot(a, b)");
1771 EXPECT_EQUAL(Equal(a, b), "equal(a, b)");
1772 EXPECT_EQUAL(Exp(a), "exp(a)");
1773 EXPECT_EQUAL(Exp2(a), "exp2(a)");
1774 EXPECT_EQUAL(Faceforward(a, b, c), "faceforward(a, b, c)");
1775 EXPECT_EQUAL(Floor(a), "floor(a)");
1776 EXPECT_EQUAL(Fract(a), "fract(a)");
1777 EXPECT_EQUAL(GreaterThan(a, b), "greaterThan(a, b)");
1778 EXPECT_EQUAL(GreaterThanEqual(a, b), "greaterThanEqual(a, b)");
1779 EXPECT_EQUAL(Inversesqrt(a), "inversesqrt(a)");
1780 EXPECT_EQUAL(LessThan(a, b), "lessThan(a, b)");
1781 EXPECT_EQUAL(LessThanEqual(a, b), "lessThanEqual(a, b)");
1782 EXPECT_EQUAL(Length(a), "length(a)");
1783 EXPECT_EQUAL(Log(a), "log(a)");
1784 EXPECT_EQUAL(Log2(a), "log2(a)");
1785 EXPECT_EQUAL(Max(a, b), "max(a, b)");
1786 EXPECT_EQUAL(Min(a, b), "min(a, b)");
1787 EXPECT_EQUAL(Mix(a, b, c), "mix(a, b, c)");
1788 EXPECT_EQUAL(Mod(a, b), "mod(a, b)");
1789 EXPECT_EQUAL(Normalize(a), "normalize(a)");
1790 EXPECT_EQUAL(NotEqual(a, b), "notEqual(a, b)");
1791 EXPECT_EQUAL(Pow(a, b), "pow(a, b)");
1792 EXPECT_EQUAL(Radians(a), "radians(a)");
1793 EXPECT_EQUAL(Reflect(a, b), "reflect(a, b)");
1794 EXPECT_EQUAL(Refract(a, b, 1), "refract(a, b, 1.0)");
1795 EXPECT_EQUAL(Round(a), "round(a)");
1796 EXPECT_EQUAL(Saturate(a), "saturate(a)");
1797 EXPECT_EQUAL(Sign(a), "sign(a)");
1798 EXPECT_EQUAL(Sin(a), "sin(a)");
1799 EXPECT_EQUAL(Smoothstep(a, b, c), "smoothstep(a, b, c)");
1800 EXPECT_EQUAL(Sqrt(a), "sqrt(a)");
1801 EXPECT_EQUAL(Step(a, b), "step(a, b)");
1802 EXPECT_EQUAL(Tan(a), "tan(a)");
1803 EXPECT_EQUAL(Unpremul(a), "unpremul(a)");
1804
1805 // these calls all go through the normal channels, so it ought to be sufficient to prove that
1806 // one of them reports errors correctly
1807 {
1808 ExpectError error(r, "no match for ceil(bool)");
1809 Ceil(a == b).release();
1810 }
1811 }
1812
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLModifiers,r,ctxInfo)1813 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLModifiers, r, ctxInfo) {
1814 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1815
1816 Var v1(kConst_Modifier, kInt_Type, "v1", 0);
1817 Statement d1 = Declare(v1);
1818 EXPECT_EQUAL(d1, "const int v1 = 0;");
1819
1820 // Most modifiers require an appropriate context to be legal. We can't yet give them that
1821 // context, so we can't as yet Declare() variables with these modifiers.
1822 // TODO: better tests when able
1823 Var v2(kIn_Modifier, kInt_Type, "v2");
1824 REPORTER_ASSERT(r, v2.modifiers().flags() == SkSL::Modifiers::kIn_Flag);
1825
1826 Var v3(kOut_Modifier, kInt_Type, "v3");
1827 REPORTER_ASSERT(r, v3.modifiers().flags() == SkSL::Modifiers::kOut_Flag);
1828
1829 Var v4(kFlat_Modifier, kInt_Type, "v4");
1830 REPORTER_ASSERT(r, v4.modifiers().flags() == SkSL::Modifiers::kFlat_Flag);
1831
1832 Var v5(kNoPerspective_Modifier, kInt_Type, "v5");
1833 REPORTER_ASSERT(r, v5.modifiers().flags() == SkSL::Modifiers::kNoPerspective_Flag);
1834
1835 Var v6(kIn_Modifier | kOut_Modifier, kInt_Type, "v6");
1836 REPORTER_ASSERT(r, v6.modifiers().flags() == (SkSL::Modifiers::kIn_Flag |
1837 SkSL::Modifiers::kOut_Flag));
1838
1839 Var v7(kInOut_Modifier, kInt_Type, "v7");
1840 REPORTER_ASSERT(r, v7.modifiers().flags() == (SkSL::Modifiers::kIn_Flag |
1841 SkSL::Modifiers::kOut_Flag));
1842
1843 Var v8(kUniform_Modifier, kInt_Type, "v8");
1844 REPORTER_ASSERT(r, v8.modifiers().flags() == SkSL::Modifiers::kUniform_Flag);
1845 }
1846
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLayout,r,ctxInfo)1847 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLLayout, r, ctxInfo) {
1848 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1849 Var v1(DSLModifiers(DSLLayout().location(1).offset(4).index(5).builtin(6)
1850 .inputAttachmentIndex(7),
1851 kConst_Modifier), kInt_Type, "v1", 0);
1852 EXPECT_EQUAL(Declare(v1), "layout (location = 1, offset = 4, index = 5, "
1853 "builtin = 6, input_attachment_index = 7) const int v1 = 0;");
1854
1855 Var v2(DSLLayout().originUpperLeft(), kFloat2_Type, "v2");
1856 EXPECT_EQUAL(Declare(v2), "layout (origin_upper_left) float2 v2;");
1857
1858 Var v4(DSLLayout().pushConstant(), kBool_Type, "v4");
1859 EXPECT_EQUAL(Declare(v4), "layout (push_constant) bool v4;");
1860
1861 Var v5(DSLLayout().blendSupportAllEquations(), kHalf4_Type, "v5");
1862 EXPECT_EQUAL(Declare(v5), "layout (blend_support_all_equations) half4 v5;");
1863
1864 {
1865 ExpectError error(r, "'layout(color)' is only permitted in runtime effects");
1866 DSLGlobalVar v(DSLModifiers(DSLLayout().color(), kUniform_Modifier), kHalf4_Type, "v");
1867 Declare(v);
1868 }
1869
1870 {
1871 ExpectError error(r, "layout qualifier 'location' appears more than once");
1872 DSLLayout().location(1).location(2);
1873 }
1874
1875 {
1876 ExpectError error(r, "layout qualifier 'set' appears more than once");
1877 DSLLayout().set(1).set(2);
1878 }
1879
1880 {
1881 ExpectError error(r, "layout qualifier 'binding' appears more than once");
1882 DSLLayout().binding(1).binding(2);
1883 }
1884
1885 {
1886 ExpectError error(r, "layout qualifier 'offset' appears more than once");
1887 DSLLayout().offset(1).offset(2);
1888 }
1889
1890 {
1891 ExpectError error(r, "layout qualifier 'index' appears more than once");
1892 DSLLayout().index(1).index(2);
1893 }
1894
1895 {
1896 ExpectError error(r, "layout qualifier 'builtin' appears more than once");
1897 DSLLayout().builtin(1).builtin(2);
1898 }
1899
1900 {
1901 ExpectError error(r, "layout qualifier 'input_attachment_index' appears more than once");
1902 DSLLayout().inputAttachmentIndex(1).inputAttachmentIndex(2);
1903 }
1904
1905 {
1906 ExpectError error(r, "layout qualifier 'origin_upper_left' appears more than once");
1907 DSLLayout().originUpperLeft().originUpperLeft();
1908 }
1909
1910 {
1911 ExpectError error(r, "layout qualifier 'push_constant' appears more than once");
1912 DSLLayout().pushConstant().pushConstant();
1913 }
1914
1915 {
1916 ExpectError error(r, "layout qualifier 'blend_support_all_equations' appears more than "
1917 "once");
1918 DSLLayout().blendSupportAllEquations().blendSupportAllEquations();
1919 }
1920
1921 {
1922 ExpectError error(r, "layout qualifier 'color' appears more than once");
1923 DSLLayout().color().color();
1924 }
1925 }
1926
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSampleShader,r,ctxInfo)1927 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLSampleShader, r, ctxInfo) {
1928 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), default_settings(),
1929 SkSL::ProgramKind::kRuntimeShader);
1930 DSLGlobalVar shader(kUniform_Modifier, kShader_Type, "child");
1931 DSLGlobalVar notShader(kUniform_Modifier, kFloat_Type, "x");
1932 EXPECT_EQUAL(shader.eval(Float2(0, 0)), "child.eval(float2(0.0))");
1933
1934 {
1935 ExpectError error(r, "no match for shader::eval(half4)");
1936 shader.eval(Half4(1)).release();
1937 }
1938
1939 {
1940 ExpectError error(r, "type does not support method calls");
1941 notShader.eval(Half4(1)).release();
1942 }
1943 }
1944
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLStruct,r,ctxInfo)1945 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLStruct, r, ctxInfo) {
1946 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
1947
1948 DSLType simpleStruct = Struct("SimpleStruct",
1949 Field(kFloat_Type, "x"),
1950 Field(kBool_Type, "b"),
1951 Field(Array(kFloat_Type, 3), "a")
1952 );
1953 DSLVar result(simpleStruct, "result");
1954 DSLFunction(simpleStruct, "returnStruct").define(
1955 Declare(result),
1956 result.field("x").assign(123),
1957 result.field("b").assign(result.field("x") > 0),
1958 result.field("a")[0].assign(result.field("x")),
1959 Return(result)
1960 );
1961 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
1962 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
1963 "struct SimpleStruct { float x; bool b; float[3] a; };");
1964 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1],
1965 "SimpleStruct returnStruct() { SimpleStruct result; result.x = 123.0;"
1966 "result.b = result.x > 0.0; result.a[0] = result.x; return result; }");
1967
1968 Struct("NestedStruct",
1969 Field(kInt_Type, "x"),
1970 Field(simpleStruct, "simple")
1971 );
1972 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 3);
1973 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[2],
1974 "struct NestedStruct { int x; SimpleStruct simple; };");
1975 }
1976
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLRTAdjust,r,ctxInfo)1977 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLRTAdjust, r, ctxInfo) {
1978 {
1979 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), default_settings(),
1980 SkSL::ProgramKind::kVertex);
1981 REPORTER_ASSERT(r, !SkSL::ThreadContext::RTAdjustState().fInterfaceBlock);
1982
1983 DSLExpression intf = InterfaceBlock(kUniform_Modifier, "uniforms",
1984 {Field(kInt_Type, "unused"),
1985 Field(kFloat4_Type, "sk_RTAdjust")});
1986 REPORTER_ASSERT(r, SkSL::ThreadContext::RTAdjustState().fInterfaceBlock);
1987 REPORTER_ASSERT(r, SkSL::ThreadContext::RTAdjustState().fFieldIndex == 1);
1988 }
1989
1990 {
1991 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), default_settings(),
1992 SkSL::ProgramKind::kVertex);
1993 ExpectError error(r, "sk_RTAdjust must have type 'float4'");
1994 InterfaceBlock(kUniform_Modifier, "uniforms",
1995 { Field(kInt_Type, "unused"), Field(kHalf4_Type, "sk_RTAdjust") });
1996 }
1997
1998 {
1999 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), default_settings(),
2000 SkSL::ProgramKind::kVertex);
2001 ExpectError error(r, "symbol 'sk_RTAdjust' was already defined");
2002 InterfaceBlock(kUniform_Modifier, "uniforms1",
2003 {Field(kInt_Type, "unused1"), Field(kFloat4_Type, "sk_RTAdjust")});
2004 InterfaceBlock(kUniform_Modifier, "uniforms2",
2005 {Field(kInt_Type, "unused2"), Field(kFloat4_Type, "sk_RTAdjust")});
2006 }
2007 }
2008
2009 #ifndef SK_ENABLE_OPTIMIZE_SIZE
2010 // The inliner doesn't exist in a size-optimized build.
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLInlining,r,ctxInfo)2011 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLInlining, r, ctxInfo) {
2012 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
2013 DSLParameter x(kFloat_Type, "x");
2014 DSLFunction sqr(kFloat_Type, "sqr", x);
2015 sqr.define(
2016 Return(x * x)
2017 );
2018 DSLFunction(kHalf4_Type, "main").define(
2019 Return(Half4(sqr(3)))
2020 );
2021 const char* source = "source test";
2022 std::unique_ptr<SkSL::Program> program = ReleaseProgram(std::make_unique<std::string>(source));
2023 EXPECT_EQUAL(*program,
2024 "layout(builtin = 17) in bool sk_Clockwise;"
2025 "layout(location = 0, index = 0, builtin = 10001) out half4 sk_FragColor;"
2026 "half4 main() {"
2027 ";"
2028 "return half4(half(9.0));"
2029 "}");
2030 REPORTER_ASSERT(r, *program->fSource == source);
2031 }
2032 #endif
2033
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLPrototypes,r,ctxInfo)2034 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLPrototypes, r, ctxInfo) {
2035 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
2036 {
2037 DSLParameter x(kFloat_Type, "x");
2038 DSLFunction sqr(kFloat_Type, "sqr", x);
2039 sqr.prototype();
2040 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
2041 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
2042 "float sqr(float x);");
2043 sqr.define(
2044 Return(x * x)
2045 );
2046 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
2047 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1],
2048 "float sqr(float x) { return x * x; }");
2049 }
2050
2051 {
2052 DSLWriter::Reset();
2053 DSLParameter x(kInOut_Modifier, kFloat_Type, "x");
2054 DSLFunction sqr(kVoid_Type, "sqr", x);
2055 sqr.prototype();
2056 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
2057 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
2058 "void sqr(inout float x);");
2059 sqr.define(
2060 x *= x
2061 );
2062 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
2063 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1],
2064 "void sqr(inout float x) { x *= x; }");
2065 }
2066
2067 {
2068 DSLWriter::Reset();
2069 DSLParameter x(kFloat_Type, "x");
2070 DSLFunction sqr(DSLModifiers(SkSL::Modifiers::kNoInline_Flag), kFloat_Type, "sqr", x);
2071 sqr.prototype();
2072 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
2073 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "noinline float sqr(float x);");
2074 DSLFunction(kVoid_Type, "main").define(sqr(5));
2075 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
2076 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "noinline float sqr(float x);");
2077 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "void main() { sqr(5.0); }");
2078 sqr.define(
2079 Return(x * x)
2080 );
2081 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 3);
2082 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[2],
2083 "noinline float sqr(float x) { return x * x; }");
2084
2085 const char* source = "source test";
2086 std::unique_ptr<SkSL::Program> p = ReleaseProgram(std::make_unique<std::string>(source));
2087
2088 EXPECT_EQUAL(*p,
2089 "layout (builtin = 17) in bool sk_Clockwise;"
2090 "noinline float sqr(float x);"
2091 "void main() {"
2092 " sqr(5.0);"
2093 "}"
2094 "noinline float sqr(float x) {"
2095 " return x * x;"
2096 "}");
2097 }
2098 }
2099
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLExtension,r,ctxInfo)2100 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLExtension, r, ctxInfo) {
2101 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
2102 AddExtension("test_extension");
2103 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
2104 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "#extension test_extension : enable");
2105 }
2106
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLModifiersDeclaration,r,ctxInfo)2107 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(DSLModifiersDeclaration, r, ctxInfo) {
2108 AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
2109 Declare(Modifiers(Layout().blendSupportAllEquations(), kOut_Modifier));
2110 REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
2111 EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
2112 "layout(blend_support_all_equations) out;");
2113 }
2114