X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Foptimize.cpp;h=8008465e91344642f76e4fb66ae4a135e8bce66f;hb=241cf36a6d7735706804bb3c517529bbe078f1ee;hp=350e2eb746537be79ea9d9c1854f45a6b860b53a;hpb=24e4eea282917c3f6e4e16a2825372da64133e35;p=libs%2Fgl.git diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index 350e2eb7..8008465e 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -532,11 +532,19 @@ bool AggregateDismantler::apply(Stage &stage) for(const AggregateMember &m: kvp.second.members) { + string name; + if(m.declaration) + name = format("%s_%s", kvp.second.declaration->name, m.declaration->name); + else + name = format("%s_%d", kvp.second.declaration->name, m.index); + VariableDeclaration *var = new VariableDeclaration; var->source = kvp.first->source; var->line = kvp.first->line; - var->name = get_unused_variable_name(*kvp.second.decl_scope, format("%s_%s", kvp.second.declaration->name, m.declaration->name)); - var->type = m.declaration->type; + var->name = get_unused_variable_name(*kvp.second.decl_scope, name); + /* XXX This is kind of brittle and depends on the array declaration's + textual type not having brackets in it. */ + var->type = (m.declaration ? m.declaration : kvp.second.declaration)->type; if(m.initializer) var->init_expression = m.initializer->clone(); @@ -570,10 +578,17 @@ void AggregateDismantler::visit(RefPtr &expr) { r_aggregate_ref = 0; expr->visit(*this); - if(r_aggregate_ref && r_reference.chain_len==1 && (r_reference.chain[0]&0x3F)!=0x3F) + if(r_aggregate_ref && r_reference.chain_len==1) { - r_aggregate_ref->members[r_reference.chain[0]&0x3F].references.push_back(&expr); - r_aggregate_ref->members_referenced = true; + if((r_reference.chain[0]&0x3F)!=0x3F) + { + r_aggregate_ref->members[r_reference.chain[0]&0x3F].references.push_back(&expr); + r_aggregate_ref->members_referenced = true; + } + else + /* If the accessed member is not known, mark the entire aggregate as + referenced. */ + r_aggregate_ref->referenced = true; } r_aggregate_ref = 0; } @@ -584,6 +599,8 @@ void AggregateDismantler::visit(VariableReference &var) r_reference.declaration = var.declaration; else { + /* If an aggregate variable is referenced as a whole, it should not be + dismantled. */ auto i = aggregates.find(var.declaration); if(i!=aggregates.end()) i->second.referenced = true; @@ -624,7 +641,19 @@ void AggregateDismantler::visit(BinaryExpression &binary) visit(binary.right); } - add_to_chain(r_reference, Assignment::Target::ARRAY, 0x3F); + unsigned index = 0x3F; + if(Literal *literal_subscript = dynamic_cast(binary.right.get())) + if(literal_subscript->value.check_type()) + index = literal_subscript->value.value(); + add_to_chain(r_reference, Assignment::Target::ARRAY, index); + + if(r_reference.declaration && r_reference.chain_len==1) + { + auto i = aggregates.find(r_reference.declaration); + r_aggregate_ref = (i!=aggregates.end() ? &i->second : 0); + } + else + r_aggregate_ref = 0; } else { @@ -638,6 +667,7 @@ void AggregateDismantler::visit(VariableDeclaration &var) TraversingVisitor::visit(var); if(var.interface.empty()) + { if(const StructDeclaration *strct = dynamic_cast(var.type_declaration)) { const FunctionCall *init_call = dynamic_cast(var.init_expression.get()); @@ -656,6 +686,7 @@ void AggregateDismantler::visit(VariableDeclaration &var) { AggregateMember member; member.declaration = mem_decl; + member.index = i; if(init_call) member.initializer = init_call->arguments[i]; aggre.members.push_back(member); @@ -664,6 +695,31 @@ void AggregateDismantler::visit(VariableDeclaration &var) } } } + else if(const Literal *literal_size = dynamic_cast(var.array_size.get())) + { + if(literal_size->value.check_type()) + { + Aggregate &aggre = aggregates[&var]; + aggre.declaration = &var; + aggre.decl_scope = current_block; + aggre.insert_point = insert_point; + + int size = literal_size->value.value(); + for(int i=0; inode); } - - if(!kvp.second.output && !kvp.second.referenced) - { - // Don't remove variables from inside interface blocks. - if(!kvp.second.interface_block) - unused_nodes.insert(kvp.first); - } - else if(kvp.second.interface_block) - // Interface blocks are kept if even one member is used. - unused_nodes.erase(kvp.second.interface_block); } NodeRemover().apply(s, unused_nodes); @@ -1242,10 +1290,10 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n { Assignment::Target::ChainType type1 = static_cast(a->target.chain[j]&0xC0); Assignment::Target::ChainType type2 = static_cast(target.chain[j]&0xC0); + unsigned index1 = a->target.chain[j]&0x3F; + unsigned index2 = target.chain[j]&0x3F; if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE) { - unsigned index1 = a->target.chain[j]&0x3F; - unsigned index2 = target.chain[j]&0x3F; if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE) covered = index1&index2; else if(type1==Assignment::Target::ARRAY && index1<4) @@ -1256,7 +1304,7 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n covered as true */ } else - covered = (a->target.chain[j]==target.chain[j]); + covered = (type1==type2 && (index1==index2 || index1==0x3F || index2==0x3F)); } if(covered) @@ -1276,7 +1324,7 @@ void UnusedVariableRemover::visit(VariableReference &var) { if(composite_reference) r_reference.declaration = var.declaration; - else + else if(var.declaration) referenced(var.declaration, var); } @@ -1284,7 +1332,7 @@ void UnusedVariableRemover::visit(InterfaceBlockReference &iface) { if(composite_reference) r_reference.declaration = iface.declaration; - else + else if(iface.declaration) referenced(iface.declaration, iface); } @@ -1336,6 +1384,7 @@ void UnusedVariableRemover::visit(BinaryExpression &binary) { SetFlag clear_assignment(assignment_target, false); SetFlag clear_composite(composite_reference, false); + SetForScope clear_reference(r_reference, Assignment::Target()); binary.right->visit(*this); } @@ -1437,14 +1486,14 @@ void UnusedVariableRemover::visit(VariableDeclaration &var) return; VariableInfo &var_info = variables[&var]; - var_info.interface_block = interface_block; /* Mark variables as output if they're used by the next stage or the graphics API. */ - if(interface_block) - var_info.output = (interface_block->interface=="out" && (interface_block->linked_block || !interface_block->block_name.compare(0, 3, "gl_"))); - else - var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || !var.name.compare(0, 3, "gl_"))); + var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || !var.name.compare(0, 3, "gl_"))); + + // Linked outputs are automatically referenced. + if(var_info.output && var.linked_declaration) + var_info.referenced = true; if(var.init_expression) { @@ -1525,8 +1574,14 @@ void UnusedVariableRemover::visit(Iteration &iter) vector saved_refs; swap(loop_ext_refs, saved_refs); { + if(iter.init_statement) + iter.init_statement->visit(*this); SetForScope set_loop(in_loop, in_loop+1); - TraversingVisitor::visit(iter); + if(iter.condition) + iter.condition->visit(*this); + iter.body.visit(*this); + if(iter.loop_expression) + iter.loop_expression->visit(*this); } swap(loop_ext_refs, saved_refs);