X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Fgenerate.cpp;h=2ff751946528f75e2a39f6a512565231ed10ce8c;hp=f29d65f58bfeeaf4fe837fa2222226473c6d3c66;hb=6dcf74922f46b086ad394c19fd6ce083a635b290;hpb=f639d088c478fe5d266f9f5779928735b5176976 diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index f29d65f5..2ff75194 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include "builtin.h" #include "generate.h" @@ -10,57 +12,6 @@ namespace Msp { namespace GL { namespace SL { -void DeclarationCombiner::apply(Stage &stage) -{ - stage.content.visit(*this); - NodeRemover().apply(stage, nodes_to_remove); -} - -void DeclarationCombiner::visit(Block &block) -{ - if(current_block) - return; - - TraversingVisitor::visit(block); -} - -void DeclarationCombiner::visit(VariableDeclaration &var) -{ - VariableDeclaration *&ptr = variables[var.name]; - if(ptr) - { - ptr->type = var.type; - if(var.init_expression) - ptr->init_expression = var.init_expression; - if(var.layout) - { - if(ptr->layout) - { - for(vector::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i) - { - bool found = false; - for(vector::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j) - if(j->name==i->name) - { - j->has_value = i->value; - j->value = i->value; - found = true; - } - - if(!found) - ptr->layout->qualifiers.push_back(*i); - } - } - else - ptr->layout = var.layout; - } - nodes_to_remove.insert(&var); - } - else - ptr = &var; -} - - ConstantSpecializer::ConstantSpecializer(): values(0) { } @@ -116,31 +67,58 @@ void ConstantSpecializer::visit(VariableDeclaration &var) void BlockHierarchyResolver::enter(Block &block) { + r_any_resolved |= (current_block!=block.parent); block.parent = current_block; } TypeResolver::TypeResolver(): - stage(0) + stage(0), + iface_block(0), + r_any_resolved(false) { } -void TypeResolver::apply(Stage &s) +bool TypeResolver::apply(Stage &s) { stage = &s; s.types.clear(); + r_any_resolved = false; s.content.visit(*this); + return r_any_resolved; } -TypeDeclaration *TypeResolver::resolve_type(const string &name) +TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type) { + map::iterator i = array_types.find(&type); + if(i!=array_types.end()) + return i->second; + + BasicTypeDeclaration *array = new BasicTypeDeclaration; + array->source = BUILTIN_SOURCE; + array->name = type.name+"[]"; + array->kind = BasicTypeDeclaration::ARRAY; + array->base = type.name; + array->base_type = &type; + stage->content.body.insert(type_insert_point, array); + array_types[&type] = array; + return array; +} + +void TypeResolver::resolve_type(TypeDeclaration *&type, const string &name, bool array) +{ + TypeDeclaration *resolved = 0; map::iterator i = stage->types.find(name); if(i!=stage->types.end()) { map::iterator j = alias_map.find(i->second); - return (j!=alias_map.end() ? j->second : i->second); + resolved = (j!=alias_map.end() ? j->second : i->second); } - else - return 0; + + if(resolved && array) + resolved = get_or_create_array_type(*resolved); + + r_any_resolved |= (resolved!=type); + type=resolved; } void TypeResolver::visit(Block &block) @@ -155,13 +133,16 @@ void TypeResolver::visit(Block &block) void TypeResolver::visit(BasicTypeDeclaration &type) { - type.base_type = resolve_type(type.base); + resolve_type(type.base_type, type.base, false); if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type) if(BasicTypeDeclaration *basic_base = dynamic_cast(type.base_type)) if(basic_base->kind==BasicTypeDeclaration::VECTOR) { type.kind = BasicTypeDeclaration::MATRIX; + /* A matrix's base type is its column vector type. This will put + the column vector's size, i.e. the matrix's row count, in the high + half of the size. */ type.size |= basic_base->size<<16; } @@ -175,7 +156,7 @@ void TypeResolver::visit(BasicTypeDeclaration &type) void TypeResolver::visit(ImageTypeDeclaration &type) { - type.base_type = resolve_type(type.base); + resolve_type(type.base_type, type.base, false); stage->types.insert(make_pair(type.name, &type)); } @@ -187,31 +168,40 @@ void TypeResolver::visit(StructDeclaration &strct) void TypeResolver::visit(VariableDeclaration &var) { - TypeDeclaration *type = resolve_type(var.type); - if(var.array && type) + resolve_type(var.type_declaration, var.type, var.array); + if(iface_block && var.interface==iface_block->interface) + var.interface.clear(); +} + +void TypeResolver::visit(InterfaceBlock &iface) +{ + if(iface.members) { - map::iterator i = array_types.find(type); - if(i==array_types.end()) - { - BasicTypeDeclaration *array = new BasicTypeDeclaration; - array->source = BUILTIN_SOURCE; - array->name = type->name+"[]"; - array->kind = BasicTypeDeclaration::ARRAY; - array->base = type->name; - array->base_type = type; - stage->content.body.insert(type_insert_point, array); - array->visit(*this); - type = array; - } - else - type = i->second; + SetForScope set_iface(iface_block, &iface); + iface.members->visit(*this); + + StructDeclaration *strct = new StructDeclaration; + strct->source = INTERNAL_SOURCE; + strct->name = format("_%s_%s", iface.interface, iface.name); + strct->members.body.splice(strct->members.body.begin(), iface.members->body); + stage->content.body.insert(type_insert_point, strct); + stage->types.insert(make_pair(strct->name, strct)); + + iface.members = 0; + strct->interface_block = &iface; + iface.struct_declaration = strct; } - var.type_declaration = type; + + TypeDeclaration *type = iface.struct_declaration; + if(type && iface.array) + type = get_or_create_array_type(*type); + r_any_resolved = (type!=iface.type_declaration); + iface.type_declaration = type; } void TypeResolver::visit(FunctionDeclaration &func) { - func.return_type_declaration = resolve_type(func.return_type); + resolve_type(func.return_type_declaration, func.return_type, false); TraversingVisitor::visit(func); } @@ -220,8 +210,7 @@ VariableResolver::VariableResolver(): stage(0), r_any_resolved(false), record_target(false), - r_self_referencing(false), - r_assignment_target(0) + r_self_referencing(false) { } bool VariableResolver::apply(Stage &s) @@ -230,6 +219,9 @@ bool VariableResolver::apply(Stage &s) s.interface_blocks.clear(); r_any_resolved = false; s.content.visit(*this); + for(vector::const_iterator i=redeclared_builtins.begin(); i!=redeclared_builtins.end(); ++i) + (*i)->source = GENERATED_SOURCE; + NodeRemover().apply(s, nodes_to_remove); return r_any_resolved; } @@ -238,15 +230,40 @@ void VariableResolver::enter(Block &block) block.variables.clear(); } -void VariableResolver::visit_and_replace(RefPtr &expr) +void VariableResolver::visit(RefPtr &expr) { r_replacement_expr = 0; expr->visit(*this); if(r_replacement_expr) + { expr = r_replacement_expr; + /* Don't record assignment target when doing a replacement, because chain + information won't be correct. */ + r_assignment_target.declaration = 0; + r_any_resolved = true; + } r_replacement_expr = 0; } +void VariableResolver::check_assignment_target(Statement *declaration) +{ + if(record_target) + { + if(r_assignment_target.declaration) + { + /* More than one reference found in assignment target. Unable to + determine what the primary target is. */ + record_target = false; + r_assignment_target.declaration = 0; + } + else + r_assignment_target.declaration = declaration; + } + // TODO This check is overly broad and may prevent some optimizations. + else if(declaration && declaration==r_assignment_target.declaration) + r_self_referencing = true; +} + void VariableResolver::visit(VariableReference &var) { VariableDeclaration *declaration = 0; @@ -280,10 +297,11 @@ void VariableResolver::visit(VariableReference &var) { // Look for the variable in anonymous interface blocks. for(i=blocks.begin(); (!declaration && i!=blocks.end()); ++i) - if(i->second->instance_name.empty()) + if(i->second->instance_name.empty() && i->second->struct_declaration) { - map::iterator j = i->second->members.variables.find(var.name); - if(j!=i->second->members.variables.end()) + const map &iface_vars = i->second->struct_declaration->members.variables; + map::const_iterator j = iface_vars.find(var.name); + if(j!=iface_vars.end()) declaration = j->second; } } @@ -292,20 +310,7 @@ void VariableResolver::visit(VariableReference &var) r_any_resolved |= (declaration!=var.declaration); var.declaration = declaration; - if(record_target) - { - if(r_assignment_target) - { - /* More than one variable reference found in assignment target. - Unable to determine what the primary target is. */ - record_target = false; - r_assignment_target = 0; - } - else - r_assignment_target = var.declaration; - } - else if(var.declaration && var.declaration==r_assignment_target) - r_self_referencing = true; + check_assignment_target(var.declaration); } void VariableResolver::visit(InterfaceBlockReference &iface) @@ -314,36 +319,82 @@ void VariableResolver::visit(InterfaceBlockReference &iface) InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0); r_any_resolved |= (declaration!=iface.declaration); iface.declaration = declaration; + + check_assignment_target(iface.declaration); +} + +void VariableResolver::add_to_chain(Assignment::Target::ChainType type, unsigned index) +{ + if(r_assignment_target.chain_len<7) + r_assignment_target.chain[r_assignment_target.chain_len] = type | min(index, 0x3F); + ++r_assignment_target.chain_len; } void VariableResolver::visit(MemberAccess &memacc) { - visit_and_replace(memacc.left); + TraversingVisitor::visit(memacc); - map *members = 0; + VariableDeclaration *declaration = 0; if(StructDeclaration *strct = dynamic_cast(memacc.left->type)) - members = &strct->members.variables; - else if(InterfaceBlockReference *iface_ref = dynamic_cast(memacc.left.get())) { - if(iface_ref->declaration) - members = &iface_ref->declaration->members.variables; - } + map::iterator i = strct->members.variables.find(memacc.member); + if(i!=strct->members.variables.end()) + { + declaration = i->second; - VariableDeclaration *declaration = 0; - if(members) + if(record_target) + { + unsigned index = 0; + for(NodeList::const_iterator j=strct->members.body.begin(); (j!=strct->members.body.end() && j->get()!=i->second); ++j) + ++index; + + add_to_chain(Assignment::Target::MEMBER, index); + } + } + } + else if(BasicTypeDeclaration *basic = dynamic_cast(memacc.left->type)) { - map::iterator i = members->find(memacc.member); - if(i!=members->end()) - declaration = i->second; + bool scalar_swizzle = ((basic->kind==BasicTypeDeclaration::INT || basic->kind==BasicTypeDeclaration::FLOAT) && memacc.member.size()==1); + bool vector_swizzle = (basic->kind==BasicTypeDeclaration::VECTOR && memacc.member.size()<=4); + if(scalar_swizzle || vector_swizzle) + { + static const char component_names[] = { 'x', 'r', 's', 'y', 'g', 't', 'z', 'b', 'p', 'w', 'a', 'q' }; + + bool ok = true; + UInt8 components[4] = { }; + for(unsigned i=0; (ok && isource = memacc.source; + swizzle->line = memacc.line; + swizzle->oper = memacc.oper; + swizzle->left = memacc.left; + swizzle->component_group = memacc.member; + swizzle->count = memacc.member.size(); + copy(components, components+memacc.member.size(), swizzle->components); + r_replacement_expr = swizzle; + } + } } r_any_resolved |= (declaration!=memacc.declaration); memacc.declaration = declaration; } -void VariableResolver::visit(UnaryExpression &unary) +void VariableResolver::visit(Swizzle &swizzle) { - visit_and_replace(unary.expression); + TraversingVisitor::visit(swizzle); + + if(record_target) + { + unsigned mask = 0; + for(unsigned i=0; i(binary.right.get())) + if(literal_subscript->value.check_type()) + index = literal_subscript->value.value(); + add_to_chain(Assignment::Target::ARRAY, index); } - visit_and_replace(binary.left); } else - { - visit_and_replace(binary.left); - visit_and_replace(binary.right); - } + TraversingVisitor::visit(binary); } void VariableResolver::visit(Assignment &assign) { { SetFlag set(record_target); - r_assignment_target = 0; - visit_and_replace(assign.left); - r_any_resolved |= (r_assignment_target!=assign.target_declaration); - assign.target_declaration = r_assignment_target; + r_assignment_target = Assignment::Target(); + visit(assign.left); + r_any_resolved |= (r_assignment_targettoken[0]!='='); } -void VariableResolver::visit(FunctionCall &call) +void VariableResolver::merge_layouts(Layout &to_layout, const Layout &from_layout) { - for(NodeArray::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - visit_and_replace(*i); + for(vector::const_iterator i=from_layout.qualifiers.begin(); i!=from_layout.qualifiers.end(); ++i) + { + bool found = false; + for(vector::iterator j=to_layout.qualifiers.begin(); (!found && j!=to_layout.qualifiers.end()); ++j) + if(j->name==i->name) + { + j->has_value = i->value; + j->value = i->value; + found = true; + } + + if(!found) + to_layout.qualifiers.push_back(*i); + } } void VariableResolver::visit(VariableDeclaration &var) { - if(!block_interface.empty() && var.interface.empty()) - var.interface = block_interface; - TraversingVisitor::visit(var); - current_block->variables.insert(make_pair(var.name, &var)); + VariableDeclaration *&ptr = current_block->variables[var.name]; + if(!ptr) + ptr = &var; + else if(!current_block->parent && ptr->interface==var.interface && ptr->type==var.type) + { + if(ptr->source==BUILTIN_SOURCE) + redeclared_builtins.push_back(&var); + else + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, var.source, var.line, + format("Redeclaring non-builtin variable '%s' is deprecated", var.name))); + + if(var.init_expression) + ptr->init_expression = var.init_expression; + if(var.layout) + { + if(ptr->layout) + merge_layouts(*ptr->layout, *var.layout); + else + ptr->layout = var.layout; + } + nodes_to_remove.insert(&var); + + r_any_resolved = true; + } } void VariableResolver::visit(InterfaceBlock &iface) @@ -403,7 +492,6 @@ void VariableResolver::visit(InterfaceBlock &iface) if(!iface.instance_name.empty()) stage->interface_blocks.insert(make_pair("_"+iface.instance_name, &iface)); - SetForScope set_iface(block_interface, iface.interface); TraversingVisitor::visit(iface); } @@ -499,11 +587,11 @@ void ExpressionResolver::convert_to(RefPtr &expr, BasicTypeDeclarati bool ExpressionResolver::convert_to_element(RefPtr &expr, BasicTypeDeclaration &elem_type) { - if(BasicTypeDeclaration *expr_type = dynamic_cast(expr->type)) + if(BasicTypeDeclaration *expr_basic = dynamic_cast(expr->type)) { BasicTypeDeclaration *to_type = &elem_type; - if(is_vector_or_matrix(*expr_type)) - to_type = find_type(elem_type, expr_type->kind, expr_type->size); + if(is_vector_or_matrix(*expr_basic)) + to_type = find_type(elem_type, expr_basic->kind, expr_basic->size); if(to_type) { convert_to(expr, *to_type); @@ -545,7 +633,8 @@ void ExpressionResolver::visit(VariableReference &var) void ExpressionResolver::visit(InterfaceBlockReference &iface) { - resolve(iface, 0, true); + if(iface.declaration) + resolve(iface, iface.declaration->type_declaration, true); } void ExpressionResolver::visit(MemberAccess &memacc) @@ -556,6 +645,20 @@ void ExpressionResolver::visit(MemberAccess &memacc) resolve(memacc, memacc.declaration->type_declaration, memacc.left->lvalue); } +void ExpressionResolver::visit(Swizzle &swizzle) +{ + TraversingVisitor::visit(swizzle); + + if(BasicTypeDeclaration *left_basic = dynamic_cast(swizzle.left->type)) + { + BasicTypeDeclaration *left_elem = get_element_type(*left_basic); + if(swizzle.count==1) + resolve(swizzle, left_elem, swizzle.left->lvalue); + else if(left_basic->kind==BasicTypeDeclaration::VECTOR && left_elem) + resolve(swizzle, find_type(*left_elem, left_basic->kind, swizzle.count), swizzle.left->lvalue); + } +} + void ExpressionResolver::visit(UnaryExpression &unary) { TraversingVisitor::visit(unary); @@ -657,11 +760,17 @@ void ExpressionResolver::visit(BinaryExpression &binary, bool assign) } else if((oper=='<' || oper=='>') && oper2==oper) { - // Shifts only apply to integers. - if(basic_left->kind!=BasicTypeDeclaration::INT || basic_right->kind!=BasicTypeDeclaration::INT) + // Shifts apply to integer scalars and vectors, with some restrictions. + if(elem_left->kind!=BasicTypeDeclaration::INT || elem_right->kind!=BasicTypeDeclaration::INT) + return; + unsigned left_size = (basic_left->kind==BasicTypeDeclaration::INT ? 1 : basic_left->kind==BasicTypeDeclaration::VECTOR ? basic_left->size : 0); + unsigned right_size = (basic_right->kind==BasicTypeDeclaration::INT ? 1 : basic_right->kind==BasicTypeDeclaration::VECTOR ? basic_right->size : 0); + if(!left_size || (left_size==1 && right_size!=1) || (left_size>1 && right_size!=1 && right_size!=left_size)) return; type = basic_left; + // Don't perform conversion even if the operands are of different sizes. + compat = SAME_TYPE; } else if(oper=='+' || oper=='-' || oper=='*' || oper=='/') { @@ -756,6 +865,36 @@ void ExpressionResolver::visit(Assignment &assign) resolve(assign, assign.left->type, true); } +void ExpressionResolver::visit(TernaryExpression &ternary) +{ + TraversingVisitor::visit(ternary); + + BasicTypeDeclaration *basic_cond = dynamic_cast(ternary.condition->type); + if(!basic_cond || basic_cond->kind!=BasicTypeDeclaration::BOOL) + return; + + TypeDeclaration *type = 0; + if(ternary.true_expr->type==ternary.false_expr->type) + type = ternary.true_expr->type; + else + { + BasicTypeDeclaration *basic_true = dynamic_cast(ternary.true_expr->type); + BasicTypeDeclaration *basic_false = dynamic_cast(ternary.false_expr->type); + Compatibility compat = get_compatibility(*basic_true, *basic_false); + if(compat==NOT_COMPATIBLE) + return; + + type = (compat==LEFT_CONVERTIBLE ? basic_true : basic_false); + + if(compat==LEFT_CONVERTIBLE) + convert_to(ternary.true_expr, *basic_false); + else if(compat==RIGHT_CONVERTIBLE) + convert_to(ternary.false_expr, *basic_true); + } + + resolve(ternary, type, false); +} + void ExpressionResolver::visit(FunctionCall &call) { TraversingVisitor::visit(call); @@ -793,44 +932,87 @@ void ExpressionResolver::visit(VariableDeclaration &var) } -void FunctionResolver::apply(Stage &s) +bool FunctionResolver::apply(Stage &s) { stage = &s; s.functions.clear(); + r_any_resolved = false; s.content.visit(*this); + return r_any_resolved; } void FunctionResolver::visit(FunctionCall &call) { - map::iterator i = stage->functions.find(call.name); - if(i!=stage->functions.end()) - call.declaration = i->second; + string arg_types; + bool has_signature = true; + for(NodeArray::const_iterator i=call.arguments.begin(); (has_signature && i!=call.arguments.end()); ++i) + { + if((*i)->type) + append(arg_types, ",", (*i)->type->name); + else + has_signature = false; + } + + FunctionDeclaration *declaration = 0; + if(has_signature) + { + map::iterator i = stage->functions.find(format("%s(%s)", call.name, arg_types)); + declaration = (i!=stage->functions.end() ? i->second : 0); + } + r_any_resolved |= (declaration!=call.declaration); + call.declaration = declaration; TraversingVisitor::visit(call); } void FunctionResolver::visit(FunctionDeclaration &func) { - FunctionDeclaration *&stage_decl = stage->functions[func.name]; - vector &decls = declarations[func.name]; + if(func.signature.empty()) + { + string param_types; + for(NodeArray::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) + { + if((*i)->type_declaration) + append(param_types, ",", (*i)->type_declaration->name); + else + return; + } + func.signature = format("(%s)", param_types); + r_any_resolved = true; + } + + string key = func.name+func.signature; + FunctionDeclaration *&stage_decl = stage->functions[key]; + vector &decls = declarations[key]; if(func.definition==&func) { + if(stage_decl && stage_decl->definition) + { + if(!func.overrd) + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, func.source, func.line, + format("Overriding function '%s' without the override keyword is deprecated", key))); + if(!stage_decl->definition->virtua) + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, func.source, func.line, + format("Overriding function '%s' not declared as virtual is deprecated", key))); + } stage_decl = &func; // Set all previous declarations to use this definition. for(vector::iterator i=decls.begin(); i!=decls.end(); ++i) { + r_any_resolved |= (func.definition!=(*i)->definition); (*i)->definition = func.definition; (*i)->body.body.clear(); } } else { - func.definition = 0; + FunctionDeclaration *definition = (stage_decl ? stage_decl->definition : 0); + r_any_resolved |= (definition!=func.definition); + func.definition = definition; + if(!stage_decl) stage_decl = &func; - else - func.definition = stage_decl->definition; } decls.push_back(&func); @@ -841,7 +1023,6 @@ void FunctionResolver::visit(FunctionDeclaration &func) InterfaceGenerator::InterfaceGenerator(): stage(0), function_scope(false), - iface_block(0), copy_block(false), iface_target_block(0) { } @@ -891,6 +1072,9 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration if(stage->content.variables.count(name)) return 0; + if(stage->type==Stage::GEOMETRY && !copy_block && var.interface=="out" && var.array) + return 0; + VariableDeclaration* iface_var = new VariableDeclaration; iface_var->sampling = var.sampling; iface_var->interface = iface; @@ -913,6 +1097,8 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration iface_target_block->body.insert(iface_insert_point, iface_var); iface_target_block->variables.insert(make_pair(name, iface_var)); + if(iface_target_block==&stage->content && iface=="in") + declared_inputs.push_back(iface_var); return iface_var; } @@ -925,6 +1111,7 @@ InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block InterfaceBlock *in_block = new InterfaceBlock; in_block->interface = "in"; in_block->name = out_block.name; + in_block->members = new Block; in_block->instance_name = out_block.instance_name; if(stage->type==Stage::GEOMETRY) in_block->array = true; @@ -935,9 +1122,12 @@ InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block { SetFlag set_copy(copy_block, true); - SetForScope set_target(iface_target_block, &in_block->members); - SetForScope::iterator> set_ins_pt(iface_insert_point, in_block->members.body.end()); - out_block.members.visit(*this); + SetForScope set_target(iface_target_block, in_block->members.get()); + SetForScope::iterator> set_ins_pt(iface_insert_point, in_block->members->body.end()); + if(out_block.struct_declaration) + out_block.struct_declaration->members.visit(*this); + else if(out_block.members) + out_block.members->visit(*this); } iface_target_block->body.insert(iface_insert_point, in_block); @@ -984,8 +1174,14 @@ void InterfaceGenerator::visit(VariableReference &var) i = prev_vars.find(in_prefix+var.name); if(i!=prev_vars.end() && i->second->interface=="out") { - generate_interface(*i->second, "in", i->second->name); - var.name = i->second->name; + if(stage->type==Stage::GEOMETRY && i->second->array) + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, var.source, var.line, + format("Can't access '%s' through automatic interface because it's an array", var.name))); + else + { + generate_interface(*i->second, "in", i->second->name); + var.name = i->second->name; + } return; } @@ -1000,10 +1196,11 @@ void InterfaceGenerator::visit(VariableReference &var) } for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j) - if(j->second->instance_name.empty()) + if(j->second->instance_name.empty() && j->second->struct_declaration) { - i = j->second->members.variables.find(var.name); - if(i!=j->second->members.variables.end()) + const map &iface_vars = j->second->struct_declaration->members.variables; + i = iface_vars.find(var.name); + if(i!=iface_vars.end()) { generate_interface(*j->second); return; @@ -1014,28 +1211,8 @@ void InterfaceGenerator::visit(VariableReference &var) void InterfaceGenerator::visit(VariableDeclaration &var) { if(copy_block) - { generate_interface(var, "in", var.name); - return; - } - - if(iface_block) - { - if(iface_block->linked_block) - { - // Link all variables to their counterparts in the linked block. - const map &linked_vars = iface_block->linked_block->members.variables; - map::const_iterator i = linked_vars.find(var.name); - if(i!=linked_vars.end()) - { - var.linked_declaration = i->second; - var.linked_declaration->linked_declaration = &var; - } - } - return; - } - - if(var.interface=="out") + else if(var.interface=="out") { /* For output variables in function scope, generate a global interface and replace the local declaration with an assignment. */ @@ -1054,11 +1231,14 @@ void InterfaceGenerator::visit(VariableDeclaration &var) } } } - else if(var.interface=="in") + else if(var.interface=="in" && current_block==&stage->content) { + if(var.name.compare(0, 3, "gl_")) + declared_inputs.push_back(&var); + /* Try to link input variables in global scope with output variables from previous stage. */ - if(current_block==&stage->content && !var.linked_declaration && stage->previous) + if(!var.linked_declaration && stage->previous) { const map &prev_vars = stage->previous->content.variables; map::const_iterator i = prev_vars.find(var.name); @@ -1091,7 +1271,6 @@ void InterfaceGenerator::visit(InterfaceBlock &iface) } } - SetForScope set_iface(iface_block, &iface); TraversingVisitor::visit(iface); } @@ -1104,12 +1283,8 @@ void InterfaceGenerator::visit(FunctionDeclaration &func) void InterfaceGenerator::visit(Passthrough &pass) { - vector pass_vars; - - // Pass through all input variables of this stage. - for(map::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i) - if(i->second->interface=="in") - pass_vars.push_back(i->second); + // Pass through all input variables declared so far. + vector pass_vars = declared_inputs; if(stage->previous) {