From abcd1fa06f9fab27c5934b4069523dd009862b18 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 3 Sep 2022 14:33:43 +0300 Subject: [PATCH] Validate the presence of in/out layout qualifiers for geometry shaders 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 | 2 +- source/glsl/validate.cpp | 36 ++++++++++++++++++++++++ source/glsl/validate.h | 3 ++ tests/glsl/missing_geometry_layouts.glsl | 22 +++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/glsl/missing_geometry_layouts.glsl diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 99253fe0..e4830ec2 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -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) diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index d669b237..4c135892 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -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"); diff --git a/source/glsl/validate.h b/source/glsl/validate.h index c9a7b736..f5620435 100644 --- a/source/glsl/validate.h +++ b/source/glsl/validate.h @@ -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 index 00000000..b531e8ed --- /dev/null +++ b/tests/glsl/missing_geometry_layouts.glsl @@ -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: +:9: No primitive type qualifier found on input +:9: No primitive type qualifier found on output +:9: No vertex count qualifier found on output +*/ -- 2.43.0