Translate shader compile errors to actual source file names
authorMikko Rasa <tdb@tdb.fi>
Fri, 21 Jun 2019 11:46:34 +0000 (14:46 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 21 Jun 2019 12:02:35 +0000 (15:02 +0300)
Intel drivers appear to process the #line directives incorrectly and
produce off-by-one line numbers.

source/programcompiler.cpp
source/programcompiler.h

index 518b31e17f0d76213f2de8c52160cb3602f346b5..bb77e0ea911e205c192c68cd88462f6affdf1ff6 100644 (file)
@@ -5,6 +5,7 @@
 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
 #include <msp/gl/extensions/ext_gpu_shader4.h>
 #include <msp/strings/format.h>
+#include <msp/strings/regex.h>
 #include <msp/strings/utils.h>
 #include "error.h"
 #include "program.h"
@@ -57,7 +58,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 +69,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 +84,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);
        }
 }
 
@@ -191,9 +231,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)
index 697c608617bc2a85c91524b04d91eff0978d74f2..bea3faec1d0fee7552cb4cbd5fb36717dca8fb34 100644 (file)
@@ -381,7 +381,7 @@ private:
 
        Resources *resources;
        ProgramSyntax::Module *module;
-       std::set<std::string> imported_names;
+       std::vector<std::string> imported_names;
 
 public:
        ProgramCompiler();