X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogrambuilder.cpp;h=28acc5d941f2f24405bc1d5302e795ecb348c8b1;hb=cb2281586d0202dfe2c8c181afc9cbf1d250cf25;hp=0f29675f19dd3e45e4a63633747c6d31093f5680;hpb=739769e449eac552813b01f8dbec89a579443715;p=libs%2Fgl.git diff --git a/source/programbuilder.cpp b/source/programbuilder.cpp index 0f29675f..28acc5d9 100644 --- a/source/programbuilder.cpp +++ b/source/programbuilder.cpp @@ -116,7 +116,7 @@ const ProgramBuilder::VariableDefinition ProgramBuilder::standard_variables[] = { UNIFORM, "eye_obj_normal_matrix", "mat3", "gl_NormalMatrix", 0 }, { UNIFORM, "projection_matrix", "mat4", "gl_ProjectionMatrix", 0 }, { UNIFORM, "shd_eye_matrix", "mat4", 0, 0 }, - { UNIFORM, "light_sources", "struct { vec4 position; vec4 diffuse; vec4 specular; } %s[2]", "gl_LightSource", 0 }, + { UNIFORM, "light_sources", "struct { vec4 position; vec4 diffuse; vec4 specular; }[2]", "gl_LightSource", 0 }, { UNIFORM, "ambient_color", "vec4", 0, 0 }, { UNIFORM, "material", "struct { vec4 ambient; vec4 diffuse; vec4 specular; float shininess; }", "gl_FrontMaterial", 0 }, @@ -292,11 +292,8 @@ void ProgramBuilder::add_shaders(Program &prog) const } } - if(optimize) - { - for(list::const_iterator i=resolved_vars.begin(); i!=resolved_vars.end(); ++i) - (*i)->check_inline(features.legacy); - } + for(list::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))); @@ -328,19 +325,14 @@ string ProgramBuilder::create_source(const list &variables, Va for(list::const_iterator i=variables.begin(); i!=variables.end(); ++i) if((*i)->variable->scope==UNIFORM && (*i)->is_referenced_from(scope) && !(*i)->inlined) - { - if(strchr((*i)->variable->type, '%')) - source += format("uniform %s;\n", format((*i)->variable->type, (*i)->resolved_name)); - else - source += format("uniform %s %s;\n", (*i)->variable->type, (*i)->resolved_name); - } + source += format("uniform %s;\n", (*i)->create_declaration()); if(scope==VERTEX) { const char *qualifier = (features.legacy ? "attribute" : "in"); for(list::const_iterator i=variables.begin(); i!=variables.end(); ++i) if((*i)->variable->scope==ATTRIBUTE && !(*i)->inlined) - source += format("%s %s %s;\n", qualifier, (*i)->variable->type, (*i)->resolved_name); + source += format("%s %s;\n", qualifier, (*i)->create_declaration()); } /* Any variables defined in vertex scope but referenced from fragment scope @@ -355,12 +347,12 @@ string ProgramBuilder::create_source(const list &variables, Va qualifier = (scope==VERTEX ? "out" : "in"); else qualifier = "varying"; - source += format("%s %s v_%s;\n", qualifier, (*i)->variable->type, (*i)->resolved_name); + source += format("%s %s;\n", qualifier, (*i)->create_declaration('v')); } for(list::const_iterator i=variables.begin(); i!=variables.end(); ++i) if((*i)->referenced_by.empty() && (*i)->resolved_name.compare(0, 3, "gl_")) - source += format("out %s %s;\n", (*i)->variable->type, (*i)->resolved_name); + source += format("out %s;\n", (*i)->create_declaration()); source += "void main()\n{\n"; @@ -368,12 +360,11 @@ string ProgramBuilder::create_source(const list &variables, Va if((*i)->variable->scope==scope && !(*i)->inlined) { source += '\t'; - if(!(*i)->referenced_by.empty()) - { - source += (*i)->variable->type; - source += ' '; - } - source += format("%s = %s;\n", (*i)->resolved_name, (*i)->get_expression()); + if((*i)->referenced_by.empty()) + source += (*i)->resolved_name; + else + source += (*i)->create_declaration(); + source += format(" = %s;\n", (*i)->create_expression()); } if(scope==VERTEX) @@ -381,7 +372,7 @@ string ProgramBuilder::create_source(const list &variables, Va for(list::const_iterator i=varyings.begin(); i!=varyings.end(); ++i) { if((*i)->inlined) - source += format("\tv_%s = %s;\n", (*i)->resolved_name, (*i)->get_expression()); + source += format("\tv_%s = %s;\n", (*i)->resolved_name, (*i)->create_expression()); else source += format("\tv_%s = %s;\n", (*i)->resolved_name, (*i)->resolved_name); } @@ -624,19 +615,39 @@ void ProgramBuilder::ShaderVariable::update_reference(ShaderVariable &from, Shad 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::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; @@ -661,24 +672,48 @@ bool ProgramBuilder::ShaderVariable::is_referenced_from(VariableScope scope) con return false; } -string ProgramBuilder::ShaderVariable::get_expression() const +string ProgramBuilder::ShaderVariable::create_declaration(char interface) const { - map replace_map; - for(list::const_iterator i=referenced_vars.begin(); i!=referenced_vars.end(); ++i) - if((*i)->variable) + if(variable->scope==UNIFORM) + { + const char *bracket = strrchr(variable->type, '['); + if(bracket) + return format("%s %s%s", string(variable->type, bracket), resolved_name, bracket); + } + + if(interface) + return format("%s %c_%s", variable->type, interface, resolved_name); + else + return format("%s %s", variable->type, resolved_name); +} + +string ProgramBuilder::ShaderVariable::create_replacement(VariableScope from_scope) const +{ + string replacement = resolved_name; + if(variable) + { + if(from_scope==FRAGMENT && (variable->scope==VERTEX || variable->scope==ATTRIBUTE)) + replacement = "v_"+replacement; + else if(inlined) { - string replacement = (*i)->resolved_name; - if(variable->scope==FRAGMENT && ((*i)->variable->scope==VERTEX || (*i)->variable->scope==ATTRIBUTE)) - replacement = "v_"+replacement; - else if((*i)->inlined) - { - replacement = (*i)->get_expression(); - if((*i)->inline_parens) - replacement = "("+replacement+")"; - } - if(replacement!=(*i)->name) - replace_map[(*i)->name] = replacement; + replacement = create_expression(); + if(inline_parens) + replacement = "("+replacement+")"; } + } + + return replacement; +} + +string ProgramBuilder::ShaderVariable::create_expression() const +{ + map replace_map; + for(list::const_iterator i=referenced_vars.begin(); i!=referenced_vars.end(); ++i) + { + string replacement = (*i)->create_replacement(variable->scope); + if(replacement!=(*i)->name) + replace_map[(*i)->name] = replacement; + } if(replace_map.empty()) return variable->expression;