if(!module)
throw invalid_operation("ProgramCompiler::add_shaders");
- string head = "#version 150\n";
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
{
if(i->type==VERTEX)
- program.attach_shader_owned(new VertexShader(head+apply<Formatter>(*i)));
+ {
+ program.attach_shader_owned(new VertexShader(apply<Formatter>(*i)));
+ for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
+ program.bind_attribute(j->second, j->first);
+ }
else if(i->type==GEOMETRY)
- program.attach_shader_owned(new GeometryShader(head+apply<Formatter>(*i)));
+ program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
else if(i->type==FRAGMENT)
- program.attach_shader_owned(new FragmentShader(head+apply<Formatter>(*i)));
+ {
+ program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
+ for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
+ program.bind_fragment_data(j->second, j->first);
+ }
}
-
- program.bind_attribute(VERTEX4, "vertex");
- program.bind_attribute(NORMAL3, "normal");
- program.bind_attribute(COLOR4_FLOAT, "color");
- program.bind_attribute(TEXCOORD4, "texcoord");
}
Module *ProgramCompiler::create_builtins_module()
void ProgramCompiler::import(const string &name)
{
- if(!resources)
- throw runtime_error("no resources");
- RefPtr<IO::Seekable> io = resources->open_raw(name+".glsl");
+ string fn = name+".glsl";
+ RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
if(!io)
throw runtime_error(format("module %s not found", name));
ProgramParser import_parser;
apply<InterfaceGenerator>(stage);
apply<VariableResolver>(stage);
apply<VariableRenamer>(stage);
+ apply<LegacyConverter>(stage);
+ apply<VariableResolver>(stage);
}
bool ProgramCompiler::optimize(Stage &stage)
else_if(0)
{ }
+void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
+{
+ const Version &ver = s.required_version;
+ if(ver.major)
+ formatted += format("#version %d%d\n", ver.major, ver.minor);
+ Visitor::apply(s);
+}
+
void ProgramCompiler::Formatter::visit(Literal &literal)
{
formatted += literal.token;
if(use_braces)
formatted += format("%s{\n", string(brace_indent*2, ' '));
- SetForScope<unsigned> set(indent, indent+!formatted.empty());
+ SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
string spaces(indent*2, ' ');
for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
{
if(!i->value.empty())
formatted += format("=%s", i->value);
}
- formatted += format(") %s;", layout.interface);
+ formatted += ')';
+}
+
+void ProgramCompiler::Formatter::visit(InterfaceLayout &layout)
+{
+ layout.layout.visit(*this);
+ formatted += format(" %s;", layout.interface);
}
void ProgramCompiler::Formatter::visit(StructDeclaration &strct)
void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
{
+ if(var.layout)
+ {
+ var.layout->visit(*this);
+ formatted += ' ';
+ }
if(var.constant)
formatted += "const ";
if(!var.sampling.empty())
VariableDeclaration *&ptr = variables[var.name];
if(ptr)
{
+ ptr->type = var.type;
if(var.init_expression)
ptr->init_expression = var.init_expression;
remove_node = true;
result_valid = true;
}
+void ProgramCompiler::ExpressionEvaluator::visit(ParenthesizedExpression &parexp)
+{
+ parexp.expression->visit(*this);
+}
+
void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
{
if(!var.declaration)
{
stage->in_variables.erase(var.name);
stage->out_variables.erase(var.name);
+ stage->locations.erase(var.name);
if(var.linked_declaration)
var.linked_declaration->linked_declaration = 0;
}
var.init_expression = 0;
}
+
+ProgramCompiler::LegacyConverter::LegacyConverter():
+ target_version(get_glsl_version())
+{ }
+
+ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v):
+ target_version(v)
+{ }
+
+bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version)
+{
+ if(target_version<feature_version)
+ return false;
+ else if(stage->required_version<feature_version)
+ stage->required_version = feature_version;
+
+ return true;
+}
+
+void ProgramCompiler::LegacyConverter::visit(VariableReference &var)
+{
+ if(var.name==frag_out_name && !check_version(Version(1, 30)))
+ {
+ var.name = "gl_FragColor";
+ var.declaration = 0;
+ type = "vec4";
+ }
+ else if(var.declaration)
+ type = var.declaration->type;
+ else
+ type = string();
+}
+
+void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
+{
+ if(call.name=="texture" && !call.declaration && !check_version(Version(1, 30)))
+ {
+ vector<NodePtr<Expression> >::iterator i = call.arguments.begin();
+ if(i!=call.arguments.end())
+ {
+ (*i)->visit(*this);
+ if(type=="sampler1D")
+ call.name = "texture1D";
+ else if(type=="sampler2D")
+ call.name = "texture2D";
+ else if(type=="sampler3D")
+ call.name = "texture3D";
+ else if(type=="sampler1DShadow")
+ call.name = "shadow1D";
+ else if(type=="sampler2DShadow")
+ call.name = "shadow2D";
+
+ for(; i!=call.arguments.end(); ++i)
+ (*i)->visit(*this);
+ }
+ }
+ else
+ TraversingVisitor::visit(call);
+}
+
+void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var)
+{
+ if(var.layout && !check_version(Version(3, 30)))
+ {
+ vector<Layout::Qualifier>::iterator i;
+ for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
+ if(i!=var.layout->qualifiers.end())
+ {
+ unsigned location = lexical_cast<unsigned>(i->value);
+ if(stage->type==VERTEX && var.interface=="in")
+ {
+ stage->locations[var.name] = location;
+ var.layout->qualifiers.erase(i);
+ }
+ else if(stage->type==FRAGMENT && var.interface=="out")
+ {
+ stage->locations[var.name] = location;
+ var.layout->qualifiers.erase(i);
+ }
+
+ if(var.layout->qualifiers.empty())
+ var.layout = 0;
+ }
+ }
+
+ if((var.interface=="in" || var.interface=="out") && !check_version(Version(1, 30)))
+ {
+ if(stage->type==VERTEX && var.interface=="in")
+ var.interface = "attribute";
+ else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in"))
+ var.interface = "varying";
+ else if(stage->type==FRAGMENT && var.interface=="out")
+ {
+ frag_out_name = var.name;
+ remove_node = true;
+ }
+ }
+
+ TraversingVisitor::visit(var);
+}
+
+void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface)
+{
+ if(!check_version(Version(1, 50)))
+ flatten_block(iface.members);
+}
+
} // namespace GL
} // namespace Msp