]> git.tdb.fi Git - libs/gl.git/blobdiff - source/programcompiler.cpp
Support precision qualifiers in shaders
[libs/gl.git] / source / programcompiler.cpp
index 697ec2193ed9e022c1bd283f4405f4188ceaf8bb..c54a33d6b6fbf0147fe21dd069db9f391d42cc16 100644 (file)
@@ -122,6 +122,8 @@ void ProgramCompiler::process()
                else
                        ++i;
        }
+       for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+               finalize(*i);
 }
 
 void ProgramCompiler::import(const string &name)
@@ -185,6 +187,14 @@ bool ProgramCompiler::optimize(Stage &stage)
        return !unused.empty();
 }
 
+void ProgramCompiler::finalize(Stage &stage)
+{
+       if(get_gl_api()==OPENGL_ES2)
+               apply<DefaultPrecisionGenerator>(stage);
+       else
+               apply<PrecisionRemover>(stage);
+}
+
 void ProgramCompiler::inject_block(Block &target, const Block &source)
 {
        list<RefPtr<Node> >::iterator insert_point = target.body.begin();
@@ -239,12 +249,6 @@ void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
                formatted += '\n';
        }
 
-       if(api==OPENGL_ES2)
-       {
-               if(s.type==FRAGMENT)
-                       formatted += "precision mediump float;\n";
-       }
-
        Visitor::apply(s);
 }
 
@@ -343,6 +347,11 @@ void ProgramCompiler::Formatter::visit(Import &import)
        formatted += format("import %s;", import.module);
 }
 
+void ProgramCompiler::Formatter::visit(Precision &prec)
+{
+       formatted += format("precision %s %s;", prec.precision, prec.type);
+}
+
 void ProgramCompiler::Formatter::visit(Layout &layout)
 {
        formatted += "layout(";
@@ -393,6 +402,8 @@ void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
                }
                formatted += format("%s ", interface);
        }
+       if(!var.precision.empty())
+               formatted += format("%s ", var.precision);
        formatted += format("%s %s", var.type, var.name);
        if(var.array)
        {
@@ -1507,6 +1518,65 @@ void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
 }
 
 
+void ProgramCompiler::PrecisionRemover::visit(Precision &)
+{
+       remove_node = true;
+}
+
+void ProgramCompiler::PrecisionRemover::visit(VariableDeclaration &var)
+{
+       var.precision.clear();
+}
+
+
+ProgramCompiler::DefaultPrecisionGenerator::DefaultPrecisionGenerator():
+       toplevel(true)
+{ }
+
+void ProgramCompiler::DefaultPrecisionGenerator::visit(Block &block)
+{
+       if(toplevel)
+       {
+               SetForScope<bool> set(toplevel, false);
+               BlockModifier::visit(block);
+       }
+       else
+               Visitor::visit(block);
+}
+
+void ProgramCompiler::DefaultPrecisionGenerator::visit(Precision &prec)
+{
+       have_default.insert(prec.type);
+}
+
+void ProgramCompiler::DefaultPrecisionGenerator::visit(VariableDeclaration &var)
+{
+       if(var.type_declaration)
+               return;
+
+       string type = var.type;
+       if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
+               type = "float";
+       else if(!type.compare(0, 3, "ivec") || type=="uint")
+               type = "int";
+
+       if(!have_default.count(type))
+       {
+               Precision *prec = new Precision;
+               if(!type.compare(0, 7, "sampler"))
+                       prec->precision = "lowp";
+               else if(stage->type==FRAGMENT)
+                       prec->precision = "mediump";
+               else
+                       prec->precision = "highp";
+               prec->type = type;
+               insert_nodes.push_back(prec);
+
+               have_default.insert(type);
+       }
+}
+
+
 ProgramCompiler::LegacyConverter::LegacyConverter():
        target_api(get_gl_api()),
        target_version(get_glsl_version()),