From: Mikko Rasa Date: Mon, 22 Aug 2016 12:33:42 +0000 (+0300) Subject: Support custom functions in ProgramBuilder X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=91b86d70b598193201a28c5cd6e6c4b180fda45a Support custom functions in ProgramBuilder --- diff --git a/source/programbuilder.cpp b/source/programbuilder.cpp index 5379abf2..195d410f 100644 --- a/source/programbuilder.cpp +++ b/source/programbuilder.cpp @@ -162,7 +162,7 @@ const ProgramBuilder::VariableDefinition ProgramBuilder::standard_variables[] = { NO_SCOPE, 0, 0, 0, 0 } }; -const char ProgramBuilder::interfaces[] = { 0, 0, 0, 0, 'v', 0 }; +const char ProgramBuilder::interfaces[] = { 0, 0, 0, 0, 0, 'v', 0 }; ProgramBuilder::ProgramBuilder(const StandardFeatures &f): features(f), @@ -211,6 +211,8 @@ ProgramBuilder::ProgramBuilder(const StandardFeatures &f): var.scope = VERTEX; else if(!strcmp(word, "fragment")) var.scope = FRAGMENT; + else if(!strcmp(word, "function")) + var.scope = FUNCTION; else throw invalid_variable_definition(word); } @@ -220,18 +222,29 @@ ProgramBuilder::ProgramBuilder(const StandardFeatures &f): var.name = word; start = features.custom.find_first_not_of(whitespace, word_end+1); - if(start>=decl_end) + if(start>=decl_end || (var.scope==FUNCTION && features.custom[start]=='(')) break; } if(equals!=string::npos) { + if(var.scope==FUNCTION) + throw invalid_variable_definition("function with expression"); start = features.custom.find_first_not_of(whitespace, equals+1); if(start>=semicolon) throw invalid_variable_definition("no expression"); features.custom[semicolon] = 0; var.expression = &features.custom[start]; } + else if(var.scope==FUNCTION) + { + string::size_type left_paren = features.custom.find('(', start); + string::size_type right_paren = features.custom.find(')', start); + if(left_paren>semicolon || right_paren>semicolon) + throw invalid_variable_definition("no argument list"); + features.custom[right_paren] = 0; + var.expression = &features.custom[left_paren+1]; + } else var.expression = 0; @@ -415,7 +428,13 @@ string ProgramBuilder::create_source(const list &variables, Va set declared_types; set uniform_blocks; for(list::const_iterator i=variables.begin(); i!=variables.end(); ++i) - if((*i)->variable->scope==UNIFORM && (*i)->is_referenced_from(scope) && !(*i)->inlined) + { + if(!(*i)->is_referenced_from(scope)) + continue; + + if((*i)->variable->scope==FUNCTION) + source += format("%s;\n", (*i)->create_declaration()); + else if((*i)->variable->scope==UNIFORM && !(*i)->inlined) { if((*i)->type && !declared_types.count((*i)->type)) { @@ -428,6 +447,7 @@ string ProgramBuilder::create_source(const list &variables, Va else source += format("uniform %s;\n", (*i)->create_declaration()); } + } for(set::const_iterator i=uniform_blocks.begin(); i!=uniform_blocks.end(); ++i) { @@ -921,7 +941,7 @@ void ProgramBuilder::ShaderVariable::update_reference(ShaderVariable &from, Shad void ProgramBuilder::ShaderVariable::check_inline(bool allow_legacy, bool trivial_only) { - if(variable->expression) + if(variable->expression && variable->scope>=UNIFORM) { if(array_sum && array_size>1) return; @@ -995,7 +1015,7 @@ ProgramBuilder::InterfaceFlags ProgramBuilder::ShaderVariable::get_interface_fla { /* Uniforms are available to all stages and are not passed through interfaces */ - if(variable->scope==UNIFORM) + if(variable->scope<=UNIFORM) return NO_INTERFACE; int flags = NO_INTERFACE; @@ -1035,6 +1055,9 @@ string ProgramBuilder::ShaderVariable::create_type_declaration() const string ProgramBuilder::ShaderVariable::create_declaration(char iface, bool loop) const { + if(variable->scope==FUNCTION) + return format("%s %s(%s)", variable->type, resolved_name, variable->expression); + if(variable->scope==UNIFORM && !array_subscript.empty()) { const char *bracket = strrchr(variable->type, '['); diff --git a/source/programbuilder.h b/source/programbuilder.h index 97a706e0..e61e9942 100644 --- a/source/programbuilder.h +++ b/source/programbuilder.h @@ -121,6 +121,7 @@ private: { NO_SCOPE, TYPE, + FUNCTION, UNIFORM, ATTRIBUTE, VERTEX,