X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Freflect.cpp;h=93d64e5fdb62aac1087d080efb37a0687fd99901;hb=c701c8787cb19fbb6dc5b0bfae1a94e2b07dd549;hp=a3e36be8448c57eba60bd4ae6a154525e95a4b59;hpb=8f5f54a9e165dae424e5b0bb8e488c3d01849bf6;p=libs%2Fgl.git diff --git a/source/glsl/reflect.cpp b/source/glsl/reflect.cpp index a3e36be8..93d64e5f 100644 --- a/source/glsl/reflect.cpp +++ b/source/glsl/reflect.cpp @@ -1,9 +1,120 @@ #include "reflect.h" +using namespace std; + namespace Msp { namespace GL { namespace SL { +unsigned TypeComparer::next_tag = 1; + +TypeComparer::TypeComparer(): + first(0), + second(0), + first_tag(0), + r_result(false) +{ } + +void TypeComparer::compare(Node &node1, Node &node2) +{ + if(&node1==&node2) + r_result = true; + else + { + second = &node2; + node1.visit(*this); + } +} + +template +T *TypeComparer::multi_visit(T &node) +{ + static unsigned tag = next_tag++; + + if(second) + { + Node *s = second; + first = &node; + first_tag = tag; + second = 0; + s->visit(*this); + } + else if(!first || tag!=first_tag) + r_result = false; + else + { + T *f = static_cast(first); + first = 0; + return f; + } + + return 0; +} + +void TypeComparer::visit(BasicTypeDeclaration &basic) +{ + if(BasicTypeDeclaration *basic1 = multi_visit(basic)) + { + if(basic1->kind!=basic.kind || basic1->size!=basic.size) + r_result = false; + else if(basic1->base_type && basic.base_type) + compare(*basic1->base_type, *basic.base_type); + else + r_result = (!basic1->base_type && !basic.base_type); + } +} + +void TypeComparer::visit(ImageTypeDeclaration &image) +{ + if(ImageTypeDeclaration *image1 = multi_visit(image)) + { + if(image1->dimensions!=image.dimensions || image1->array!=image.array) + r_result = false; + else if(image1->sampled!=image.sampled || image1->shadow!=image.shadow) + r_result = false; + else if(image1->base_type && image.base_type) + compare(*image1->base_type, *image.base_type); + else + r_result = (!image1->base_type && !image.base_type); + } +} + +void TypeComparer::visit(StructDeclaration &strct) +{ + if(StructDeclaration *strct1 = multi_visit(strct)) + { + if(strct1->members.body.size()!=strct.members.body.size()) + r_result = false; + else + { + r_result = true; + NodeList::const_iterator i = strct1->members.body.begin(); + NodeList::const_iterator j = strct.members.body.begin(); + for(; (r_result && i!=strct1->members.body.end()); ++i, ++j) + compare(**i, **j); + } + } +} + +void TypeComparer::visit(VariableDeclaration &var) +{ + if(VariableDeclaration *var1 = multi_visit(var)) + { + if(var1->name!=var.name || var1->array!=var.array) + r_result = false; + else if(!var1->type_declaration || !var.type_declaration) + r_result = false; + else + { + // TODO Compare array sizes + if(var1->type_declaration!=var.type_declaration) + compare(*var1->type_declaration, *var.type_declaration); + // TODO Compare layout qualifiers for interface block members + } + } +} + + LocationCounter::LocationCounter(): r_count(0) { } @@ -41,6 +152,114 @@ void LocationCounter::visit(VariableDeclaration &var) r_count *= literal->value.value(); } + +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::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 qualifiers = var.layout->qualifiers; + for(vector::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(var.array_size.get())) + if(literal->value.check_type()) + r_size += r_alignment*(literal->value.value()-1); +} + + +set 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