]> git.tdb.fi Git - libs/gl.git/blobdiff - source/programcompiler.cpp
Remove the deprecated ProgramBuilder class
[libs/gl.git] / source / programcompiler.cpp
index 518b31e17f0d76213f2de8c52160cb3602f346b5..d021ab4f75732769855e9370fe0c8eec990aca20 100644 (file)
@@ -4,7 +4,9 @@
 #include <msp/gl/extensions/arb_gpu_shader5.h>
 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
 #include <msp/gl/extensions/ext_gpu_shader4.h>
+#include <msp/gl/extensions/ext_texture_array.h>
 #include <msp/strings/format.h>
+#include <msp/strings/regex.h>
 #include <msp/strings/utils.h>
 #include "error.h"
 #include "program.h"
@@ -57,7 +59,7 @@ void ProgramCompiler::compile(const string &source, const string &src_name)
        delete module;
        module = new Module();
        ProgramParser parser;
-       imported_names.insert(src_name);
+       imported_names.push_back(src_name);
        append_module(parser.parse(source, src_name, 1));
        process();
 }
@@ -68,7 +70,7 @@ void ProgramCompiler::compile(IO::Base &io, Resources *res, const string &src_na
        delete module;
        module = new Module();
        ProgramParser parser;
-       imported_names.insert(src_name);
+       imported_names.push_back(src_name);
        append_module(parser.parse(io, src_name, 1));
        process();
 }
@@ -83,25 +85,64 @@ void ProgramCompiler::add_shaders(Program &program)
        if(!module)
                throw invalid_operation("ProgramCompiler::add_shaders");
 
-       for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+       try
        {
-               if(i->type==VERTEX)
+               for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++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);
+                       if(i->type==VERTEX)
+                       {
+                               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(apply<Formatter>(*i)));
+                       else if(i->type==FRAGMENT)
+                       {
+                               program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
+                               if(EXT_gpu_shader4)
+                               {
+                                       for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
+                                               program.bind_fragment_data(j->second, j->first);
+                               }
+                       }
                }
-               else if(i->type==GEOMETRY)
-                       program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
-               else if(i->type==FRAGMENT)
+       }
+       catch(const compile_error &e)
+       {
+               static const Regex r_message("^(([0-9]+)\\(([0-9]+)\\) :|ERROR: ([0-9]+):([0-9]+):) (.*)$");
+               vector<string> lines = split(e.what(), '\n');
+               string translated;
+               for(vector<string>::const_iterator i=lines.begin(); i!=lines.end(); ++i)
                {
-                       program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
-                       if(EXT_gpu_shader4)
+                       RegMatch m = r_message.match(*i);
+                       if(m)
                        {
-                               for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
-                                       program.bind_fragment_data(j->second, j->first);
+                               unsigned index = 0;
+                               unsigned line = 0;
+                               if(m[2])
+                               {
+                                       index = lexical_cast<unsigned>(m[2].str);
+                                       line = lexical_cast<unsigned>(m[3].str);
+                               }
+                               else if(m[4])
+                               {
+                                       index = lexical_cast<unsigned>(m[4].str);
+                                       line = lexical_cast<unsigned>(m[5].str);
+                               }
+                               const char *src = "<unknown>";
+                               if(index==0)
+                                       src = "<generated>";
+                               else if(index-1<imported_names.size())
+                                       src = imported_names[index-1].c_str();
+                               translated += format("%s:%d: %s", src, line, m[6].str);
                        }
+                       else
+                               translated += *i;
+                       translated += '\n';
                }
+
+               throw compile_error(translated);
        }
 }
 
@@ -168,6 +209,8 @@ void ProgramCompiler::append_stage(Stage &stage)
                target = &*i;
        }
 
+       if(stage.required_version>target->required_version)
+               target->required_version = stage.required_version;
        for(NodeList<Statement>::iterator i=stage.content.body.begin(); i!=stage.content.body.end(); ++i)
                target->content.body.push_back(*i);
        apply<DeclarationCombiner>(*target);
@@ -191,9 +234,9 @@ void ProgramCompiler::process()
 void ProgramCompiler::import(const string &name)
 {
        string fn = name+".glsl";
-       if(imported_names.count(fn))
+       if(find(imported_names, fn)!=imported_names.end())
                return;
-       imported_names.insert(fn);
+       imported_names.push_back(fn);
 
        RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
        if(!io)
@@ -204,6 +247,8 @@ void ProgramCompiler::import(const string &name)
 
 void ProgramCompiler::generate(Stage &stage)
 {
+       if(module->shared.required_version>stage.required_version)
+               stage.required_version = module->shared.required_version;
        inject_block(stage.content, module->shared.content);
 
        apply<DeclarationReorderer>(stage);
@@ -307,6 +352,7 @@ void ProgramCompiler::BlockModifier::visit(Block &block)
 
 
 ProgramCompiler::Formatter::Formatter():
+       source_index(0),
        source_line(1),
        indent(0),
        parameter_list(false)
@@ -949,7 +995,7 @@ bool ProgramCompiler::InterfaceGenerator::generate_interface(VariableDeclaration
        return true;
 }
 
-void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right)
+ExpressionStatement &ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right)
 {
        Assignment *assign = new Assignment;
        VariableReference *ref = new VariableReference;
@@ -962,6 +1008,8 @@ void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left,
        stmt->expression = assign;
        stmt->visit(*this);
        insert_nodes.push_back(stmt);
+
+       return *stmt;
 }
 
 void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var)
@@ -993,7 +1041,9 @@ void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var)
                        remove_node = true;
                        if(var.init_expression)
                        {
-                               insert_assignment(var.name, var.init_expression->clone());
+                               ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
+                               stmt.source = var.source;
+                               stmt.line = var.line;
                                return;
                        }
                }
@@ -1631,7 +1681,7 @@ void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
                {
                        if(!i->second.referenced)
                                unused_nodes.insert(i->first);
-                       clear_assignments(i->second, true);
+                       clear_assignments(i->second, i->first->interface!="out");
                        continue;
                }
 
@@ -1904,10 +1954,32 @@ void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
                                call.name = "texture2D";
                        else if(type=="sampler3D")
                                call.name = "texture3D";
+                       else if(type=="samplerCube")
+                               call.name = "textureCube";
                        else if(type=="sampler1DShadow")
                                call.name = "shadow1D";
                        else if(type=="sampler2DShadow")
                                call.name = "shadow2D";
+                       else if(type=="sampler1DArray")
+                       {
+                               check_extension(EXT_texture_array);
+                               call.name = "texture1DArray";
+                       }
+                       else if(type=="sampler2DArray")
+                       {
+                               check_extension(EXT_texture_array);
+                               call.name = "texture2DArray";
+                       }
+                       else if(type=="sampler1DArrayShadow")
+                       {
+                               check_extension(EXT_texture_array);
+                               call.name = "shadow1DArray";
+                       }
+                       else if(type=="sampler2DArrayShadow")
+                       {
+                               check_extension(EXT_texture_array);
+                               call.name = "shadow2DArray";
+                       }
 
                        for(; i!=call.arguments.end(); ++i)
                                (*i)->visit(*this);