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