• 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/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