]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/reflect.cpp
Add visitors to calculate offsets of struct members
[libs/gl.git] / source / glsl / reflect.cpp
index a3e36be8448c57eba60bd4ae6a154525e95a4b59..151735ab18f3790d51b94bbf61da68726ce56a39 100644 (file)
@@ -1,5 +1,7 @@
 #include "reflect.h"
 
+using namespace std;
+
 namespace Msp {
 namespace GL {
 namespace SL {
@@ -41,6 +43,114 @@ void LocationCounter::visit(VariableDeclaration &var)
                                r_count *= literal->value.value<int>();
 }
 
+
+void MemoryRequirementsCalculator::visit(BasicTypeDeclaration &basic)
+{
+       if(basic.kind==BasicTypeDeclaration::BOOL)
+       {
+               r_size = 1;
+               r_alignment = 1;
+       }
+       else if(basic.kind==BasicTypeDeclaration::INT || basic.kind==BasicTypeDeclaration::FLOAT)
+       {
+               r_size = basic.size/8;
+               r_alignment = r_size;
+       }
+       else if(basic.kind==BasicTypeDeclaration::VECTOR || basic.kind==BasicTypeDeclaration::MATRIX)
+       {
+               basic.base_type->visit(*this);
+               unsigned n_elem = basic.size&0xFFFF;
+               r_size *= n_elem;
+               if(basic.kind==BasicTypeDeclaration::VECTOR)
+                       r_alignment *= (n_elem==3 ? 4 : n_elem);
+       }
+       else if(basic.kind==BasicTypeDeclaration::ARRAY)
+               basic.base_type->visit(*this);
+}
+
+void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
+{
+       unsigned total = 0;
+       unsigned max_align = 1;
+       for(NodeList<Statement>::iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i)
+       {
+               r_size = 0;
+               r_alignment = 1;
+               r_offset = -1;
+               (*i)->visit(*this);
+               if(r_offset)
+                       total = r_offset;
+               total += r_alignment-1;
+               total -= total%r_alignment;
+               total += r_size;
+               max_align = max(max_align, r_alignment);
+       }
+       r_size = total;
+       r_alignment = max_align;
+}
+
+void MemoryRequirementsCalculator::visit(VariableDeclaration &var)
+{
+       if(var.layout)
+       {
+               const vector<Layout::Qualifier> qualifiers = var.layout->qualifiers;
+               for(vector<Layout::Qualifier>::const_iterator i=qualifiers.begin(); (r_offset<0 && i!=qualifiers.end()); ++i)
+                       if(i->name=="offset")
+                               r_offset = i->value;
+       }
+
+       if(var.type_declaration)
+               var.type_declaration->visit(*this);
+       if(var.array)
+               if(const Literal *literal = dynamic_cast<const Literal *>(var.array_size.get()))
+                       if(literal->value.check_type<int>())
+                               r_size += r_alignment*(literal->value.value<int>()-1);
+}
+
+
+set<Node *> DependencyCollector::apply(FunctionDeclaration &func)
+{
+       func.visit(*this);
+       return dependencies;
+}
+
+void DependencyCollector::visit(VariableReference &var)
+{
+       if(var.declaration && !locals.count(var.declaration))
+       {
+               dependencies.insert(var.declaration);
+               var.declaration->visit(*this);
+       }
+}
+
+void DependencyCollector::visit(InterfaceBlockReference &iface)
+{
+       if(iface.declaration)
+       {
+               dependencies.insert(iface.declaration);
+               iface.declaration->visit(*this);
+       }
+}
+
+void DependencyCollector::visit(FunctionCall &call)
+{
+       if(call.declaration)
+               dependencies.insert(call.declaration);
+       TraversingVisitor::visit(call);
+}
+
+void DependencyCollector::visit(VariableDeclaration &var)
+{
+       locals.insert(&var);
+       if(var.type_declaration)
+       {
+               dependencies.insert(var.type_declaration);
+               var.type_declaration->visit(*this);
+       }
+
+       TraversingVisitor::visit(var);
+}
+
 } // namespace SL
 } // namespace GL
 } // namespace Msp