X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fgenerate.cpp;h=53676c26784cf7d32709639fea843459e3cf4269;hb=041ba4b1acd55337239c5ce24cc310118c621206;hp=f29d65f58bfeeaf4fe837fa2222226473c6d3c66;hpb=f639d088c478fe5d266f9f5779928735b5176976;p=libs%2Fgl.git diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index f29d65f5..53676c26 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -116,31 +116,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::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; } -TypeDeclaration *TypeResolver::resolve_type(const string &name) +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,7 +182,7 @@ 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)) @@ -175,7 +202,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 +214,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); } @@ -243,7 +279,10 @@ void VariableResolver::visit_and_replace(RefPtr &expr) r_replacement_expr = 0; expr->visit(*this); if(r_replacement_expr) + { expr = r_replacement_expr; + r_any_resolved = true; + } r_replacement_expr = 0; } @@ -280,10 +319,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; } } @@ -320,20 +360,11 @@ void VariableResolver::visit(MemberAccess &memacc) { visit_and_replace(memacc.left); - map *members = 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; - } - VariableDeclaration *declaration = 0; - if(members) + if(StructDeclaration *strct = dynamic_cast(memacc.left->type)) { - map::iterator i = members->find(memacc.member); - if(i!=members->end()) + map::iterator i = strct->members.variables.find(memacc.member); + if(i!=strct->members.variables.end()) declaration = i->second; } @@ -388,10 +419,12 @@ void VariableResolver::visit(FunctionCall &call) void VariableResolver::visit(VariableDeclaration &var) { - if(!block_interface.empty() && var.interface.empty()) - var.interface = block_interface; - - TraversingVisitor::visit(var); + if(var.layout) + var.layout->visit(*this); + if(var.array_size) + visit_and_replace(var.array_size); + if(var.init_expression) + visit_and_replace(var.init_expression); current_block->variables.insert(make_pair(var.name, &var)); } @@ -403,7 +436,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); } @@ -545,7 +577,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) @@ -657,11 +690,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=='/') { @@ -793,11 +832,13 @@ 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) @@ -841,7 +882,6 @@ void FunctionResolver::visit(FunctionDeclaration &func) InterfaceGenerator::InterfaceGenerator(): stage(0), function_scope(false), - iface_block(0), copy_block(false), iface_target_block(0) { } @@ -925,6 +965,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 +976,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); @@ -1000,10 +1044,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 +1059,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. */ @@ -1091,7 +1116,6 @@ void InterfaceGenerator::visit(InterfaceBlock &iface) } } - SetForScope set_iface(iface_block, &iface); TraversingVisitor::visit(iface); }