X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fgenerate.cpp;h=09a776afb7f60bb61d2bdc47d0a8f3fb9e470b3e;hb=30f676460bb6e87fd7ca2532e507b97965c4a407;hp=3e53c1526daa88c43766dbfc4a019d267c317157;hpb=f526938b407e061c7424adedc34af4d1ff687f90;p=libs%2Fgl.git diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 3e53c152..09a776af 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "builtin.h" #include "generate.h" @@ -257,8 +258,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) @@ -275,18 +275,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; @@ -333,20 +355,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) @@ -355,18 +364,38 @@ 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); VariableDeclaration *declaration = 0; if(StructDeclaration *strct = dynamic_cast(memacc.left->type)) { map::iterator i = strct->members.variables.find(memacc.member); if(i!=strct->members.variables.end()) + { declaration = i->second; + + 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)) { @@ -402,12 +431,15 @@ void VariableResolver::visit(MemberAccess &memacc) void VariableResolver::visit(Swizzle &swizzle) { - visit_and_replace(swizzle.left); -} + TraversingVisitor::visit(swizzle); -void VariableResolver::visit(UnaryExpression &unary) -{ - visit_and_replace(unary.expression); + 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) -{ - for(NodeArray::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - visit_and_replace(*i); -} - void VariableResolver::visit(VariableDeclaration &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); + TraversingVisitor::visit(var); current_block->variables.insert(make_pair(var.name, &var)); } @@ -564,11 +591,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); @@ -890,17 +917,47 @@ bool FunctionResolver::apply(Stage &s) 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) { stage_decl = &func; @@ -908,17 +965,19 @@ void FunctionResolver::visit(FunctionDeclaration &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);