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