]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/reflect.cpp
Move some type information functions to glsl/reflect.cpp
[libs/gl.git] / source / glsl / reflect.cpp
1 #include "reflect.h"
2
3 using namespace std;
4
5 namespace Msp {
6 namespace GL {
7 namespace SL {
8
9 bool is_scalar(const BasicTypeDeclaration &type)
10 {
11         return (type.kind==BasicTypeDeclaration::INT || type.kind==BasicTypeDeclaration::FLOAT);
12 }
13
14 bool is_vector_or_matrix(const BasicTypeDeclaration &type)
15 {
16         return (type.kind==BasicTypeDeclaration::VECTOR || type.kind==BasicTypeDeclaration::MATRIX);
17 }
18
19 BasicTypeDeclaration *get_element_type(BasicTypeDeclaration &type)
20 {
21         if(is_vector_or_matrix(type) || type.kind==BasicTypeDeclaration::ARRAY)
22         {
23                 BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type);
24                 return (basic_base ? get_element_type(*basic_base) : 0);
25         }
26         else
27                 return &type;
28 }
29
30 bool can_convert(const BasicTypeDeclaration &from, const BasicTypeDeclaration &to)
31 {
32         if(from.kind==BasicTypeDeclaration::INT && to.kind==BasicTypeDeclaration::FLOAT)
33                 return from.size<=to.size;
34         else if(from.kind!=to.kind)
35                 return false;
36         else if(is_vector_or_matrix(from) && from.size==to.size)
37         {
38                 BasicTypeDeclaration *from_base = dynamic_cast<BasicTypeDeclaration *>(from.base_type);
39                 BasicTypeDeclaration *to_base = dynamic_cast<BasicTypeDeclaration *>(to.base_type);
40                 return (from_base && to_base && can_convert(*from_base, *to_base));
41         }
42         else
43                 return false;
44 }
45
46
47 unsigned TypeComparer::next_tag = 1;
48
49 TypeComparer::TypeComparer():
50         first(0),
51         second(0),
52         first_tag(0),
53         r_result(false)
54 { }
55
56 void TypeComparer::compare(Node &node1, Node &node2)
57 {
58         if(&node1==&node2)
59                 r_result = true;
60         else
61         {
62                 second = &node2;
63                 node1.visit(*this);
64         }
65 }
66
67 template<typename T>
68 T *TypeComparer::multi_visit(T &node)
69 {
70         static unsigned tag = next_tag++;
71
72         if(second)
73         {
74                 Node *s = second;
75                 first = &node;
76                 first_tag = tag;
77                 second = 0;
78                 s->visit(*this);
79         }
80         else if(!first || tag!=first_tag)
81                 r_result = false;
82         else
83         {
84                 T *f = static_cast<T *>(first);
85                 first = 0;
86                 return f;
87         }
88
89         return 0;
90 }
91
92 void TypeComparer::visit(Literal &literal)
93 {
94         if(Literal *lit1 = multi_visit(literal))
95         {
96                 if(!lit1->type || !literal.type)
97                         r_result = false;
98                 else
99                 {
100                         compare(*lit1->type, *literal.type);
101                         if(r_result)
102                                 r_result = (literal.value.check_type<int>() && lit1->value.value<int>()==literal.value.value<int>());
103                 }
104         }
105 }
106
107 void TypeComparer::visit(VariableReference &var)
108 {
109         if(VariableReference *var1 = multi_visit(var))
110         {
111                 if(!var1->declaration || !var.declaration)
112                         r_result = false;
113                 else if(!var1->declaration->constant || !var.declaration->constant)
114                         r_result = false;
115                 else if(!var1->declaration->init_expression || !var.declaration->init_expression)
116                         r_result = false;
117                 else
118                         compare(*var1->declaration->init_expression, *var.declaration->init_expression);
119         }
120 }
121
122 void TypeComparer::visit(BasicTypeDeclaration &basic)
123 {
124         if(BasicTypeDeclaration *basic1 = multi_visit(basic))
125         {
126                 if(basic1->kind!=basic.kind || basic1->size!=basic.size)
127                         r_result = false;
128                 else if(basic1->base_type && basic.base_type)
129                         compare(*basic1->base_type, *basic.base_type);
130                 else
131                         r_result = (!basic1->base_type && !basic.base_type);
132         }
133 }
134
135 void TypeComparer::visit(ImageTypeDeclaration &image)
136 {
137         if(ImageTypeDeclaration *image1 = multi_visit(image))
138         {
139                 if(image1->dimensions!=image.dimensions || image1->array!=image.array)
140                         r_result = false;
141                 else if(image1->sampled!=image.sampled || image1->shadow!=image.shadow)
142                         r_result = false;
143                 else if(image1->base_type && image.base_type)
144                         compare(*image1->base_type, *image.base_type);
145                 else
146                         r_result = (!image1->base_type && !image.base_type);
147         }
148 }
149
150 void TypeComparer::visit(StructDeclaration &strct)
151 {
152         if(StructDeclaration *strct1 = multi_visit(strct))
153         {
154                 if(strct1->members.body.size()!=strct.members.body.size())
155                         r_result = false;
156                 else
157                 {
158                         r_result = true;
159                         NodeList<Statement>::const_iterator i = strct1->members.body.begin();
160                         NodeList<Statement>::const_iterator j = strct.members.body.begin();
161                         for(; (r_result && i!=strct1->members.body.end()); ++i, ++j)
162                                 compare(**i, **j);
163                 }
164         }
165 }
166
167 void TypeComparer::visit(VariableDeclaration &var)
168 {
169         if(VariableDeclaration *var1 = multi_visit(var))
170         {
171                 if(var1->name!=var.name || var1->array!=var.array)
172                         r_result = false;
173                 else if(!var1->type_declaration || !var.type_declaration)
174                         r_result = false;
175                 else
176                 {
177                         if(var1->array)
178                         {
179                                 r_result = false;
180                                 if(var1->array_size && var.array_size)
181                                         compare(*var1->array_size, *var.array_size);
182                         }
183                         if(r_result && var1->type_declaration!=var.type_declaration)
184                                 compare(*var1->type_declaration, *var.type_declaration);
185                         // TODO Compare layout qualifiers for interface block members
186                 }
187         }
188 }
189
190
191 LocationCounter::LocationCounter():
192         r_count(0)
193 { }
194
195 void LocationCounter::visit(BasicTypeDeclaration &basic)
196 {
197         r_count = basic.kind==BasicTypeDeclaration::MATRIX ? basic.size>>16 : 1;
198 }
199
200 void LocationCounter::visit(ImageTypeDeclaration &)
201 {
202         r_count = 1;
203 }
204
205 void LocationCounter::visit(StructDeclaration &strct)
206 {
207         unsigned total = 0;
208         for(NodeList<Statement>::const_iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
209         {
210                 r_count = 1;
211                 (*i)->visit(*this);
212                 total += r_count;
213         }
214         r_count = total;
215 }
216
217 void LocationCounter::visit(VariableDeclaration &var)
218 {
219         r_count = 1;
220         if(var.type_declaration)
221                 var.type_declaration->visit(*this);
222         if(var.array)
223                 if(const Literal *literal = dynamic_cast<const Literal *>(var.array_size.get()))
224                         if(literal->value.check_type<int>())
225                                 r_count *= literal->value.value<int>();
226 }
227
228
229 void MemoryRequirementsCalculator::visit(BasicTypeDeclaration &basic)
230 {
231         if(basic.kind==BasicTypeDeclaration::BOOL)
232         {
233                 r_size = 1;
234                 r_alignment = 1;
235         }
236         else if(basic.kind==BasicTypeDeclaration::INT || basic.kind==BasicTypeDeclaration::FLOAT)
237         {
238                 r_size = basic.size/8;
239                 r_alignment = r_size;
240         }
241         else if(basic.kind==BasicTypeDeclaration::VECTOR || basic.kind==BasicTypeDeclaration::MATRIX)
242         {
243                 basic.base_type->visit(*this);
244                 unsigned n_elem = basic.size&0xFFFF;
245                 r_size *= n_elem;
246                 if(basic.kind==BasicTypeDeclaration::VECTOR)
247                         r_alignment *= (n_elem==3 ? 4 : n_elem);
248         }
249         else if(basic.kind==BasicTypeDeclaration::ARRAY)
250                 basic.base_type->visit(*this);
251 }
252
253 void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
254 {
255         unsigned total = 0;
256         unsigned max_align = 1;
257         for(NodeList<Statement>::iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
258         {
259                 r_size = 0;
260                 r_alignment = 1;
261                 r_offset = -1;
262                 (*i)->visit(*this);
263                 if(r_offset)
264                         total = r_offset;
265                 total += r_alignment-1;
266                 total -= total%r_alignment;
267                 total += r_size;
268                 max_align = max(max_align, r_alignment);
269         }
270         r_size = total;
271         r_alignment = max_align;
272 }
273
274 void MemoryRequirementsCalculator::visit(VariableDeclaration &var)
275 {
276         if(var.layout)
277         {
278                 const vector<Layout::Qualifier> qualifiers = var.layout->qualifiers;
279                 for(vector<Layout::Qualifier>::const_iterator i=qualifiers.begin(); (r_offset<0 && i!=qualifiers.end()); ++i)
280                         if(i->name=="offset")
281                                 r_offset = i->value;
282         }
283
284         if(var.type_declaration)
285                 var.type_declaration->visit(*this);
286         if(var.array)
287                 if(const Literal *literal = dynamic_cast<const Literal *>(var.array_size.get()))
288                         if(literal->value.check_type<int>())
289                                 r_size += r_alignment*(literal->value.value<int>()-1);
290 }
291
292
293 set<Node *> DependencyCollector::apply(FunctionDeclaration &func)
294 {
295         func.visit(*this);
296         return dependencies;
297 }
298
299 void DependencyCollector::visit(VariableReference &var)
300 {
301         if(var.declaration && !locals.count(var.declaration))
302         {
303                 dependencies.insert(var.declaration);
304                 var.declaration->visit(*this);
305         }
306 }
307
308 void DependencyCollector::visit(InterfaceBlockReference &iface)
309 {
310         if(iface.declaration)
311         {
312                 dependencies.insert(iface.declaration);
313                 iface.declaration->visit(*this);
314         }
315 }
316
317 void DependencyCollector::visit(FunctionCall &call)
318 {
319         if(call.declaration)
320         {
321                 dependencies.insert(call.declaration);
322                 call.declaration->visit(*this);
323         }
324         TraversingVisitor::visit(call);
325 }
326
327 void DependencyCollector::visit(VariableDeclaration &var)
328 {
329         locals.insert(&var);
330         if(var.type_declaration)
331         {
332                 dependencies.insert(var.type_declaration);
333                 var.type_declaration->visit(*this);
334         }
335
336         TraversingVisitor::visit(var);
337 }
338
339 void DependencyCollector::visit(FunctionDeclaration &func)
340 {
341         if(!visited_functions.count(&func))
342         {
343                 visited_functions.insert(&func);
344                 TraversingVisitor::visit(func);
345         }
346 }
347
348 } // namespace SL
349 } // namespace GL
350 } // namespace Msp