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 #ifndef SKSL_DSL_CORE
9 #define SKSL_DSL_CORE
10
11 #include "include/private/SkSLProgramKind.h"
12 #include "include/private/SkTArray.h"
13 #include "include/sksl/DSLBlock.h"
14 #include "include/sksl/DSLCase.h"
15 #include "include/sksl/DSLExpression.h"
16 #include "include/sksl/DSLFunction.h"
17 #include "include/sksl/DSLStatement.h"
18 #include "include/sksl/DSLType.h"
19 #include "include/sksl/DSLVar.h"
20 #include "include/sksl/DSLWrapper.h"
21 #include "include/sksl/SkSLErrorReporter.h"
22
23 namespace SkSL {
24
25 class Compiler;
26 struct Program;
27 struct ProgramSettings;
28
29 namespace dsl {
30
31 // When users import the DSL namespace via `using namespace SkSL::dsl`, we want the SwizzleComponent
32 // Type enum to come into scope as well, so `Swizzle(var, X, Y, ONE)` can work as expected.
33 // `namespace SkSL::SwizzleComponent` contains only an `enum Type`; this `using namespace` directive
34 // shouldn't pollute the SkSL::dsl namespace with anything else.
35 using namespace SkSL::SwizzleComponent;
36
37 /**
38 * Starts DSL output on the current thread using the specified compiler. This must be called
39 * prior to any other DSL functions.
40 */
41 void Start(SkSL::Compiler* compiler, SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment);
42
43 void Start(SkSL::Compiler* compiler, SkSL::ProgramKind kind, const SkSL::ProgramSettings& settings);
44
45 /**
46 * Signals the end of DSL output. This must be called sometime between a call to Start() and the
47 * termination of the thread.
48 */
49 void End();
50
51 /**
52 * Returns all global elements (functions and global variables) as a self-contained Program. The
53 * optional source string is retained as the program's source. DSL programs do not normally have
54 * sources, but when a DSL program is produced from parsed program text (as in DSLParser), it may be
55 * important to retain it so that any skstd::string_views derived from it remain valid.
56 */
57 std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<SkSL::String> source = nullptr);
58
59 /**
60 * Returns the ErrorReporter which will be notified of any errors that occur during DSL calls. The
61 * default error reporter aborts on any error.
62 */
63 ErrorReporter& GetErrorReporter();
64
65 /**
66 * Installs an ErrorReporter which will be notified of any errors that occur during DSL calls.
67 */
68 void SetErrorReporter(ErrorReporter* errorReporter);
69
70 DSLGlobalVar sk_FragColor();
71
72 DSLGlobalVar sk_FragCoord();
73
74 DSLExpression sk_Position();
75
76 /**
77 * #extension <name> : enable
78 */
79 void AddExtension(skstd::string_view name, PositionInfo pos = PositionInfo::Capture());
80
81 /**
82 * break;
83 */
84 DSLStatement Break(PositionInfo pos = PositionInfo::Capture());
85
86 /**
87 * continue;
88 */
89 DSLStatement Continue(PositionInfo pos = PositionInfo::Capture());
90
91 /**
92 * Adds a modifiers declaration to the current program.
93 */
94 void Declare(const DSLModifiers& modifiers, PositionInfo pos = PositionInfo::Capture());
95
96 /**
97 * Creates a local variable declaration statement.
98 */
99 DSLStatement Declare(DSLVar& var, PositionInfo pos = PositionInfo::Capture());
100
101 /**
102 * Creates a local variable declaration statement containing multiple variables.
103 */
104 DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos = PositionInfo::Capture());
105
106 /**
107 * Declares a global variable.
108 */
109 void Declare(DSLGlobalVar& var, PositionInfo pos = PositionInfo::Capture());
110
111 /**
112 * Declares a set of global variables.
113 */
114 void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos = PositionInfo::Capture());
115
116 /**
117 * default: statements
118 */
119 template<class... Statements>
Default(Statements...statements)120 DSLCase Default(Statements... statements) {
121 return DSLCase(DSLExpression(), std::move(statements)...);
122 }
123
124 /**
125 * discard;
126 */
127 DSLStatement Discard(PositionInfo pos = PositionInfo::Capture());
128
129 /**
130 * do stmt; while (test);
131 */
132 DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos = PositionInfo::Capture());
133
134 /**
135 * for (initializer; test; next) stmt;
136 */
137 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
138 DSLStatement stmt, PositionInfo pos = PositionInfo::Capture());
139
140 /**
141 * if (test) ifTrue; [else ifFalse;]
142 */
143 DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse = DSLStatement(),
144 PositionInfo pos = PositionInfo::Capture());
145
146 DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName,
147 SkTArray<DSLField> fields, skstd::string_view varName = "",
148 int arraySize = 0, PositionInfo pos = PositionInfo::Capture());
149
150 /**
151 * return [value];
152 */
153 DSLStatement Return(DSLExpression value = DSLExpression(),
154 PositionInfo pos = PositionInfo::Capture());
155
156 /**
157 * test ? ifTrue : ifFalse
158 */
159 DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
160 PositionInfo info = PositionInfo::Capture());
161
162 DSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue,
163 DSLStatement ifFalse = DSLStatement(),
164 PositionInfo pos = PositionInfo::Capture());
165
166 // Internal use only
167 DSLPossibleStatement PossibleStaticSwitch(DSLExpression value, SkTArray<DSLCase> cases);
168
169 DSLStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases,
170 PositionInfo info = PositionInfo::Capture());
171
172 /**
173 * @switch (value) { cases }
174 */
175 template<class... Cases>
StaticSwitch(DSLExpression value,Cases...cases)176 DSLPossibleStatement StaticSwitch(DSLExpression value, Cases... cases) {
177 SkTArray<DSLCase> caseArray;
178 caseArray.reserve_back(sizeof...(cases));
179 (caseArray.push_back(std::move(cases)), ...);
180 return PossibleStaticSwitch(std::move(value), std::move(caseArray));
181 }
182
183 // Internal use only
184 DSLPossibleStatement PossibleSwitch(DSLExpression value, SkTArray<DSLCase> cases);
185
186 DSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases,
187 PositionInfo info = PositionInfo::Capture());
188
189 /**
190 * switch (value) { cases }
191 */
192 template<class... Cases>
Switch(DSLExpression value,Cases...cases)193 DSLPossibleStatement Switch(DSLExpression value, Cases... cases) {
194 SkTArray<DSLCase> caseArray;
195 caseArray.reserve_back(sizeof...(cases));
196 (caseArray.push_back(std::move(cases)), ...);
197 return PossibleSwitch(std::move(value), std::move(caseArray));
198 }
199
200 /**
201 * while (test) stmt;
202 */
203 DSLStatement While(DSLExpression test, DSLStatement stmt,
204 PositionInfo info = PositionInfo::Capture());
205
206 /**
207 * expression.xyz1
208 */
209 DSLExpression Swizzle(DSLExpression base,
210 SkSL::SwizzleComponent::Type a,
211 PositionInfo pos = PositionInfo::Capture());
212
213 DSLExpression Swizzle(DSLExpression base,
214 SkSL::SwizzleComponent::Type a,
215 SkSL::SwizzleComponent::Type b,
216 PositionInfo pos = PositionInfo::Capture());
217
218 DSLExpression Swizzle(DSLExpression base,
219 SkSL::SwizzleComponent::Type a,
220 SkSL::SwizzleComponent::Type b,
221 SkSL::SwizzleComponent::Type c,
222 PositionInfo pos = PositionInfo::Capture());
223
224 DSLExpression Swizzle(DSLExpression base,
225 SkSL::SwizzleComponent::Type a,
226 SkSL::SwizzleComponent::Type b,
227 SkSL::SwizzleComponent::Type c,
228 SkSL::SwizzleComponent::Type d,
229 PositionInfo pos = PositionInfo::Capture());
230
231 /**
232 * Returns the absolute value of x. If x is a vector, operates componentwise.
233 */
234 DSLExpression Abs(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
235
236 /**
237 * Returns true if all of the components of boolean vector x are true.
238 */
239 DSLExpression All(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
240
241 /**
242 * Returns true if any of the components of boolean vector x are true.
243 */
244 DSLExpression Any(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
245
246 /**
247 * Returns the arctangent of y over x. Operates componentwise on vectors.
248 */
249 DSLExpression Atan(DSLExpression y_over_x, PositionInfo pos = PositionInfo::Capture());
250 DSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos = PositionInfo::Capture());
251
252 /**
253 * Returns x rounded towards positive infinity. If x is a vector, operates componentwise.
254 */
255 DSLExpression Ceil(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
256
257 /**
258 * Returns x clamped to between min and max. If x is a vector, operates componentwise.
259 */
260 DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max,
261 PositionInfo pos = PositionInfo::Capture());
262
263 /**
264 * Returns the cosine of x. If x is a vector, operates componentwise.
265 */
266 DSLExpression Cos(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
267
268 /**
269 * Returns the cross product of x and y.
270 */
271 DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
272
273 /**
274 * Returns x converted from radians to degrees. If x is a vector, operates componentwise.
275 */
276 DSLExpression Degrees(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
277
278 /**
279 * Returns the distance between x and y.
280 */
281 DSLExpression Distance(DSLExpression x, DSLExpression y,
282 PositionInfo pos = PositionInfo::Capture());
283
284 /**
285 * Returns the dot product of x and y.
286 */
287 DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
288
289 /**
290 * Returns a boolean vector indicating whether components of x are equal to the corresponding
291 * components of y.
292 */
293 DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
294
295 /**
296 * Returns e^x. If x is a vector, operates componentwise.
297 */
298 DSLExpression Exp(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
299
300 /**
301 * Returns 2^x. If x is a vector, operates componentwise.
302 */
303 DSLExpression Exp2(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
304
305 /**
306 * If dot(i, nref) >= 0, returns n, otherwise returns -n.
307 */
308 DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref,
309 PositionInfo pos = PositionInfo::Capture());
310
311 /**
312 * Returns x rounded towards negative infinity. If x is a vector, operates componentwise.
313 */
314 DSLExpression Floor(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
315
316 /**
317 * Returns the fractional part of x. If x is a vector, operates componentwise.
318 */
319 DSLExpression Fract(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
320
321 /**
322 * Returns a boolean vector indicating whether components of x are greater than the corresponding
323 * components of y.
324 */
325 DSLExpression GreaterThan(DSLExpression x, DSLExpression y,
326 PositionInfo pos = PositionInfo::Capture());
327
328 /**
329 * Returns a boolean vector indicating whether components of x are greater than or equal to the
330 * corresponding components of y.
331 */
332 DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y,
333 PositionInfo pos = PositionInfo::Capture());
334
335 /**
336 * Returns the 1/sqrt(x). If x is a vector, operates componentwise.
337 */
338 DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
339
340 /**
341 * Returns the inverse of the matrix x.
342 */
343 DSLExpression Inverse(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
344
345 /**
346 * Returns the length of the vector x.
347 */
348 DSLExpression Length(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
349
350 /**
351 * Returns a boolean vector indicating whether components of x are less than the corresponding
352 * components of y.
353 */
354 DSLExpression LessThan(DSLExpression x, DSLExpression y,
355 PositionInfo pos = PositionInfo::Capture());
356
357 /**
358 * Returns a boolean vector indicating whether components of x are less than or equal to the
359 * corresponding components of y.
360 */
361 DSLExpression LessThanEqual(DSLExpression x, DSLExpression y,
362 PositionInfo pos = PositionInfo::Capture());
363
364 /**
365 * Returns the log base e of x. If x is a vector, operates componentwise.
366 */
367 DSLExpression Log(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
368
369 /**
370 * Returns the log base 2 of x. If x is a vector, operates componentwise.
371 */
372 DSLExpression Log2(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
373
374 /**
375 * Returns the larger (closer to positive infinity) of x and y. If x is a vector, operates
376 * componentwise. y may be either a vector of the same dimensions as x, or a scalar.
377 */
378 DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
379
380 /**
381 * Returns the smaller (closer to negative infinity) of x and y. If x is a vector, operates
382 * componentwise. y may be either a vector of the same dimensions as x, or a scalar.
383 */
384 DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
385
386 /**
387 * Returns a linear intepolation between x and y at position a, where a=0 results in x and a=1
388 * results in y. If x and y are vectors, operates componentwise. a may be either a vector of the
389 * same dimensions as x and y, or a scalar.
390 */
391 DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a,
392 PositionInfo pos = PositionInfo::Capture());
393
394 /**
395 * Returns x modulo y. If x is a vector, operates componentwise. y may be either a vector of the
396 * same dimensions as x, or a scalar.
397 */
398 DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
399
400 /**
401 * Returns the vector x normalized to a length of 1.
402 */
403 DSLExpression Normalize(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
404
405 /**
406 * Returns a boolean vector indicating whether components of x are not equal to the corresponding
407 * components of y.
408 */
409 DSLExpression NotEqual(DSLExpression x, DSLExpression y,
410 PositionInfo pos = PositionInfo::Capture());
411
412 /**
413 * Returns x raised to the power y. If x is a vector, operates componentwise. y may be either a
414 * vector of the same dimensions as x, or a scalar.
415 */
416 DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo::Capture());
417
418 /**
419 * Returns x converted from degrees to radians. If x is a vector, operates componentwise.
420 */
421 DSLExpression Radians(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
422
423 /**
424 * Returns i reflected from a surface with normal n.
425 */
426 DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos = PositionInfo::Capture());
427
428 /**
429 * Returns i refracted across a surface with normal n and ratio of indices of refraction eta.
430 */
431 DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta,
432 PositionInfo pos = PositionInfo::Capture());
433
434 /**
435 * Returns x, rounded to the nearest integer. If x is a vector, operates componentwise.
436 */
437 DSLExpression Round(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
438
439 /**
440 * Returns x clamped to the range [0, 1]. If x is a vector, operates componentwise.
441 */
442 DSLExpression Saturate(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
443
444 /**
445 * Returns -1, 0, or 1 depending on whether x is negative, zero, or positive, respectively. If x is
446 * a vector, operates componentwise.
447 */
448 DSLExpression Sign(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
449
450 /**
451 * Returns the sine of x. If x is a vector, operates componentwise.
452 */
453 DSLExpression Sin(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
454
455 /**
456 * Returns a smooth interpolation between 0 (at x=edge1) and 1 (at x=edge2). If x is a vector,
457 * operates componentwise. edge1 and edge2 may either be both vectors of the same dimensions as x or
458 * scalars.
459 */
460 DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
461 PositionInfo pos = PositionInfo::Capture());
462
463 /**
464 * Returns the square root of x. If x is a vector, operates componentwise.
465 */
466 DSLExpression Sqrt(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
467
468 /**
469 * Returns 0 if x < edge or 1 if x >= edge. If x is a vector, operates componentwise. edge may be
470 * either a vector of the same dimensions as x, or a scalar.
471 */
472 DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos = PositionInfo::Capture());
473
474 /**
475 * Returns the tangent of x. If x is a vector, operates componentwise.
476 */
477 DSLExpression Tan(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
478
479 /**
480 * Returns x converted from premultipled to unpremultiplied alpha.
481 */
482 DSLExpression Unpremul(DSLExpression x, PositionInfo pos = PositionInfo::Capture());
483
484 } // namespace dsl
485
486 } // namespace SkSL
487
488 #endif
489