]> git.tdb.fi Git - libs/gl.git/blob - source/programcompiler.h
Properly handle the legacy replacement of fragment shader output
[libs/gl.git] / source / programcompiler.h
1 #ifndef MSP_GL_PROGRAMCOMPILER_H_
2 #define MSP_GL_PROGRAMCOMPILER_H_
3
4 #include <set>
5 #include "programparser.h"
6 #include "programsyntax.h"
7
8 namespace Msp {
9 namespace GL {
10
11 class Program;
12 class Resources;
13
14 class ProgramCompiler
15 {
16 private:
17         struct Visitor: ProgramSyntax::TraversingVisitor
18         {
19                 typedef void ResultType;
20
21                 ProgramSyntax::Stage *stage;
22
23                 Visitor();
24
25                 virtual void apply(ProgramSyntax::Stage &);
26                 void get_result() const { }
27         };
28
29         struct Formatter: Visitor
30         {
31                 typedef std::string ResultType;
32
33                 std::string formatted;
34                 unsigned indent;
35                 bool parameter_list;
36                 unsigned else_if;
37                 std::string block_interface;
38
39                 Formatter();
40
41                 virtual void apply(ProgramSyntax::Stage &);
42                 const std::string &get_result() const { return formatted; }
43                 using Visitor::visit;
44                 virtual void visit(ProgramSyntax::Block &);
45                 virtual void visit(ProgramSyntax::Literal &);
46                 virtual void visit(ProgramSyntax::ParenthesizedExpression &);
47                 virtual void visit(ProgramSyntax::VariableReference &);
48                 virtual void visit(ProgramSyntax::MemberAccess &);
49                 virtual void visit(ProgramSyntax::UnaryExpression &);
50                 virtual void visit(ProgramSyntax::BinaryExpression &);
51                 virtual void visit(ProgramSyntax::Assignment &);
52                 virtual void visit(ProgramSyntax::FunctionCall &);
53                 virtual void visit(ProgramSyntax::ExpressionStatement &);
54                 virtual void visit(ProgramSyntax::Import &);
55                 virtual void visit(ProgramSyntax::Layout &);
56                 virtual void visit(ProgramSyntax::InterfaceLayout &);
57                 virtual void visit(ProgramSyntax::StructDeclaration &);
58                 virtual void visit(ProgramSyntax::VariableDeclaration &);
59                 virtual void visit(ProgramSyntax::InterfaceBlock &);
60                 virtual void visit(ProgramSyntax::FunctionDeclaration &);
61                 virtual void visit(ProgramSyntax::Conditional &);
62                 virtual void visit(ProgramSyntax::Iteration &);
63                 virtual void visit(ProgramSyntax::Return &);
64                 virtual void visit(ProgramSyntax::Jump &);
65         };
66
67         template<typename T>
68         struct NodeGatherer: Visitor
69         {
70                 typedef std::list<T *> ResultType;
71
72                 std::list<T *> nodes;
73
74                 const ResultType &get_result() const { return nodes; }
75                 using Visitor::visit;
76                 virtual void visit(T &n) { nodes.push_back(&n); }
77         };
78
79         struct DeclarationCombiner: Visitor
80         {
81                 bool toplevel;
82                 std::map<std::string, std::vector<ProgramSyntax::FunctionDeclaration *> > functions;
83                 std::map<std::string, ProgramSyntax::VariableDeclaration *> variables;
84                 bool remove_node;
85
86                 DeclarationCombiner();
87
88                 using Visitor::visit;
89                 virtual void visit(ProgramSyntax::Block &);
90                 virtual void visit(ProgramSyntax::FunctionDeclaration &);
91                 virtual void visit(ProgramSyntax::VariableDeclaration &);
92         };
93
94         struct VariableResolver: Visitor
95         {
96                 std::vector<ProgramSyntax::Block *> blocks;
97                 ProgramSyntax::StructDeclaration *type;
98                 bool anonymous;
99                 std::string block_interface;
100                 bool record_target;
101                 ProgramSyntax::VariableDeclaration *assignment_target;
102                 bool self_referencing;
103
104                 VariableResolver();
105
106                 virtual void apply(ProgramSyntax::Stage &);
107                 using Visitor::visit;
108                 virtual void visit(ProgramSyntax::Block &);
109                 virtual void visit(ProgramSyntax::VariableReference &);
110                 virtual void visit(ProgramSyntax::MemberAccess &);
111                 virtual void visit(ProgramSyntax::BinaryExpression &);
112                 virtual void visit(ProgramSyntax::Assignment &);
113                 virtual void visit(ProgramSyntax::StructDeclaration &);
114                 virtual void visit(ProgramSyntax::VariableDeclaration &);
115                 virtual void visit(ProgramSyntax::InterfaceBlock &);
116         };
117
118         struct FunctionResolver: Visitor
119         {
120                 std::map<std::string, std::vector<ProgramSyntax::FunctionDeclaration *> > functions;
121
122                 using Visitor::visit;
123                 virtual void visit(ProgramSyntax::FunctionCall &);
124                 virtual void visit(ProgramSyntax::FunctionDeclaration &);
125         };
126
127         struct BlockModifier: Visitor
128         {
129                 bool remove_node;
130                 std::list<RefPtr<ProgramSyntax::Node> > insert_nodes;
131
132                 BlockModifier();
133
134                 void flatten_block(ProgramSyntax::Block &);
135                 void apply_and_increment(ProgramSyntax::Block &, std::list<RefPtr<ProgramSyntax::Node> >::iterator &);
136                 using Visitor::visit;
137                 virtual void visit(ProgramSyntax::Block &);
138         };
139
140         struct InterfaceGenerator: BlockModifier
141         {
142                 std::string in_prefix;
143                 std::string out_prefix;
144                 unsigned scope_level;
145                 std::map<std::string, RefPtr<ProgramSyntax::VariableDeclaration> > iface_declarations;
146
147                 InterfaceGenerator();
148
149                 static std::string get_out_prefix(ProgramSyntax::StageType);
150                 virtual void apply(ProgramSyntax::Stage &);
151                 using Visitor::visit;
152                 virtual void visit(ProgramSyntax::Block &);
153                 std::string change_prefix(const std::string &, const std::string &) const;
154                 bool generate_interface(ProgramSyntax::VariableDeclaration &, const std::string &, const std::string &);
155                 void insert_assignment(const std::string &, ProgramSyntax::Expression *);
156                 virtual void visit(ProgramSyntax::VariableReference &);
157                 virtual void visit(ProgramSyntax::VariableDeclaration &);
158                 virtual void visit(ProgramSyntax::Passthrough &);
159         };
160
161         struct VariableRenamer: Visitor
162         {
163                 using Visitor::visit;
164                 virtual void visit(ProgramSyntax::VariableReference &);
165                 virtual void visit(ProgramSyntax::VariableDeclaration &);
166         };
167
168         struct DeclarationReorderer: Visitor
169         {
170                 enum DeclarationKind
171                 {
172                         NO_DECLARATION,
173                         LAYOUT,
174                         STRUCT,
175                         VARIABLE,
176                         FUNCTION
177                 };
178
179                 DeclarationKind kind;
180
181                 DeclarationReorderer();
182
183                 using Visitor::visit;
184                 virtual void visit(ProgramSyntax::Block &);
185                 virtual void visit(ProgramSyntax::InterfaceLayout &) { kind = LAYOUT; }
186                 virtual void visit(ProgramSyntax::StructDeclaration &) { kind = STRUCT; }
187                 virtual void visit(ProgramSyntax::VariableDeclaration &) { kind = VARIABLE; }
188                 virtual void visit(ProgramSyntax::InterfaceBlock &) { kind = VARIABLE; }
189                 virtual void visit(ProgramSyntax::FunctionDeclaration &) { kind = FUNCTION; }
190         };
191
192         struct InlineableFunctionLocator: Visitor
193         {
194                 typedef std::set<ProgramSyntax::FunctionDeclaration *> ResultType;
195
196                 std::map<ProgramSyntax::FunctionDeclaration *, unsigned> refcounts;
197                 std::set<ProgramSyntax::FunctionDeclaration *> inlineable;
198                 ProgramSyntax::FunctionDeclaration *in_function;
199
200                 InlineableFunctionLocator();
201
202                 const ResultType &get_result() const { return inlineable; }
203                 using Visitor::visit;
204                 virtual void visit(ProgramSyntax::FunctionCall &);
205                 virtual void visit(ProgramSyntax::FunctionDeclaration &);
206         };
207
208         struct FunctionInliner: Visitor
209         {
210                 std::set<ProgramSyntax::FunctionDeclaration *> inlineable;
211                 unsigned extract_result;
212                 RefPtr<ProgramSyntax::Expression> inline_result;
213
214                 FunctionInliner();
215                 FunctionInliner(const std::set<ProgramSyntax::FunctionDeclaration *> &);
216
217                 void visit_and_inline(RefPtr<ProgramSyntax::Expression> &);
218                 using Visitor::visit;
219                 virtual void visit(ProgramSyntax::Block &);
220                 virtual void visit(ProgramSyntax::UnaryExpression &);
221                 virtual void visit(ProgramSyntax::BinaryExpression &);
222                 virtual void visit(ProgramSyntax::FunctionCall &);
223                 virtual void visit(ProgramSyntax::Return &);
224         };
225
226         struct ExpressionEvaluator: ProgramSyntax::NodeVisitor
227         {
228                 typedef std::map<ProgramSyntax::VariableDeclaration *, ProgramSyntax::Expression *> ValueMap;
229
230                 const ValueMap *variable_values;
231                 float result;
232                 bool result_valid;
233
234                 ExpressionEvaluator();
235                 ExpressionEvaluator(const ValueMap &);
236
237                 using ProgramSyntax::NodeVisitor::visit;
238                 virtual void visit(ProgramSyntax::Literal &);
239                 virtual void visit(ProgramSyntax::ParenthesizedExpression &);
240                 virtual void visit(ProgramSyntax::VariableReference &);
241                 virtual void visit(ProgramSyntax::UnaryExpression &);
242                 virtual void visit(ProgramSyntax::BinaryExpression &);
243         };
244
245         struct ConstantConditionEliminator: BlockModifier
246         {
247                 unsigned scope_level;
248                 ExpressionEvaluator::ValueMap variable_values;
249
250                 ConstantConditionEliminator();
251
252                 using Visitor::visit;
253                 virtual void visit(ProgramSyntax::Block &);
254                 virtual void visit(ProgramSyntax::Assignment &);
255                 virtual void visit(ProgramSyntax::VariableDeclaration &);
256                 virtual void visit(ProgramSyntax::Conditional &);
257                 virtual void visit(ProgramSyntax::Iteration &);
258         };
259
260         struct UnusedVariableLocator: Visitor
261         {
262                 struct VariableInfo
263                 {
264                         bool local;
265                         std::vector<ProgramSyntax::Node *> assignments;
266                         bool conditionally_assigned;
267                         bool referenced;
268
269                         VariableInfo();
270                 };
271
272                 typedef std::set<ProgramSyntax::Node *> ResultType;
273                 typedef std::map<ProgramSyntax::VariableDeclaration *, VariableInfo> BlockVariableMap;
274
275                 std::set<ProgramSyntax::Node *> unused_nodes;
276                 std::map<ProgramSyntax::VariableDeclaration *, ProgramSyntax::Node *> aggregates;
277                 ProgramSyntax::Node *aggregate;
278                 std::vector<BlockVariableMap> variables;
279                 ProgramSyntax::Assignment *assignment;
280                 bool assignment_target;
281                 bool global_scope;
282
283                 UnusedVariableLocator();
284
285                 virtual void apply(ProgramSyntax::Stage &);
286                 const ResultType &get_result() const { return unused_nodes; }
287                 using Visitor::visit;
288                 virtual void visit(ProgramSyntax::VariableReference &);
289                 virtual void visit(ProgramSyntax::MemberAccess &);
290                 virtual void visit(ProgramSyntax::BinaryExpression &);
291                 virtual void visit(ProgramSyntax::Assignment &);
292                 void record_assignment(ProgramSyntax::VariableDeclaration &, ProgramSyntax::Node &, bool);
293                 void clear_assignments(VariableInfo &, bool);
294                 virtual void visit(ProgramSyntax::ExpressionStatement &);
295                 virtual void visit(ProgramSyntax::StructDeclaration &);
296                 virtual void visit(ProgramSyntax::VariableDeclaration &);
297                 virtual void visit(ProgramSyntax::InterfaceBlock &);
298                 virtual void visit(ProgramSyntax::FunctionDeclaration &);
299                 void merge_down_variables();
300                 virtual void visit(ProgramSyntax::Conditional &);
301                 virtual void visit(ProgramSyntax::Iteration &);
302         };
303
304         struct UnusedFunctionLocator: Visitor
305         {
306                 typedef std::set<ProgramSyntax::Node *> ResultType;
307
308                 std::set<ProgramSyntax::Node *> unused_nodes;
309                 std::set<ProgramSyntax::FunctionDeclaration *> used_definitions;
310
311                 const ResultType &get_result() const { return unused_nodes; }
312                 using Visitor::visit;
313                 virtual void visit(ProgramSyntax::FunctionCall &);
314                 virtual void visit(ProgramSyntax::FunctionDeclaration &);
315         };
316
317         struct NodeRemover: Visitor
318         {
319                 std::set<ProgramSyntax::Node *> to_remove;
320
321                 NodeRemover() { }
322                 NodeRemover(const std::set<ProgramSyntax::Node *> &);
323
324                 using Visitor::visit;
325                 virtual void visit(ProgramSyntax::Block &);
326                 virtual void visit(ProgramSyntax::VariableDeclaration &);
327         };
328
329         struct LegacyConverter: BlockModifier
330         {
331                 Version target_version;
332                 std::string type;
333                 ProgramSyntax::VariableDeclaration *frag_out;
334
335                 LegacyConverter();
336                 LegacyConverter(const Version &);
337
338                 bool check_version(const Version &);
339                 using Visitor::visit;
340                 virtual void visit(ProgramSyntax::VariableReference &);
341                 virtual void visit(ProgramSyntax::Assignment &);
342                 virtual void visit(ProgramSyntax::FunctionCall &);
343                 virtual void visit(ProgramSyntax::VariableDeclaration &);
344                 virtual void visit(ProgramSyntax::InterfaceBlock &);
345         };
346
347         Resources *resources;
348         ProgramParser parser;
349         ProgramSyntax::Module *module;
350
351 public:
352         ProgramCompiler();
353
354         void compile(const std::string &);
355         void compile(IO::Base &, Resources * = 0);
356         void add_shaders(Program &);
357
358 private:
359         static ProgramSyntax::Module *create_builtins_module();
360         static ProgramSyntax::Module &get_builtins_module();
361         static ProgramSyntax::Stage *get_builtins(ProgramSyntax::StageType);
362         void process();
363         void import(const std::string &);
364         void generate(ProgramSyntax::Stage &);
365         bool optimize(ProgramSyntax::Stage &);
366         static void inject_block(ProgramSyntax::Block &, const ProgramSyntax::Block &);
367         template<typename T>
368         static typename T::ResultType apply(ProgramSyntax::Stage &);
369         template<typename T, typename A>
370         static typename T::ResultType apply(ProgramSyntax::Stage &, const A &);
371 };
372
373 } // namespace GL
374 } // namespace Msp
375
376 #endif