]> git.tdb.fi Git - libs/gl.git/commitdiff
Support custom functions in ProgramBuilder
authorMikko Rasa <tdb@tdb.fi>
Mon, 22 Aug 2016 12:33:42 +0000 (15:33 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 22 Aug 2016 12:33:42 +0000 (15:33 +0300)
source/programbuilder.cpp
source/programbuilder.h

index 5379abf2cc289162fb843341c7315759d039431f..195d410fe10f7971739e9ee03448f810dd7c8235 100644 (file)
@@ -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<ShaderVariable *> &variables, Va
        set<const VariableDefinition *> declared_types;
        set<string> uniform_blocks;
        for(list<ShaderVariable *>::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<ShaderVariable *> &variables, Va
                        else
                                source += format("uniform %s;\n", (*i)->create_declaration());
                }
+       }
 
        for(set<string>::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, '[');
index 97a706e077d93d3729c65eba5290c5a6a5b285e2..e61e9942c0a343083f5d876baaa819befac61b44 100644 (file)
@@ -121,6 +121,7 @@ private:
        {
                NO_SCOPE,
                TYPE,
+               FUNCTION,
                UNIFORM,
                ATTRIBUTE,
                VERTEX,