]> git.tdb.fi Git - libs/gl.git/commitdiff
Automatically backport shaders to earlier GLSL versions if necessary
authorMikko Rasa <tdb@tdb.fi>
Fri, 18 Nov 2016 17:40:16 +0000 (19:40 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 18 Nov 2016 22:00:10 +0000 (00:00 +0200)
Fragment shader output replacement is a bit crude and will just replace
any output with gl_FragColor.  It will be made better later.

source/programcompiler.cpp
source/programcompiler.h
source/programsyntax.h

index 3cb8611c0192be3d08d67798aa9c1c0d6407f09a..d65869316423d64806a23bdf3e60254d0f014ce7 100644 (file)
@@ -58,15 +58,14 @@ void ProgramCompiler::add_shaders(Program &program)
        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)));
                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)));
        }
 
        program.bind_attribute(VERTEX4, "vertex");
@@ -164,6 +163,8 @@ void ProgramCompiler::generate(Stage &stage)
        apply<InterfaceGenerator>(stage);
        apply<VariableResolver>(stage);
        apply<VariableRenamer>(stage);
+       apply<LegacyConverter>(stage);
+       apply<VariableResolver>(stage);
 }
 
 bool ProgramCompiler::optimize(Stage &stage)
@@ -220,6 +221,14 @@ ProgramCompiler::Formatter::Formatter():
        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;
@@ -295,7 +304,7 @@ void ProgramCompiler::Formatter::visit(Block &block)
        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)
        {
@@ -1281,5 +1290,90 @@ void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
                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.interface=="in" || var.interface=="out")
+               if(!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
index 96fee471cc7e5351a59e7d51f9b3772862bcc195..8ae22901e89dcbfb19bf08fc2a25929aaddf9188 100644 (file)
@@ -38,6 +38,7 @@ private:
 
                Formatter();
 
+               virtual void apply(ProgramSyntax::Stage &);
                const std::string &get_result() const { return formatted; }
                virtual void visit(ProgramSyntax::Block &);
                virtual void visit(ProgramSyntax::Literal &);
@@ -246,6 +247,22 @@ private:
                virtual void visit(ProgramSyntax::VariableDeclaration &);
        };
 
+       struct LegacyConverter: BlockModifier
+       {
+               Version target_version;
+               std::string type;
+               std::string frag_out_name;
+
+               LegacyConverter();
+               LegacyConverter(const Version &);
+
+               bool check_version(const Version &);
+               virtual void visit(ProgramSyntax::VariableReference &);
+               virtual void visit(ProgramSyntax::FunctionCall &);
+               virtual void visit(ProgramSyntax::VariableDeclaration &);
+               virtual void visit(ProgramSyntax::InterfaceBlock &);
+       };
+
        Resources *resources;
        ProgramParser parser;
        ProgramSyntax::Module *module;
index 089683323c507b81573b0c908163f9b28337de7d..2f9f1fc08a50f47eb3a8fc6f4757217cb39f0b09 100644 (file)
@@ -5,6 +5,7 @@
 #include <map>
 #include <string>
 #include <vector>
+#include "extension.h"
 
 namespace Msp {
 namespace GL {
@@ -343,6 +344,7 @@ struct Stage
        ProgramSyntax::Block content;
        std::map<std::string, VariableDeclaration *> in_variables;
        std::map<std::string, VariableDeclaration *> out_variables;
+       Version required_version;
 
        Stage(StageType);
 };