]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/syntax.h
Use extended alignment in SPIR-V struct layout when necessary
[libs/gl.git] / source / glsl / syntax.h
1 #ifndef MSP_GL_SL_SYNTAX_H_
2 #define MSP_GL_SL_SYNTAX_H_
3
4 #include <list>
5 #include <map>
6 #include <set>
7 #include <string>
8 #include <vector>
9 #include <cstdint>
10 #include <msp/core/refptr.h>
11 #include <msp/core/variant.h>
12 #include "features.h"
13 #include "glsl_error.h"
14 #include "sourcemap.h"
15
16 #pragma push_macro("interface")
17 #undef interface
18
19 namespace Msp {
20 namespace GL {
21 namespace SL {
22
23 struct Operator
24 {
25         enum Type
26         {
27                 NO_OPERATOR,
28                 BINARY,
29                 PREFIX,
30                 POSTFIX,
31                 TERNARY
32         };
33
34         enum Associativity
35         {
36                 LEFT_TO_RIGHT,
37                 RIGHT_TO_LEFT,
38                 ASSOCIATIVE
39         };
40
41         char token[4];
42         char token2[2];
43         std::uint8_t precedence;
44         Type type;
45         Associativity assoc;
46
47         static const Operator operators[];
48
49         static const Operator &get_operator(const std::string &, Type);
50 };
51
52 enum
53 {
54         INTERNAL_SOURCE = -2,
55         BUILTIN_SOURCE = -1,
56         GENERATED_SOURCE = 0
57 };
58
59 struct NodeVisitor;
60
61 struct Node
62 {
63         int source = GENERATED_SOURCE;
64         unsigned line = 1;
65
66         Node() = default;
67         Node(const Node &) = default;
68 private:
69         Node &operator=(const Node &);
70 public:
71         virtual ~Node() = default;
72
73         virtual Node *clone() const = 0;
74         virtual void visit(NodeVisitor &) = 0;
75 };
76
77 template<typename T>
78 class NodePtr: public RefPtr<T>
79 {
80 public:
81         NodePtr() = default;
82         NodePtr(T *p): RefPtr<T>(p) { }
83         NodePtr(const NodePtr &p): RefPtr<T>(p ? p->clone() : 0) { }
84         NodePtr &operator=(const NodePtr &p) = default;
85
86         template<typename U>
87         NodePtr(const RefPtr<U> &p): RefPtr<T>(p) { }
88
89         template<typename U>
90         NodePtr(const NodePtr<U> &p): RefPtr<T>(p ? p->clone() : 0) { }
91 };
92
93 template<typename C>
94 class NodeContainer: public C
95 {
96 public:
97         NodeContainer() = default;
98         NodeContainer(const NodeContainer &);
99
100         void push_back_nocopy(const typename C::value_type &v)
101         { C::push_back(0); C::back() = v; }
102 };
103
104 template<typename T>
105 class NodeList: public NodeContainer<std::list<RefPtr<T> > >
106 { };
107
108 template<typename T>
109 class NodeArray: public NodeContainer<std::vector<RefPtr<T> > >
110 { };
111
112 struct TypeDeclaration;
113 struct VariableDeclaration;
114 struct InterfaceBlock;
115 struct FunctionDeclaration;
116
117 struct Statement: Node
118 {
119         virtual Statement *clone() const = 0;
120 };
121
122 struct Block: Node
123 {
124         NodeList<Statement> body;
125         bool use_braces = false;
126
127         std::map<std::string, VariableDeclaration *> variables;
128         Block *parent = 0;
129
130         Block() = default;
131         Block(const Block &);
132
133         virtual Block *clone() const { return new Block(*this); }
134         virtual void visit(NodeVisitor &);
135 };
136
137 struct Expression: Node
138 {
139         const Operator *oper = 0;
140
141         TypeDeclaration *type = 0;
142         bool lvalue = false;
143
144         virtual Expression *clone() const = 0;
145 };
146
147 struct Literal: Expression
148 {
149         std::string token;
150         Variant value;
151
152         virtual Literal *clone() const { return new Literal(*this); }
153         virtual void visit(NodeVisitor &);
154 };
155
156 struct VariableReference: Expression
157 {
158         std::string name;
159
160         VariableDeclaration *declaration = 0;
161
162         VariableReference() = default;
163         VariableReference(const VariableReference &);
164
165         virtual VariableReference *clone() const { return new VariableReference(*this); }
166         virtual void visit(NodeVisitor &);
167 };
168
169 struct InterfaceBlockReference: Expression
170 {
171         std::string name;
172
173         InterfaceBlock *declaration = 0;
174
175         InterfaceBlockReference() = default;
176         InterfaceBlockReference(const InterfaceBlockReference &);
177
178         virtual InterfaceBlockReference *clone() const { return new InterfaceBlockReference(*this); }
179         virtual void visit(NodeVisitor &);
180 };
181
182 struct MemberAccess: Expression
183 {
184         NodePtr<Expression> left;
185         std::string member;
186
187         VariableDeclaration *declaration = 0;
188         int index = -1;
189
190         MemberAccess() = default;
191         MemberAccess(const MemberAccess &);
192
193         virtual MemberAccess *clone() const { return new MemberAccess(*this); }
194         virtual void visit(NodeVisitor &);
195 };
196
197 struct Swizzle: Expression
198 {
199         NodePtr<Expression> left;
200         std::string component_group;
201         unsigned count = 0;
202         std::uint8_t components[4] = { 0, 0, 0, 0 };
203
204         virtual Swizzle *clone() const { return new Swizzle(*this); }
205         virtual void visit(NodeVisitor &);
206 };
207
208 struct UnaryExpression: Expression
209 {
210         NodePtr<Expression> expression;
211
212         virtual UnaryExpression *clone() const { return new UnaryExpression(*this); }
213         virtual void visit(NodeVisitor &);
214 };
215
216 struct BinaryExpression: Expression
217 {
218         NodePtr<Expression> left;
219         NodePtr<Expression> right;
220
221         virtual BinaryExpression *clone() const { return new BinaryExpression(*this); }
222         virtual void visit(NodeVisitor &);
223 };
224
225 struct Assignment: BinaryExpression
226 {
227         struct Target
228         {
229                 enum ChainType
230                 {
231                         MEMBER = 0x40,
232                         SWIZZLE = 0x80,
233                         ARRAY = 0xC0
234                 };
235
236                 Statement *declaration = 0;
237                 std::uint8_t chain_len = 0;
238                 std::uint8_t chain[7] = { };
239
240                 Target(Statement *d = 0): declaration(d) { }
241
242                 bool operator<(const Target &) const;
243         };
244
245         bool self_referencing = false;
246
247         Target target;
248
249         Assignment() = default;
250         Assignment(const Assignment &);
251
252         virtual Assignment *clone() const { return new Assignment(*this); }
253         virtual void visit(NodeVisitor &);
254 };
255
256 struct TernaryExpression: Expression
257 {
258         NodePtr<Expression> condition;
259         NodePtr<Expression> true_expr;
260         NodePtr<Expression> false_expr;
261
262         virtual TernaryExpression *clone() const { return new TernaryExpression(*this); }
263         virtual void visit(NodeVisitor &);
264 };
265
266 struct FunctionCall: Expression
267 {
268         std::string name;
269         bool constructor = false;
270         NodeArray<Expression> arguments;
271
272         FunctionDeclaration *declaration = 0;
273
274         FunctionCall() = default;
275         FunctionCall(const FunctionCall &);
276
277         virtual FunctionCall *clone() const { return new FunctionCall(*this); }
278         virtual void visit(NodeVisitor &);
279 };
280
281 struct ExpressionStatement: Statement
282 {
283         NodePtr<Expression> expression;
284
285         virtual ExpressionStatement *clone() const { return new ExpressionStatement(*this); }
286         virtual void visit(NodeVisitor &);
287 };
288
289 struct Import: Statement
290 {
291         std::string module;
292
293         virtual Import *clone() const { return new Import(*this); }
294         virtual void visit(NodeVisitor &);
295 };
296
297 struct Precision: Statement
298 {
299         std::string precision;
300         std::string type;
301
302         virtual Precision *clone() const { return new Precision(*this); }
303         virtual void visit(NodeVisitor &);
304 };
305
306 struct Layout: Node
307 {
308         struct Qualifier
309         {
310                 std::string name;
311                 bool has_value;
312                 int value;
313
314                 Qualifier(const std::string &n = std::string()): name(n), has_value(false), value(0) { }
315                 Qualifier(const std::string &n, int v): name(n), has_value(true), value(v) { }
316         };
317
318         std::vector<Qualifier> qualifiers;
319
320         virtual Layout *clone() const { return new Layout(*this); }
321         virtual void visit(NodeVisitor &);
322 };
323
324 struct InterfaceLayout: Statement
325 {
326         std::string interface;
327         Layout layout;
328
329         virtual InterfaceLayout *clone() const { return new InterfaceLayout(*this); }
330         virtual void visit(NodeVisitor &);
331 };
332
333 struct TypeDeclaration: Statement
334 {
335         std::string name;
336
337         virtual TypeDeclaration *clone() const = 0;
338 };
339
340 struct BasicTypeDeclaration: TypeDeclaration
341 {
342         enum Kind
343         {
344                 ALIAS,
345                 VOID,
346                 BOOL,
347                 INT,
348                 FLOAT,
349                 VECTOR,
350                 MATRIX,
351                 ARRAY
352         };
353
354         Kind kind = ALIAS;
355         unsigned size = 0;
356         bool sign = true;
357         bool extended_alignment = false;
358         std::string base;
359
360         TypeDeclaration *base_type = 0;
361
362         BasicTypeDeclaration() = default;
363         BasicTypeDeclaration(const BasicTypeDeclaration &);
364
365         virtual BasicTypeDeclaration *clone() const { return new BasicTypeDeclaration(*this); }
366         virtual void visit(NodeVisitor &);
367 };
368
369 struct ImageTypeDeclaration: TypeDeclaration
370 {
371         enum Dimensions
372         {
373                 ONE = 1,
374                 TWO,
375                 THREE,
376                 CUBE
377         };
378
379         Dimensions dimensions = TWO;
380         bool array = false;
381         bool sampled = true;
382         bool shadow = false;
383         std::string base;
384
385         TypeDeclaration *base_type = 0;
386
387         virtual ImageTypeDeclaration *clone() const { return new ImageTypeDeclaration(*this); }
388         virtual void visit(NodeVisitor &);
389 };
390
391 struct StructDeclaration: TypeDeclaration
392 {
393         Block members;
394         bool extended_alignment = false;
395
396         InterfaceBlock *interface_block = 0;
397
398         StructDeclaration();
399         StructDeclaration(const StructDeclaration &);
400         ~StructDeclaration();
401
402         virtual StructDeclaration *clone() const { return new StructDeclaration(*this); }
403         virtual void visit(NodeVisitor &);
404 };
405
406 struct VariableDeclaration: Statement
407 {
408         NodePtr<Layout> layout;
409         bool constant = false;
410         std::string sampling;
411         std::string interpolation;
412         std::string interface;
413         std::string precision;
414         std::string type;
415         std::string name;
416         bool array = false;
417         NodePtr<Expression> array_size;
418         NodePtr<Expression> init_expression;
419
420         TypeDeclaration *type_declaration = 0;
421         VariableDeclaration *linked_declaration = 0;
422
423         VariableDeclaration() = default;
424         VariableDeclaration(const VariableDeclaration &);
425         ~VariableDeclaration();
426
427         virtual VariableDeclaration *clone() const { return new VariableDeclaration(*this); }
428         virtual void visit(NodeVisitor &);
429 };
430
431 struct InterfaceBlock: Statement
432 {
433         NodePtr<Layout> layout;
434         std::string interface;
435         std::string block_name;
436         NodePtr<Block> members;
437         std::string instance_name;
438         bool array = false;
439
440         /* An interface block's ultimate base type is always a struct.  The
441         immediate type may be either that same struct or an array of it. */
442         TypeDeclaration *type_declaration = 0;
443         StructDeclaration *struct_declaration = 0;
444         InterfaceBlock *linked_block = 0;
445
446         InterfaceBlock() = default;
447         InterfaceBlock(const InterfaceBlock &);
448         ~InterfaceBlock();
449
450         virtual InterfaceBlock *clone() const { return new InterfaceBlock(*this); }
451         virtual void visit(NodeVisitor &);
452 };
453
454 struct FunctionDeclaration: Statement
455 {
456         std::string return_type;
457         std::string name;
458         NodeArray<VariableDeclaration> parameters;
459         bool virtua = false;
460         bool overrd = false;
461         Block body;
462
463         std::string signature;
464         FunctionDeclaration *definition = 0;
465         TypeDeclaration *return_type_declaration = 0;
466
467         FunctionDeclaration() = default;
468         FunctionDeclaration(const FunctionDeclaration &);
469
470         virtual FunctionDeclaration *clone() const { return new FunctionDeclaration(*this); }
471         virtual void visit(NodeVisitor &);
472 };
473
474 struct Conditional: Statement
475 {
476         NodePtr<Expression> condition;
477         Block body;
478         Block else_body;
479
480         virtual Conditional *clone() const { return new Conditional(*this); }
481         virtual void visit(NodeVisitor &);
482 };
483
484 struct Iteration: Statement
485 {
486         NodePtr<Statement> init_statement;
487         NodePtr<Expression> condition;
488         NodePtr<Expression> loop_expression;
489         Block body;
490
491         virtual Iteration *clone() const { return new Iteration(*this); }
492         virtual void visit(NodeVisitor &);
493 };
494
495 struct Passthrough: Statement
496 {
497         NodePtr<Expression> subscript;
498
499         virtual Passthrough *clone() const { return new Passthrough(*this); }
500         virtual void visit(NodeVisitor &);
501 };
502
503 struct Return: Statement
504 {
505         NodePtr<Expression> expression;
506
507         virtual Return *clone() const { return new Return(*this); }
508         virtual void visit(NodeVisitor &);
509 };
510
511 struct Jump: Statement
512 {
513         std::string keyword;
514
515         virtual Jump *clone() const { return new Jump(*this); }
516         virtual void visit(NodeVisitor &);
517 };
518
519 struct Stage
520 {
521         enum Type
522         {
523                 SHARED,
524                 VERTEX,
525                 GEOMETRY,
526                 FRAGMENT
527         };
528
529         Type type;
530         Stage *previous = 0;
531         Block content;
532         std::map<std::string, TypeDeclaration *> types;
533         std::map<std::string, InterfaceBlock *> interface_blocks;
534         std::map<std::string, FunctionDeclaration *> functions;
535         std::map<std::string, unsigned> locations;
536         std::map<std::string, unsigned> texture_bindings;
537         std::map<std::string, unsigned> uniform_block_bindings;
538         unsigned n_clip_distances = 0;
539         Features required_features;
540         std::vector<Diagnostic> diagnostics;
541
542         Stage(Type);
543
544         static const char *get_stage_name(Type);
545 };
546
547 struct Module
548 {
549         SourceMap source_map;
550         Stage shared;
551         std::list<Stage> stages;
552
553         Module();
554 };
555
556 std::string get_unused_variable_name(const Block &, const std::string &);
557 const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *);
558 bool has_layout_qualifier(const Layout *, const std::string &);
559 int get_layout_value(const Layout *, const std::string &, int = -1);
560 void add_layout_qualifier(RefPtr<Layout> &, const Layout::Qualifier &);
561 void add_to_chain(Assignment::Target &, Assignment::Target::ChainType, unsigned);
562 bool targets_overlap(const Assignment::Target &, const Assignment::Target &);
563
564 } // namespace SL
565 } // namespace GL
566 } // namespace Msp
567
568 #pragma pop_macro("interface")
569
570 #endif