X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Fgenerate.cpp;h=8547152e45df9edb714f06ae8c2c83cccae40350;hp=3e53c1526daa88c43766dbfc4a019d267c317157;hb=cc3f4aaaf8d2b34347f69b026c10f82797059aa4;hpb=50a79aee4c53c4198bae38c7ff447133a043aacc diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 3e53c152..8547152e 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -257,8 +257,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) @@ -282,11 +281,33 @@ void VariableResolver::visit_and_replace(RefPtr &expr) 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 +354,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,6 +363,15 @@ 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) @@ -366,7 +383,18 @@ void VariableResolver::visit(MemberAccess &memacc) { 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)) { @@ -403,6 +431,14 @@ void VariableResolver::visit(MemberAccess &memacc) void VariableResolver::visit(Swizzle &swizzle) { visit_and_replace(swizzle.left); + + 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); + } } else { @@ -433,10 +478,10 @@ void VariableResolver::visit(Assignment &assign) { { SetFlag set(record_target); - r_assignment_target = 0; + r_assignment_target = Assignment::Target(); visit_and_replace(assign.left); - r_any_resolved |= (r_assignment_target!=assign.target_declaration); - assign.target_declaration = r_assignment_target; + r_any_resolved |= (r_assignment_target