]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/validate.cpp
Add a utility function for following a chain of base types
[libs/gl.git] / source / glsl / validate.cpp
index f12177db4a4236109f4060ffc72c13098f66093f..df3312e1fa9f6b46f3fdc52f7e305ded14059bab 100644 (file)
@@ -34,6 +34,13 @@ void Validator::add_info(Node &node, const string &message)
 }
 
 
+void DeclarationValidator::apply(Stage &s, const Features &f)
+{
+       stage = &s;
+       features = f;
+       s.content.visit(*this);
+}
+
 const char *DeclarationValidator::describe_variable(ScopeType scope)
 {
        switch(scope)
@@ -49,6 +56,8 @@ const char *DeclarationValidator::describe_variable(ScopeType scope)
 
 void DeclarationValidator::visit(Layout &layout)
 {
+       bool push_constant = false;
+       bool binding = false;
        for(const Layout::Qualifier &q: layout.qualifiers)
        {
                bool allowed = false;
@@ -58,7 +67,9 @@ void DeclarationValidator::visit(Layout &layout)
                        allowed = (variable && scope==GLOBAL);
                else if(q.name=="binding" || q.name=="set")
                {
-                       if(q.name=="set")
+                       binding = true;
+
+                       if(q.name=="set" && features.target_api!=VULKAN)
                        {
                                error(layout, "Layout qualifier 'set' not allowed when targeting OpenGL");
                                continue;
@@ -66,11 +77,9 @@ void DeclarationValidator::visit(Layout &layout)
 
                        if(variable)
                        {
-                               TypeDeclaration *type = variable->type_declaration;
-                               while(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(type))
-                                       type = basic->base_type;
+                               const TypeDeclaration *base_type = get_ultimate_base_type(variable->type_declaration);
                                bool uniform = (variable->interface=="uniform");
-                               allowed = (scope==GLOBAL && uniform && dynamic_cast<ImageTypeDeclaration *>(type));
+                               allowed = (scope==GLOBAL && uniform && dynamic_cast<const ImageTypeDeclaration *>(base_type));
                                err_descr = (uniform ? "variable of non-opaque type" : "non-uniform variable");
                        }
                        else if(iface_block)
@@ -141,6 +150,12 @@ void DeclarationValidator::visit(Layout &layout)
                                err_descr = "non-matrix variable";
                        }
                }
+               else if(q.name=="push_constant")
+               {
+                       push_constant = true;
+                       allowed = (iface_block && !variable && iface_block->interface=="uniform");
+                       value = false;
+               }
 
                if(!allowed)
                {
@@ -162,6 +177,9 @@ void DeclarationValidator::visit(Layout &layout)
                else if(!value && q.has_value)
                        error(layout, format("Layout qualifier '%s' does not allow a value", q.name));
        }
+
+       if(push_constant && binding)
+               error(layout, "Layout qualifier 'push_constant' not allowed together with 'binding' or 'set'");
 }
 
 void DeclarationValidator::visit(InterfaceLayout &layout)
@@ -236,6 +254,11 @@ void DeclarationValidator::visit(VariableDeclaration &var)
                        error(var, format("Mismatched interface qualifier '%s' inside '%s' block", var.interface, iface_block->interface));
                else if(scope==STRUCT || scope==FUNCTION)
                        error(var, format("Interface qualifier not allowed on %s", descr));
+               else if(scope==GLOBAL && variable->interface=="uniform" && features.target_api==VULKAN)
+               {
+                       if(!dynamic_cast<const ImageTypeDeclaration *>(get_ultimate_base_type(variable->type_declaration)))
+                               error(var, "Interface qualifier 'uniform' not allowed on non-opaque variable in global scope");
+               }
        }
 
        TypeDeclaration *type = var.type_declaration;