]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Don't return references from apply functions
[libs/gl.git] / source / glsl / optimize.cpp
index 6ac84b5b0247be7c48ffe3339ba288c1d047ab3c..32f7ce67959b388fa1bc2c2fb58ecc344a11bb87 100644 (file)
@@ -1,6 +1,7 @@
 #include <msp/core/raii.h>
 #include <msp/strings/format.h>
 #include "optimize.h"
+#include "reflect.h"
 
 using namespace std;
 
@@ -8,6 +9,55 @@ namespace Msp {
 namespace GL {
 namespace SL {
 
+ConstantSpecializer::ConstantSpecializer():
+       values(0)
+{ }
+
+void ConstantSpecializer::apply(Stage &stage, const map<string, int> &v)
+{
+       values = &v;
+       stage.content.visit(*this);
+}
+
+void ConstantSpecializer::visit(VariableDeclaration &var)
+{
+       bool specializable = false;
+       if(var.layout)
+       {
+               vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
+               for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); (!specializable && i!=qualifiers.end()); ++i)
+                       if(i->name=="constant_id")
+                       {
+                               specializable = true;
+                               qualifiers.erase(i);
+                       }
+
+               if(qualifiers.empty())
+                       var.layout = 0;
+       }
+
+       if(specializable)
+       {
+               map<string, int>::const_iterator i = values->find(var.name);
+               if(i!=values->end())
+               {
+                       RefPtr<Literal> literal = new Literal;
+                       if(var.type=="bool")
+                       {
+                               literal->token = (i->second ? "true" : "false");
+                               literal->value = static_cast<bool>(i->second);
+                       }
+                       else if(var.type=="int")
+                       {
+                               literal->token = lexical_cast<string>(i->second);
+                               literal->value = i->second;
+                       }
+                       var.init_expression = literal;
+               }
+       }
+}
+
+
 InlineableFunctionLocator::InlineableFunctionLocator():
        current_function(0),
        return_count(0)
@@ -70,17 +120,13 @@ void InlineableFunctionLocator::visit(Return &ret)
 
 InlineContentInjector::InlineContentInjector():
        source_func(0),
-       pass(DEPENDS)
+       pass(REFERENCED)
 { }
 
-const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList<Statement>::iterator &ins_pt, FunctionCall &call)
+string InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList<Statement>::iterator &ins_pt, FunctionCall &call)
 {
        source_func = call.declaration->definition;
 
-       // Collect all declarations the inlined function depends on.
-       pass = DEPENDS;
-       source_func->visit(*this);
-
        /* Populate referenced_names from the target function so we can rename
        variables from the inlined function that would conflict. */
        pass = REFERENCED;
@@ -138,7 +184,7 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta
 
        tgt_blk.body.splice(ins_pt, staging_block.body);
 
-       NodeReorderer().apply(stage, target_func, dependencies);
+       NodeReorderer().apply(stage, target_func, DependencyCollector().apply(*source_func));
 
        return r_result_name;
 }
@@ -151,31 +197,19 @@ void InlineContentInjector::visit(VariableReference &var)
                if(i!=staging_block.variables.end())
                        var.name = i->second->name;
        }
-       else if(pass==DEPENDS && var.declaration)
-       {
-               dependencies.insert(var.declaration);
-               var.declaration->visit(*this);
-       }
        else if(pass==REFERENCED)
                referenced_names.insert(var.name);
 }
 
 void InlineContentInjector::visit(InterfaceBlockReference &iface)
 {
-       if(pass==DEPENDS && iface.declaration)
-       {
-               dependencies.insert(iface.declaration);
-               iface.declaration->visit(*this);
-       }
-       else if(pass==REFERENCED)
+       if(pass==REFERENCED)
                referenced_names.insert(iface.name);
 }
 
 void InlineContentInjector::visit(FunctionCall &call)
 {
-       if(pass==DEPENDS && call.declaration)
-               dependencies.insert(call.declaration);
-       else if(pass==REFERENCED)
+       if(pass==REFERENCED)
                referenced_names.insert(call.name);
        TraversingVisitor::visit(call);
 }
@@ -186,8 +220,11 @@ void InlineContentInjector::visit(VariableDeclaration &var)
 
        if(pass==RENAME)
        {
+               /* Check against conflicts with the other context as well as variables
+               already renamed here. */
+               bool conflict = (staging_block.variables.count(var.name) || referenced_names.count(var.name));
                staging_block.variables[var.name] = &var;
-               if(referenced_names.count(var.name))
+               if(conflict)
                {
                        string mapped_name = get_unused_variable_name(staging_block, var.name);
                        if(mapped_name!=var.name)
@@ -197,11 +234,6 @@ void InlineContentInjector::visit(VariableDeclaration &var)
                        }
                }
        }
-       else if(pass==DEPENDS && var.type_declaration)
-       {
-               dependencies.insert(var.type_declaration);
-               var.type_declaration->visit(*this);
-       }
        else if(pass==REFERENCED)
                referenced_names.insert(var.type);
 }
@@ -265,12 +297,12 @@ void FunctionInliner::visit(Block &block)
 
 void FunctionInliner::visit(FunctionCall &call)
 {
+       for(NodeArray<Expression>::iterator i=call.arguments.begin(); (!r_inlined_here && i!=call.arguments.end()); ++i)
+               visit(*i);
+
        if(r_inlined_here)
                return;
 
-       for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
-               visit(*i);
-
        FunctionDeclaration *def = call.declaration;
        if(def)
                def = def->definition;
@@ -316,15 +348,6 @@ void FunctionInliner::visit(Iteration &iter)
 }
 
 
-ExpressionInliner::ExpressionInfo::ExpressionInfo():
-       expression(0),
-       assign_scope(0),
-       inline_point(0),
-       trivial(false),
-       available(true)
-{ }
-
-
 ExpressionInliner::ExpressionInliner():
        r_ref_info(0),
        r_any_inlined(false),
@@ -974,10 +997,6 @@ bool UnusedVariableRemover::apply(Stage &s)
                if(i->used_by.empty())
                        unused_nodes.insert(i->node);
 
-       for(map<string, InterfaceBlock *>::const_iterator i=s.interface_blocks.begin(); i!=s.interface_blocks.end(); ++i)
-               if(i->second->instance_name.empty())
-                       unused_nodes.insert(i->second);
-
        for(BlockVariableMap::const_iterator i=variables.begin(); i!=variables.end(); ++i)
        {
                if(i->second.output)
@@ -1130,16 +1149,8 @@ void UnusedVariableRemover::visit(VariableDeclaration &var)
 
 void UnusedVariableRemover::visit(InterfaceBlock &iface)
 {
-       if(iface.instance_name.empty())
-       {
-               SetForScope<InterfaceBlock *> set_block(interface_block, &iface);
-               iface.struct_declaration->members.visit(*this);
-       }
-       else
-       {
-               VariableInfo &var_info = variables[&iface];
-               var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_")));
-       }
+       VariableInfo &var_info = variables[&iface];
+       var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_")));
 }
 
 void UnusedVariableRemover::merge_variables(const BlockVariableMap &other_vars)