}
}
- if(optimize)
- {
- for(list<ShaderVariable *>::const_iterator i=resolved_vars.begin(); i!=resolved_vars.end(); ++i)
- (*i)->check_inline(features.legacy);
- }
+ for(list<ShaderVariable *>::const_iterator i=resolved_vars.begin(); i!=resolved_vars.end(); ++i)
+ (*i)->check_inline(features.legacy, !optimize);
prog.attach_shader_owned(new VertexShader(create_source(resolved_vars, VERTEX)));
prog.attach_shader_owned(new FragmentShader(create_source(resolved_vars, FRAGMENT)));
resolve_space(to.resolved_space);
}
-void ProgramBuilder::ShaderVariable::check_inline(bool allow_legacy)
+void ProgramBuilder::ShaderVariable::check_inline(bool allow_legacy, bool trivial_only)
{
if(variable->expression)
{
if(!allow_legacy && !strncmp(variable->expression, "gl_", 3))
return;
+ // Never inline goal variables
unsigned total_refs = referenced_by.size();
+ if(!total_refs)
+ return;
+
+ // Inline an expression consisting of a single identifier
+ unsigned start, length;
+ if(parse_identifier(variable->expression, start, length))
+ if(start==0 && variable->expression[length]==0)
+ {
+ inlined = true;
+ return;
+ }
+
+ if(trivial_only)
+ return;
+
unsigned in_scope_refs = 0;
for(list<ShaderVariable *>::const_iterator i=referenced_by.begin(); i!=referenced_by.end(); ++i)
if((*i)->variable->scope==variable->scope)
++in_scope_refs;
- if(total_refs==1 || (total_refs>0 && in_scope_refs==0))
+
+ /* Inline if there's only one ref, or if all refs are in other scopes.
+ In the latter case, the actual inlining will happen in the interface
+ variable assignment. */
+ if(total_refs==1 || in_scope_refs==0)
{
inlined = true;
unsigned level = 0;
void resolve_space(const std::string &);
void add_reference(ShaderVariable &);
void update_reference(ShaderVariable &, ShaderVariable &);
- void check_inline(bool);
+ void check_inline(bool, bool);
bool is_referenced_from(VariableScope) const;
std::string get_expression() const;
};