]> git.tdb.fi Git - libs/gl.git/commitdiff
Validate the presence of in/out layout qualifiers for geometry shaders
authorMikko Rasa <tdb@tdb.fi>
Sat, 3 Sep 2022 11:33:43 +0000 (14:33 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 3 Sep 2022 12:39:57 +0000 (15:39 +0300)
Builtin arrays are now always autosized, even when the appropriate size
isn't known, because the error message from the missing size is confusing.

source/glsl/generate.cpp
source/glsl/validate.cpp
source/glsl/validate.h
tests/glsl/missing_geometry_layouts.glsl [new file with mode: 0644]

index 99253fe041463ce01a852f340b967cb744f33a50..e4830ec22aee2340aae79a93711600f415ef89a6 100644 (file)
@@ -350,7 +350,7 @@ void ArraySizer::apply(Stage &stage)
                                size = input_size;
                        else if(kvp.second>=0)
                                size = kvp.second+1;
-                       else if(!kvp.first->name.compare(0, 3, "gl_"))
+                       if(!size && !kvp.first->name.compare(0, 3, "gl_"))
                                size = 1;
 
                        if(size>0)
index d669b2370e08bbb9032d02d308a6377210dd0fa4..4c135892056c1e82b3c33ca0536232202a05ac69 100644 (file)
@@ -39,6 +39,27 @@ void DeclarationValidator::apply(Stage &s, const Features &f)
        stage = &s;
        features = f;
        s.content.visit(*this);
+
+       Node *global_err_node = 0;
+       auto i = s.functions.find("main()");
+       if(i!=s.functions.end())
+               global_err_node = i->second;
+       else
+       {
+               for(auto j=s.content.body.begin(); (!global_err_node && j!=s.content.body.end()); ++j)
+                       if((*j)->source>0)
+                               global_err_node = j->get();
+       }
+
+       if(s.type==Stage::GEOMETRY)
+       {
+               if(!have_input_primitive)
+                       error(*global_err_node, "No primitive type qualifier found on input");
+               if(!have_output_primitive)
+                       error(*global_err_node, "No primitive type qualifier found on output");
+               if(!have_output_vertex_count)
+                       error(*global_err_node, "No vertex count qualifier found on output");
+       }
 }
 
 const char *DeclarationValidator::describe_variable(ScopeType scope)
@@ -118,21 +139,36 @@ void DeclarationValidator::visit(Layout &layout)
                {
                        allowed = (stage->type==Stage::GEOMETRY && iface_layout && (iface_layout->interface=="in" || iface_layout->interface=="out"));
                        value = false;
+                       if(allowed)
+                       {
+                               if(iface_layout->interface=="in")
+                                       have_input_primitive = true;
+                               else if(iface_layout->interface=="out")
+                                       have_output_primitive = true;
+                       }
                }
                else if(q.name=="lines" || q.name=="lines_adjacency" || q.name=="triangles" || q.name=="triangles_adjacency")
                {
                        allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="in");
                        value = false;
+                       if(allowed)
+                               have_input_primitive = true;
                }
                else if(q.name=="line_strip" || q.name=="triangle_strip")
                {
                        allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="out");
                        value = false;
+                       if(allowed)
+                               have_output_primitive = true;
                }
                else if(q.name=="invocations")
                        allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="in");
                else if(q.name=="max_vertices")
+               {
                        allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="out");
+                       if(allowed)
+                               have_output_vertex_count = true;
+               }
                else if(q.name=="std140" || q.name=="std430")
                {
                        allowed = (iface_block && !variable && iface_block->interface=="uniform");
index c9a7b736035519e3d3767062e198cb22e5f8ba6b..f562043576e0b8db285b3a9d2a821c78977979c3 100644 (file)
@@ -44,6 +44,9 @@ private:
        InterfaceLayout *iface_layout = 0;
        VariableDeclaration *iface_block = 0;
        VariableDeclaration *variable = 0;
+       bool have_input_primitive = false;
+       bool have_output_primitive = false;
+       bool have_output_vertex_count = false;
 
 public:
        void apply(Stage &, const Features &);
diff --git a/tests/glsl/missing_geometry_layouts.glsl b/tests/glsl/missing_geometry_layouts.glsl
new file mode 100644 (file)
index 0000000..b531e8e
--- /dev/null
@@ -0,0 +1,22 @@
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+       gl_Position = position;
+}
+
+#pragma MSP stage(geometry)
+void main()
+{
+       for(int i=0; i<3; ++i)
+       {
+               passthrough[i];
+               EmitVertex();
+       }
+}
+
+/* Expected error:
+<test>:9: No primitive type qualifier found on input
+<test>:9: No primitive type qualifier found on output
+<test>:9: No vertex count qualifier found on output
+*/