]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/reflect.cpp
Rewrite type comparisons as a visitor
[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(BasicTypeDeclaration &basic)
55 {
56         if(BasicTypeDeclaration *basic1 = multi_visit(basic))
57         {
58                 if(basic1->kind!=basic.kind || basic1->size!=basic.size)
59                         r_result = false;
60                 else if(basic1->base_type && basic.base_type)
61                         compare(*basic1->base_type, *basic.base_type);
62                 else
63                         r_result = (!basic1->base_type && !basic.base_type);
64         }
65 }
66
67 void TypeComparer::visit(ImageTypeDeclaration &image)
68 {
69         if(ImageTypeDeclaration *image1 = multi_visit(image))
70         {
71                 if(image1->dimensions!=image.dimensions || image1->array!=image.array)
72                         r_result = false;
73                 else if(image1->sampled!=image.sampled || image1->shadow!=image.shadow)
74                         r_result = false;
75                 else if(image1->base_type && image.base_type)
76                         compare(*image1->base_type, *image.base_type);
77                 else
78                         r_result = (!image1->base_type && !image.base_type);
79         }
80 }
81
82 void TypeComparer::visit(StructDeclaration &strct)
83 {
84         if(StructDeclaration *strct1 = multi_visit(strct))
85         {
86                 if(strct1->members.body.size()!=strct.members.body.size())
87                         r_result = false;
88                 else
89                 {
90                         r_result = true;
91                         NodeList<Statement>::const_iterator i = strct1->members.body.begin();
92                         NodeList<Statement>::const_iterator j = strct.members.body.begin();
93                         for(; (r_result && i!=strct1->members.body.end()); ++i, ++j)
94                                 compare(**i, **j);
95                 }
96         }
97 }
98
99 void TypeComparer::visit(VariableDeclaration &var)
100 {
101         if(VariableDeclaration *var1 = multi_visit(var))
102         {
103                 if(var1->name!=var.name || var1->array!=var.array)
104                         r_result = false;
105                 else if(!var1->type_declaration || !var.type_declaration)
106                         r_result = false;
107                 else
108                 {
109                         // TODO Compare array sizes
110                         if(var1->type_declaration!=var.type_declaration)
111                                 compare(*var1->type_declaration, *var.type_declaration);
112                         // TODO Compare layout qualifiers for interface block members
113                 }
114         }
115 }
116
117
118 LocationCounter::LocationCounter():
119         r_count(0)
120 { }
121
122 void LocationCounter::visit(BasicTypeDeclaration &basic)
123 {
124         r_count = basic.kind==BasicTypeDeclaration::MATRIX ? basic.size>>16 : 1;
125 }
126
127 void LocationCounter::visit(ImageTypeDeclaration &)
128 {
129         r_count = 1;
130 }
131
132 void LocationCounter::visit(StructDeclaration &strct)
133 {
134         unsigned total = 0;
135         for(NodeList<Statement>::const_iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
136         {
137                 r_count = 1;
138                 (*i)->visit(*this);
139                 total += r_count;
140         }
141         r_count = total;
142 }
143
144 void LocationCounter::visit(VariableDeclaration &var)
145 {
146         r_count = 1;
147         if(var.type_declaration)
148                 var.type_declaration->visit(*this);
149         if(var.array)
150                 if(const Literal *literal = dynamic_cast<const Literal *>(var.array_size.get()))
151                         if(literal->value.check_type<int>())
152                                 r_count *= literal->value.value<int>();
153 }
154
155
156 void MemoryRequirementsCalculator::visit(BasicTypeDeclaration &basic)
157 {
158         if(basic.kind==BasicTypeDeclaration::BOOL)
159         {
160                 r_size = 1;
161                 r_alignment = 1;
162         }
163         else if(basic.kind==BasicTypeDeclaration::INT || basic.kind==BasicTypeDeclaration::FLOAT)
164         {
165                 r_size = basic.size/8;
166                 r_alignment = r_size;
167         }
168         else if(basic.kind==BasicTypeDeclaration::VECTOR || basic.kind==BasicTypeDeclaration::MATRIX)
169         {
170                 basic.base_type->visit(*this);
171                 unsigned n_elem = basic.size&0xFFFF;
172                 r_size *= n_elem;
173                 if(basic.kind==BasicTypeDeclaration::VECTOR)
174                         r_alignment *= (n_elem==3 ? 4 : n_elem);
175         }
176         else if(basic.kind==BasicTypeDeclaration::ARRAY)
177                 basic.base_type->visit(*this);
178 }
179
180 void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
181 {
182         unsigned total = 0;
183         unsigned max_align = 1;
184         for(NodeList<Statement>::iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
185         {
186                 r_size = 0;
187                 r_alignment = 1;
188                 r_offset = -1;
189                 (*i)->visit(*this);
190                 if(r_offset)
191                         total = r_offset;
192                 total += r_alignment-1;
193                 total -= total%r_alignment;
194                 total += r_size;
195                 max_align = max(max_align, r_alignment);
196         }
197         r_size = total;
198         r_alignment = max_align;
199 }
200
201 void MemoryRequirementsCalculator::visit(VariableDeclaration &var)
202 {
203         if(var.layout)
204         {
205                 const vector<Layout::Qualifier> qualifiers = var.layout->qualifiers;
206                 for(vector<Layout::Qualifier>::const_iterator i=qualifiers.begin(); (r_offset<0 && i!=qualifiers.end()); ++i)
207                         if(i->name=="offset")
208                                 r_offset = i->value;
209         }
210
211         if(var.type_declaration)
212                 var.type_declaration->visit(*this);
213         if(var.array)
214                 if(const Literal *literal = dynamic_cast<const Literal *>(var.array_size.get()))
215                         if(literal->value.check_type<int>())
216                                 r_size += r_alignment*(literal->value.value<int>()-1);
217 }
218
219
220 set<Node *> DependencyCollector::apply(FunctionDeclaration &func)
221 {
222         func.visit(*this);
223         return dependencies;
224 }
225
226 void DependencyCollector::visit(VariableReference &var)
227 {
228         if(var.declaration && !locals.count(var.declaration))
229         {
230                 dependencies.insert(var.declaration);
231                 var.declaration->visit(*this);
232         }
233 }
234
235 void DependencyCollector::visit(InterfaceBlockReference &iface)
236 {
237         if(iface.declaration)
238         {
239                 dependencies.insert(iface.declaration);
240                 iface.declaration->visit(*this);
241         }
242 }
243
244 void DependencyCollector::visit(FunctionCall &call)
245 {
246         if(call.declaration)
247                 dependencies.insert(call.declaration);
248         TraversingVisitor::visit(call);
249 }
250
251 void DependencyCollector::visit(VariableDeclaration &var)
252 {
253         locals.insert(&var);
254         if(var.type_declaration)
255         {
256                 dependencies.insert(var.type_declaration);
257                 var.type_declaration->visit(*this);
258         }
259
260         TraversingVisitor::visit(var);
261 }
262
263 } // namespace SL
264 } // namespace GL
265 } // namespace Msp