]> git.tdb.fi Git - libs/gl.git/blobdiff - source/programcompiler.cpp
Set both min and mag filters when exporting textures
[libs/gl.git] / source / programcompiler.cpp
index c2ebb4b96ad3e474b2f636578e404601282b82ad..3dc07d80fa4dd2566c069d0cae5bdb4451f7ac5d 100644 (file)
@@ -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)
@@ -545,14 +545,40 @@ 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)
@@ -1175,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<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
@@ -1193,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);
@@ -1204,14 +1243,12 @@ void ProgramCompiler::FunctionInliner::visit(Return &ret)
 
 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
        variable_values(0),
-       const_only(false),
        result(0.0f),
        result_valid(false)
 { }
 
-ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap *v, bool c):
-       variable_values(v),
-       const_only(c),
+ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
+       variable_values(&v),
        result(0.0f),
        result_valid(false)
 { }
@@ -1236,8 +1273,6 @@ void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
 {
        if(!var.declaration)
                return;
-       if(const_only && !var.declaration->constant)
-               return;
 
        if(variable_values)
        {
@@ -1298,7 +1333,7 @@ void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary)
 
 ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
        scope_level(0),
-       in_loop(false)
+       record_only(false)
 { }
 
 void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
@@ -1310,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<VariableReference *>(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);
@@ -1323,30 +1365,49 @@ void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &va
 
 void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
 {
-       ExpressionEvaluator eval(&variable_values, in_loop);
-       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)
 {
-       // XXX Should this not visit init_statement first?
-       if(iter.condition)
+       if(!record_only)
        {
-               ExpressionEvaluator eval(0, in_loop);
-               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);
        }
 
-       SetFlag set_loop(in_loop);
        TraversingVisitor::visit(iter);
+
+       if(VariableDeclaration *init_decl = dynamic_cast<VariableDeclaration *>(iter.init_statement.get()))
+               variable_values.erase(init_decl);
 }
 
 
@@ -1354,6 +1415,7 @@ ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
        aggregate(0),
        assignment(0),
        assignment_target(false),
+       assign_to_subscript(false),
        global_scope(true)
 { }
 
@@ -1399,6 +1461,8 @@ void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
 {
        if(binary.oper=="[")
        {
+               if(assignment_target)
+                       assign_to_subscript = true;
                binary.left->visit(*this);
                SetForScope<bool> set(assignment_target, false);
                binary.right->visit(*this);
@@ -1410,6 +1474,7 @@ void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
 void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
 {
        {
+               assign_to_subscript = false;
                SetForScope<bool> set(assignment_target, !assign.self_referencing);
                assign.left->visit(*this);
        }
@@ -1417,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;
@@ -1441,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)
@@ -1622,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 &)
 {