]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/compiler.cpp
Add basic validation to the GLSL compiler
[libs/gl.git] / source / glsl / compiler.cpp
index 55a69f0df38ecaf1b681f9a698e6bbc2abed02da..803862cb45787974a21a50628d9495009eb2fbca 100644 (file)
@@ -1,5 +1,4 @@
 #include <msp/core/algorithm.h>
-#include <msp/gl/extensions/ext_gpu_shader4.h>
 #include <msp/strings/format.h>
 #include "builtin.h"
 #include "compatibility.h"
@@ -7,10 +6,11 @@
 #include "debug.h"
 #include "error.h"
 #include "generate.h"
+#include "glsl_error.h"
 #include "optimize.h"
 #include "output.h"
 #include "resources.h"
-#include "shader.h"
+#include "validate.h"
 
 #undef interface
 
@@ -76,6 +76,14 @@ void Compiler::compile(Mode mode)
 {
        for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
                generate(*i, mode);
+
+       bool valid = true;
+       for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+               if(!validate(*i))
+                       valid = false;
+       if(!valid)
+               throw invalid_shader_source(get_diagnostics());
+
        unsigned n = 0;
        for(list<Stage>::iterator i=module->stages.begin(); (i!=module->stages.end() && n<10000); ++n)
        {
@@ -152,6 +160,15 @@ string Compiler::get_stage_debug(Stage::Type stage_type) const
        throw key_error(Stage::get_stage_name(stage_type));
 }
 
+string Compiler::get_diagnostics() const
+{
+       string combined;
+       for(list<Stage>::const_iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+               for(vector<Diagnostic>::const_iterator j=i->diagnostics.begin(); j!=i->diagnostics.end(); ++j)
+                       combined += format("%s:%d: %s\n", module->source_map.get_name(j->source), j->line, j->message);
+       return combined;
+}
+
 void Compiler::append_module(Module &mod, DataFile::Collection *res)
 {
        module->source_map.merge_from(mod.source_map);
@@ -239,13 +256,28 @@ void Compiler::generate(Stage &stage, Mode mode)
                LegacyConverter().apply(stage, features);
 }
 
+bool Compiler::validate(Stage &stage)
+{
+       DeclarationValidator().apply(stage);
+
+       for(vector<Diagnostic>::const_iterator i=stage.diagnostics.begin(); i!=stage.diagnostics.end(); ++i)
+               if(i->severity==Diagnostic::ERR)
+                       return false;
+
+       return true;
+}
+
 Compiler::OptimizeResult Compiler::optimize(Stage &stage)
 {
        ConstantConditionEliminator().apply(stage);
 
        bool any_inlined = FunctionInliner().apply(stage);
-       BlockHierarchyResolver().apply(stage);
-       VariableResolver().apply(stage);
+       any_inlined |= ExpressionInliner().apply(stage);
+       if(any_inlined)
+       {
+               VariableResolver().apply(stage);
+               FunctionResolver().apply(stage);
+       }
 
        /* Removing variables or functions may cause things from the previous stage
        to become unused. */