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