X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=3dc07d80fa4dd2566c069d0cae5bdb4451f7ac5d;hp=5bb84269f30abe4fcd38198cef0b6a2ae416b2f8;hb=6a832fe1771f8c7bca0faa0d383fbbab062a1c56;hpb=f14516331a9b98b1d9d6c9c4e44787167f87a813 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 5bb84269..3dc07d80 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -8,6 +8,8 @@ #include "resources.h" #include "shader.h" +#undef interface + using namespace std; namespace { @@ -35,8 +37,6 @@ namespace GL { using namespace ProgramSyntax; -// XXX For some reason global declarations are emitted for otherwise undeclared local variables - ProgramCompiler::ProgramCompiler(): resources(0), module(0) @@ -460,6 +460,8 @@ void ProgramCompiler::Formatter::visit(VariableDeclaration &var) } if(var.constant) formatted += "const "; + if(!var.interpolation.empty()) + formatted += format("%s ", var.interpolation); if(!var.sampling.empty()) formatted += format("%s ", var.sampling); if(!var.interface.empty() && var.interface!=block_interface) @@ -543,20 +545,50 @@ void ProgramCompiler::Formatter::visit(Conditional &cond) void ProgramCompiler::Formatter::visit(Iteration &iter) { - formatted += "for("; - iter.init_statement->visit(*this); - formatted += ' '; - iter.condition->visit(*this); - formatted += "; "; - iter.loop_expression->visit(*this); - formatted += ")\n"; - iter.body.visit(*this); + if(!iter.init_statement && iter.condition && !iter.loop_expression) + { + formatted += "while("; + iter.condition->visit(*this); + formatted += ')'; + } + else + { + formatted += "for("; + if(iter.init_statement) + iter.init_statement->visit(*this); + else + formatted += ';'; + if(iter.condition) + { + formatted += ' '; + iter.condition->visit(*this); + } + formatted += ';'; + if(iter.loop_expression) + { + formatted += ' '; + iter.loop_expression->visit(*this); + } + formatted += ')'; + } + + if(iter.body.body.empty()) + formatted += " { }"; + else + { + formatted += '\n'; + iter.body.visit(*this); + } } void ProgramCompiler::Formatter::visit(Return &ret) { - formatted += "return "; - ret.expression->visit(*this); + formatted += "return"; + if(ret.expression) + { + formatted += ' '; + ret.expression->visit(*this); + } formatted += ';'; } @@ -1169,6 +1201,12 @@ void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary) inline_result = 0; } +void ProgramCompiler::FunctionInliner::visit(MemberAccess &memacc) +{ + visit_and_inline(memacc.left); + inline_result = 0; +} + void ProgramCompiler::FunctionInliner::visit(FunctionCall &call) { for(vector >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) @@ -1187,6 +1225,13 @@ void ProgramCompiler::FunctionInliner::visit(FunctionCall &call) inline_result = 0; } +void ProgramCompiler::FunctionInliner::visit(VariableDeclaration &var) +{ + if(var.init_expression) + visit_and_inline(var.init_expression); + inline_result = 0; +} + void ProgramCompiler::FunctionInliner::visit(Return &ret) { TraversingVisitor::visit(ret); @@ -1287,7 +1332,8 @@ void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary) ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator(): - scope_level(0) + scope_level(0), + record_only(false) { } void ProgramCompiler::ConstantConditionEliminator::visit(Block &block) @@ -1299,6 +1345,13 @@ void ProgramCompiler::ConstantConditionEliminator::visit(Block &block) variable_values.erase(i->second); } +void ProgramCompiler::ConstantConditionEliminator::visit(UnaryExpression &unary) +{ + if(VariableReference *var = dynamic_cast(unary.expression.get())) + if(unary.oper=="++" || unary.oper=="--") + variable_values.erase(var->declaration); +} + void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign) { variable_values.erase(assign.target_declaration); @@ -1312,28 +1365,49 @@ void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &va void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond) { - ExpressionEvaluator eval(variable_values); - cond.condition->visit(eval); - if(eval.result_valid) - flatten_block(eval.result ? cond.body : cond.else_body); - else - TraversingVisitor::visit(cond); + if(!record_only) + { + ExpressionEvaluator eval(variable_values); + cond.condition->visit(eval); + if(eval.result_valid) + { + flatten_block(eval.result ? cond.body : cond.else_body); + return; + } + } + + TraversingVisitor::visit(cond); } void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter) { - if(iter.condition) + if(!record_only) { - ExpressionEvaluator eval; - iter.condition->visit(eval); - if(eval.result_valid && !eval.result) + if(iter.condition) { - remove_node = true; - return; + /* If the loop condition is always false on the first iteration, the + entire loop can be removed */ + if(iter.init_statement) + iter.init_statement->visit(*this); + ExpressionEvaluator eval(variable_values); + iter.condition->visit(eval); + if(eval.result_valid && !eval.result) + { + remove_node = true; + return; + } } + + /* Record all assignments that occur inside the loop body so those + variables won't be considered as constant */ + SetFlag set_record(record_only); + TraversingVisitor::visit(iter); } TraversingVisitor::visit(iter); + + if(VariableDeclaration *init_decl = dynamic_cast(iter.init_statement.get())) + variable_values.erase(init_decl); } @@ -1341,6 +1415,7 @@ ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator(): aggregate(0), assignment(0), assignment_target(false), + assign_to_subscript(false), global_scope(true) { } @@ -1386,6 +1461,8 @@ void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary) { if(binary.oper=="[") { + if(assignment_target) + assign_to_subscript = true; binary.left->visit(*this); SetForScope set(assignment_target, false); binary.right->visit(*this); @@ -1397,6 +1474,7 @@ void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary) void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign) { { + assign_to_subscript = false; SetForScope set(assignment_target, !assign.self_referencing); assign.left->visit(*this); } @@ -1404,10 +1482,10 @@ void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign) assignment = &assign; } -void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref) +void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool chained) { VariableInfo &var_info = variables.back()[&var]; - if(!self_ref) + if(!chained) clear_assignments(var_info, true); var_info.assignments.push_back(&node); var_info.conditionally_assigned = false; @@ -1428,7 +1506,7 @@ void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr) assignment = 0; TraversingVisitor::visit(expr); if(assignment && assignment->target_declaration) - record_assignment(*assignment->target_declaration, expr, assignment->self_referencing); + record_assignment(*assignment->target_declaration, expr, (assignment->self_referencing || assign_to_subscript)); } void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct) @@ -1609,6 +1687,13 @@ void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var) var.init_expression = 0; } +void ProgramCompiler::NodeRemover::visit(Iteration &iter) +{ + if(to_remove.count(iter.init_statement.get())) + iter.init_statement = 0; + TraversingVisitor::visit(iter); +} + void ProgramCompiler::PrecisionRemover::visit(Precision &) { @@ -1763,6 +1848,22 @@ bool ProgramCompiler::LegacyConverter::supports_interface_layouts() const return check_version(Version(3, 30)); } +bool ProgramCompiler::LegacyConverter::supports_centroid_sampling() const +{ + if(target_api==OPENGL_ES2) + return check_version(Version(3, 0)); + else + return check_version(Version(1, 20)); +} + +bool ProgramCompiler::LegacyConverter::supports_sample_sampling() const +{ + if(target_api==OPENGL_ES2) + return check_version(Version(3, 20)); + else + return check_version(Version(4, 0)); +} + void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var) { if(var.layout && !supports_interface_layouts()) @@ -1790,6 +1891,17 @@ void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var) } } + if(var.sampling=="centroid") + { + if(!supports_centroid_sampling()) + var.sampling = string(); + } + else if(var.sampling=="sample") + { + if(!supports_sample_sampling()) + var.sampling = string(); + } + if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax()) { if(stage->type==FRAGMENT && var.interface=="out")