X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogrambuilder.cpp;h=05e801c72b8cc3cbbd77821a6e0dcdf84670955f;hp=1e07c1e555b03af9e271db964d398a72dbab95f8;hb=83bfb4bc26cf20cada1fcda47064b75d8e49fa08;hpb=b250a711295f5ba00114f11a5b1c855eebe08d26 diff --git a/source/programbuilder.cpp b/source/programbuilder.cpp index 1e07c1e5..05e801c7 100644 --- a/source/programbuilder.cpp +++ b/source/programbuilder.cpp @@ -38,16 +38,17 @@ anything that might need them. */ const ProgramBuilder::StandardVariable ProgramBuilder::standard_variables[] = { { FRAGMENT, "gl_FragColor", 0, "color_base", "!t" }, - { FRAGMENT, "gl_FragColor", 0, "tex_sample*color_base", "t" }, - { FRAGMENT, "color_base", "vec4", "color_unlit", "!l!s" }, - { FRAGMENT, "color_base", "vec4", "color_unlit*vec4(vec3(l_shadow), 1.0)", "!ls" }, + { FRAGMENT, "gl_FragColor", 0, "tex_sample", "!l!s!mt" }, + { FRAGMENT, "gl_FragColor", 0, "tex_sample*color_base", "l|s|mt" }, + { FRAGMENT, "color_base", "vec4", "vec4(1.0)", "!l!s!m" }, + { FRAGMENT, "color_base", "vec4", "color", "!l!sm" }, + { FRAGMENT, "color_base", "vec4", "vec4(vec3(l_shadow), 1.0)", "!ls!m" }, + { FRAGMENT, "color_base", "vec4", "color*vec4(vec3(l_shadow), 1.0)", "!lsm" }, { FRAGMENT, "color_base", "vec4", "vec4(rgb_light_full, 1.0)", "l!m" }, { FRAGMENT, "color_base", "vec4", "vec4(rgb_light_full, gl_FrontMaterial.diffuse.a)", "lm" }, - { FRAGMENT, "color_unlit", "vec4", "vec4(1.0)", "!m" }, - { FRAGMENT, "color_unlit", "vec4", "color", "m" }, { FRAGMENT, "rgb_light_full", "vec3", "rgb_light_shadow+gl_FrontLightModelProduct.sceneColor.rgb", "m" }, { FRAGMENT, "rgb_light_full", "vec3", "rgb_light_shadow", "!m" }, - { FRAGMENT, "rgb_light_shadow", "vec3", "(rgb_light)*l_shadow", "s" }, + { FRAGMENT, "rgb_light_shadow", "vec3", "rgb_light*l_shadow", "s" }, { FRAGMENT, "rgb_light_shadow", "vec3", "rgb_light", "!s" }, { FRAGMENT, "rgb_light", "vec3", "vec3(l_diffuse)", "!m!p" }, { FRAGMENT, "rgb_light", "vec3", "vec3(l_diffuse+l_specular)", "!mp" }, @@ -97,9 +98,15 @@ const ProgramBuilder::StandardVariable ProgramBuilder::standard_variables[] = ProgramBuilder::ProgramBuilder(const StandardFeatures &f): features(f), - feature_flags(features.create_flags()) + feature_flags(features.create_flags()), + optimize(true) { } +void ProgramBuilder::set_optimize(bool o) +{ + optimize = o; +} + Program *ProgramBuilder::create_program() const { Program *prog = new Program; @@ -167,6 +174,12 @@ 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(); + } + prog.attach_shader_owned(new VertexShader(create_source(resolved_vars, VERTEX))); prog.attach_shader_owned(new FragmentShader(create_source(resolved_vars, FRAGMENT))); } @@ -206,7 +219,7 @@ string ProgramBuilder::create_source(const list &variables, Va source += "void main()\n{\n"; for(list::const_iterator i=variables.begin(); i!=variables.end(); ++i) - if((*i)->variable->scope==scope) + if((*i)->variable->scope==scope && !(*i)->inlined) { source += '\t'; if((*i)->variable->type) @@ -220,7 +233,12 @@ string ProgramBuilder::create_source(const list &variables, Va if(scope==VERTEX) { for(list::const_iterator i=varyings.begin(); i!=varyings.end(); ++i) - source += format("\tv_%s = %s;\n", (*i)->resolved_name, (*i)->resolved_name); + { + if((*i)->inlined) + source += format("\tv_%s = %s;\n", (*i)->resolved_name, (*i)->get_expression()); + else + source += format("\tv_%s = %s;\n", (*i)->resolved_name, (*i)->resolved_name); + } } source += '}'; @@ -401,7 +419,9 @@ ProgramBuilder::ShaderVariable::ShaderVariable(const std::string &n): name(n), variable(0), resolved_name(n), - fuzzy_space(name.find("zzz")!=string::npos) + fuzzy_space(name.find("zzz")!=string::npos), + inlined(false), + inline_parens(false) { } void ProgramBuilder::ShaderVariable::resolve(const StandardVariable &var) @@ -416,6 +436,7 @@ void ProgramBuilder::ShaderVariable::resolve(ShaderVariable &var) { for(list::iterator i=referenced_by.begin(); i!=referenced_by.end(); ++i) (*i)->update_reference(*this, var); + var.referenced_by.insert(var.referenced_by.end(), referenced_by.begin(), referenced_by.end()); } void ProgramBuilder::ShaderVariable::resolve_space(const string &space) @@ -454,6 +475,32 @@ void ProgramBuilder::ShaderVariable::update_reference(ShaderVariable &from, Shad resolve_space(to.resolved_space); } +void ProgramBuilder::ShaderVariable::check_inline() +{ + if(variable->expression) + { + unsigned total_refs = referenced_by.size(); + 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)) + { + inlined = true; + unsigned level = 0; + for(const char *c=variable->expression; (!inline_parens && *c); ++c) + { + if(*c=='(') + ++level; + else if(*c==')') + --level; + else if(level==0 && !isalnum(*c) && *c!='_' && *c!='.') + inline_parens = true; + } + } + } +} + bool ProgramBuilder::ShaderVariable::is_referenced_from(VariableScope scope) const { for(list::const_iterator i=referenced_by.begin(); i!=referenced_by.end(); ++i) @@ -468,11 +515,17 @@ string ProgramBuilder::ShaderVariable::get_expression() const for(list::const_iterator i=referenced_vars.begin(); i!=referenced_vars.end(); ++i) if((*i)->variable) { - string var_name = (*i)->resolved_name; + string replacement = (*i)->resolved_name; if(variable->scope==FRAGMENT && (*i)->variable->scope==VERTEX) - var_name = "v_"+var_name; - if(var_name!=(*i)->name) - replace_map[(*i)->name] = var_name; + 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; } if(replace_map.empty())