]> git.tdb.fi Git - libs/gl.git/commitdiff
Add a standalone GLSL compiler frontend
authorMikko Rasa <tdb@tdb.fi>
Sun, 21 Feb 2021 23:12:25 +0000 (01:12 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 21 Feb 2021 23:53:20 +0000 (01:53 +0200)
This makes debugging the compiler easier and will eventually allow
shaders to be compiled into SPIR-V during build.

Build
source/glsl/compiler.cpp
source/glsl/compiler.h
source/glsl/features.cpp
source/glsl/features.h
tools/glslcompiler.cpp [new file with mode: 0644]

diff --git a/Build b/Build
index 19831c3e54cc5eed723f2f91acd9572ccd288f63..fb571b0c085f7665ed579412623d715f6e87fdbb 100644 (file)
--- a/Build
+++ b/Build
@@ -94,6 +94,12 @@ package "mspgl"
                use "mspgl";
        };
 
+       program "glslcompiler"
+       {
+               source "tools/glslcompiler.cpp";
+               use "mspgl";
+       };
+
        source_tarball
        {
                source "License.txt";
index 4a7a19e29759770966db8ae105c0967bdd5c4f9b..ca6c58057022b8b3a9f69373433c0f6c54a2e35d 100644 (file)
@@ -3,6 +3,7 @@
 #include <msp/strings/format.h>
 #include "compatibility.h"
 #include "compiler.h"
+#include "debug.h"
 #include "error.h"
 #include "generate.h"
 #include "optimize.h"
@@ -132,6 +133,14 @@ const SourceMap &Compiler::get_source_map() const
        return module->source_map;
 }
 
+string Compiler::get_stage_debug(Stage::Type stage_type) const
+{
+       for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+               if(i->type==stage_type)
+                       return DumpTree().apply(*i);
+       throw key_error(Stage::get_stage_name(stage_type));
+}
+
 void Compiler::append_module(Module &mod, DataFile::Collection *res)
 {
        module->source_map.merge_from(mod.source_map);
index 8340aa6d817bf426caa495eb981944092b9bf256..4eaff213076ea07131528b03810b1c51b961369e 100644 (file)
@@ -44,8 +44,10 @@ public:
        const std::map<std::string, unsigned> &get_vertex_attributes() const;
        const std::map<std::string, unsigned> &get_fragment_outputs() const;
        const SourceMap &get_source_map() const;
-private:
 
+       std::string get_stage_debug(Stage::Type) const;
+
+private:
        void append_module(Module &, DataFile::Collection *);
        void append_stage(Stage &);
        void import(DataFile::Collection *, const std::string &);
index d1c8101d63ab2a5054a34dd743642289e29aa0c7..11b6c942fa4324b4e6b15f546d11bf440ab0bacc 100644 (file)
@@ -32,6 +32,19 @@ Features Features::from_context()
        return features;
 }
 
+Features Features::all()
+{
+       Features features;
+       features.gl_api = OPENGL;
+       features.glsl_version = Version(4, 60);
+       features.arb_explicit_attrib_location = true;
+       features.arb_gpu_shader5 = true;
+       features.arb_uniform_buffer_object = true;
+       features.ext_gpu_shader4 = true;
+       features.ext_texture_array = true;
+       return features;
+}
+
 } // namespace SL
 } // namespace GL
 } // namespace Msp
index 8f7a3e7c342eb69d12856c93f1f9af6ae017aaf4..8d32f8beefa35254a3d1cce8bb1b8c72b2e91979 100644 (file)
@@ -20,6 +20,7 @@ struct Features
        Features();
 
        static Features from_context();
+       static Features all();
 };
 
 } // namespace SL
diff --git a/tools/glslcompiler.cpp b/tools/glslcompiler.cpp
new file mode 100644 (file)
index 0000000..74b37ef
--- /dev/null
@@ -0,0 +1,71 @@
+#include <msp/core/application.h>
+#include <msp/core/getopt.h>
+#include <msp/gl/glsl/compiler.h>
+#include <msp/io/print.h>
+
+class GlslCompiler: public Msp::RegisteredApplication<GlslCompiler>
+{
+private:
+       std::string source_fn;
+       bool parse_only;
+       bool combined;
+       Msp::GL::SL::Stage::Type stage;
+       bool dump_ast;
+
+public:
+       GlslCompiler(int, char **);
+
+       virtual int main();
+};
+
+using namespace std;
+using namespace Msp;
+
+GlslCompiler::GlslCompiler(int argc, char **argv):
+       parse_only(false),
+       combined(false),
+       stage(GL::SL::Stage::SHARED),
+       dump_ast(false)
+{
+       string stage_str;
+
+       GetOpt getopt;
+       getopt.add_option('c', "combined", combined, GetOpt::NO_ARG).set_help("Output combined GLSL");
+       getopt.add_option('a', "dump-ast", dump_ast, GetOpt::NO_ARG).set_help("Dump AST for debugging");
+       getopt.add_option('p', "parse_only", parse_only, GetOpt::NO_ARG).set_help("Only parse the loaded source, don't compile");
+       getopt.add_option('s', "stage", stage_str, GetOpt::REQUIRED_ARG).set_help("Output GLSL for STAGE", "STAGE");
+       getopt.add_argument("source", source_fn, GetOpt::REQUIRED_ARG).set_help("GLSL file to compile");
+       getopt(argc, argv);
+
+       if(stage_str=="vertex")
+               stage = GL::SL::Stage::VERTEX;
+       else if(stage_str=="geometry")
+               stage = GL::SL::Stage::GEOMETRY;
+       else if(stage_str=="fragment")
+               stage = GL::SL::Stage::FRAGMENT;
+       else if(!dump_ast)
+               combined = true;
+}
+
+int GlslCompiler::main()
+{
+       GL::SL::Compiler compiler(GL::SL::Features::all());
+       IO::File file(source_fn);
+       compiler.load_source(file, source_fn);
+       if(!parse_only)
+               compiler.compile(GL::SL::Compiler::PROGRAM);
+
+       if(dump_ast)
+       {
+               vector<GL::SL::Stage::Type> stages = compiler.get_stages();
+               for(vector<GL::SL::Stage::Type>::const_iterator i=stages.begin(); i!=stages.end(); ++i)
+                       IO::print("%s\n", compiler.get_stage_debug(*i));
+       }
+
+       if(combined)
+               IO::print("%s\n", compiler.get_combined_glsl());
+       else if(stage!=GL::SL::Stage::SHARED)
+               IO::print("%s\n", compiler.get_stage_glsl(stage));
+
+       return 0;
+}