]> 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 688c99bf81b951ae288a23c9d5409e94fd7903c8..151735ab18f3790d51b94bbf61da68726ce56a39 100644 (file)
@@ -44,6 +44,70 @@ void LocationCounter::visit(VariableDeclaration &var)
 }
 
 
+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);