{ 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),
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);
}
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;
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))
{
else
source += format("uniform %s;\n", (*i)->create_declaration());
}
+ }
for(set<string>::const_iterator i=uniform_blocks.begin(); i!=uniform_blocks.end(); ++i)
{
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;
{
/* 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;
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, '[');