[Mesa-dev] [PATCH v5 23/70] glsl: refactor parser processing of an interface block definition

Iago Toral Quiroga itoral at igalia.com
Thu Sep 10 06:35:39 PDT 2015


From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>

---
 src/glsl/ast.h                  |   5 ++
 src/glsl/glsl_parser.yy         | 127 +---------------------------------------
 src/glsl/glsl_parser_extras.cpp | 122 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 128 insertions(+), 126 deletions(-)

diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 335f426..cca32b3 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -1172,4 +1172,9 @@ extern void
 check_builtin_array_max_size(const char *name, unsigned size,
                              YYLTYPE loc, struct _mesa_glsl_parse_state *state);
 
+extern void _mesa_ast_process_interface_block(YYLTYPE *locp,
+                                              _mesa_glsl_parse_state *state,
+                                              ast_interface_block *const block,
+                                              const struct ast_type_qualifier q);
+
 #endif /* AST_H */
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 42108a3..7f00929 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -2634,132 +2634,7 @@ basic_interface_block:
       block->block_name = $2;
       block->declarations.push_degenerate_list_at_head(& $4->link);
 
-      if ($1.flags.q.buffer) {
-         if (!state->has_shader_storage_buffer_objects()) {
-            _mesa_glsl_error(& @1, state,
-                             "#version 430 / GL_ARB_shader_storage_buffer_object "
-                             "required for defining shader storage blocks");
-         } else if (state->ARB_shader_storage_buffer_object_warn) {
-            _mesa_glsl_warning(& @1, state,
-                               "#version 430 / GL_ARB_shader_storage_buffer_object "
-                               "required for defining shader storage blocks");
-         }
-      } else if ($1.flags.q.uniform) {
-         if (!state->has_uniform_buffer_objects()) {
-            _mesa_glsl_error(& @1, state,
-                             "#version 140 / GL_ARB_uniform_buffer_object "
-                             "required for defining uniform blocks");
-         } else if (state->ARB_uniform_buffer_object_warn) {
-            _mesa_glsl_warning(& @1, state,
-                               "#version 140 / GL_ARB_uniform_buffer_object "
-                               "required for defining uniform blocks");
-         }
-      } else {
-         if (state->es_shader || state->language_version < 150) {
-            _mesa_glsl_error(& @1, state,
-                             "#version 150 required for using "
-                             "interface blocks");
-         }
-      }
-
-      /* From the GLSL 1.50.11 spec, section 4.3.7 ("Interface Blocks"):
-       * "It is illegal to have an input block in a vertex shader
-       *  or an output block in a fragment shader"
-       */
-      if ((state->stage == MESA_SHADER_VERTEX) && $1.flags.q.in) {
-         _mesa_glsl_error(& @1, state,
-                          "`in' interface block is not allowed for "
-                          "a vertex shader");
-      } else if ((state->stage == MESA_SHADER_FRAGMENT) && $1.flags.q.out) {
-         _mesa_glsl_error(& @1, state,
-                          "`out' interface block is not allowed for "
-                          "a fragment shader");
-      }
-
-      /* Since block arrays require names, and both features are added in
-       * the same language versions, we don't have to explicitly
-       * version-check both things.
-       */
-      if (block->instance_name != NULL) {
-         state->check_version(150, 300, & @1, "interface blocks with "
-                               "an instance name are not allowed");
-      }
-
-      uint64_t interface_type_mask;
-      struct ast_type_qualifier temp_type_qualifier;
-
-      /* Get a bitmask containing only the in/out/uniform/buffer
-       * flags, allowing us to ignore other irrelevant flags like
-       * interpolation qualifiers.
-       */
-      temp_type_qualifier.flags.i = 0;
-      temp_type_qualifier.flags.q.uniform = true;
-      temp_type_qualifier.flags.q.buffer = true;
-      temp_type_qualifier.flags.q.in = true;
-      temp_type_qualifier.flags.q.out = true;
-      interface_type_mask = temp_type_qualifier.flags.i;
-
-      /* Get the block's interface qualifier.  The interface_qualifier
-       * production rule guarantees that only one bit will be set (and
-       * it will be in/out/uniform).
-       */
-      uint64_t block_interface_qualifier = $1.flags.i;
-
-      block->layout.flags.i |= block_interface_qualifier;
-
-      if (state->stage == MESA_SHADER_GEOMETRY &&
-          state->has_explicit_attrib_stream()) {
-         /* Assign global layout's stream value. */
-         block->layout.flags.q.stream = 1;
-         block->layout.flags.q.explicit_stream = 0;
-         block->layout.stream = state->out_qualifier->stream;
-      }
-
-      foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
-         ast_type_qualifier& qualifier = member->type->qualifier;
-         if ((qualifier.flags.i & interface_type_mask) == 0) {
-            /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
-             * "If no optional qualifier is used in a member declaration, the
-             *  qualifier of the variable is just in, out, or uniform as declared
-             *  by interface-qualifier."
-             */
-            qualifier.flags.i |= block_interface_qualifier;
-         } else if ((qualifier.flags.i & interface_type_mask) !=
-                    block_interface_qualifier) {
-            /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
-             * "If optional qualifiers are used, they can include interpolation
-             *  and storage qualifiers and they must declare an input, output,
-             *  or uniform variable consistent with the interface qualifier of
-             *  the block."
-             */
-            _mesa_glsl_error(& @1, state,
-                             "uniform/in/out qualifier on "
-                             "interface block member does not match "
-                             "the interface block");
-         }
-
-         /* From GLSL ES 3.0, chapter 4.3.7 "Interface Blocks":
-          *
-          * "GLSL ES 3.0 does not support interface blocks for shader inputs or
-          * outputs."
-          *
-          * And from GLSL ES 3.0, chapter 4.6.1 "The invariant qualifier":.
-          *
-          * "Only variables output from a shader can be candidates for
-          * invariance."
-          *
-          * From GLSL 4.40 and GLSL 1.50, section "Interface Blocks":
-          *
-          * "If optional qualifiers are used, they can include interpolation
-          * qualifiers, auxiliary storage qualifiers, and storage qualifiers
-          * and they must declare an input, output, or uniform member
-          * consistent with the interface qualifier of the block"
-          */
-         if (qualifier.flags.q.invariant)
-            _mesa_glsl_error(&@1, state,
-                             "invariant qualifiers cannot be used "
-                             "with interface blocks members");
-      }
+      _mesa_ast_process_interface_block(& @1, state, block, $1);
 
       $$ = block;
    }
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 20bbe6e..0a3f745 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -858,6 +858,128 @@ _mesa_ast_set_aggregate_type(const glsl_type *type,
    }
 }
 
+void
+_mesa_ast_process_interface_block(YYLTYPE *locp,
+                                  _mesa_glsl_parse_state *state,
+                                  ast_interface_block *const block,
+                                  const struct ast_type_qualifier q)
+{
+   if (q.flags.q.uniform) {
+      if (!state->has_uniform_buffer_objects()) {
+         _mesa_glsl_error(locp, state,
+                          "#version 140 / GL_ARB_uniform_buffer_object "
+                          "required for defining uniform blocks");
+      } else if (state->ARB_uniform_buffer_object_warn) {
+         _mesa_glsl_warning(locp, state,
+                            "#version 140 / GL_ARB_uniform_buffer_object "
+                            "required for defining uniform blocks");
+      }
+   } else {
+      if (state->es_shader || state->language_version < 150) {
+         _mesa_glsl_error(locp, state,
+                          "#version 150 required for using "
+                          "interface blocks");
+      }
+   }
+
+   /* From the GLSL 1.50.11 spec, section 4.3.7 ("Interface Blocks"):
+    * "It is illegal to have an input block in a vertex shader
+    *  or an output block in a fragment shader"
+    */
+   if ((state->stage == MESA_SHADER_VERTEX) && q.flags.q.in) {
+      _mesa_glsl_error(locp, state,
+                       "`in' interface block is not allowed for "
+                       "a vertex shader");
+   } else if ((state->stage == MESA_SHADER_FRAGMENT) && q.flags.q.out) {
+      _mesa_glsl_error(locp, state,
+                       "`out' interface block is not allowed for "
+                       "a fragment shader");
+   }
+
+   /* Since block arrays require names, and both features are added in
+    * the same language versions, we don't have to explicitly
+    * version-check both things.
+    */
+   if (block->instance_name != NULL) {
+      state->check_version(150, 300, locp, "interface blocks with "
+                           "an instance name are not allowed");
+   }
+
+   uint64_t interface_type_mask;
+   struct ast_type_qualifier temp_type_qualifier;
+
+   /* Get a bitmask containing only the in/out/uniform
+    * flags, allowing us to ignore other irrelevant flags like
+    * interpolation qualifiers.
+    */
+   temp_type_qualifier.flags.i = 0;
+   temp_type_qualifier.flags.q.uniform = true;
+   temp_type_qualifier.flags.q.in = true;
+   temp_type_qualifier.flags.q.out = true;
+   interface_type_mask = temp_type_qualifier.flags.i;
+
+   /* Get the block's interface qualifier.  The interface_qualifier
+    * production rule guarantees that only one bit will be set (and
+    * it will be in/out/uniform).
+    */
+   uint64_t block_interface_qualifier = q.flags.i;
+
+   block->layout.flags.i |= block_interface_qualifier;
+
+   if (state->stage == MESA_SHADER_GEOMETRY &&
+       state->has_explicit_attrib_stream()) {
+      /* Assign global layout's stream value. */
+      block->layout.flags.q.stream = 1;
+      block->layout.flags.q.explicit_stream = 0;
+      block->layout.stream = state->out_qualifier->stream;
+   }
+
+   foreach_list_typed (ast_declarator_list, member, link, &block->declarations) {
+      ast_type_qualifier& qualifier = member->type->qualifier;
+      if ((qualifier.flags.i & interface_type_mask) == 0) {
+         /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
+          * "If no optional qualifier is used in a member declaration, the
+          *  qualifier of the variable is just in, out, or uniform as declared
+          *  by interface-qualifier."
+          */
+         qualifier.flags.i |= block_interface_qualifier;
+      } else if ((qualifier.flags.i & interface_type_mask) !=
+                 block_interface_qualifier) {
+         /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks):
+          * "If optional qualifiers are used, they can include interpolation
+          *  and storage qualifiers and they must declare an input, output,
+          *  or uniform variable consistent with the interface qualifier of
+          *  the block."
+          */
+         _mesa_glsl_error(locp, state,
+                          "uniform/in/out qualifier on "
+                          "interface block member does not match "
+                          "the interface block");
+      }
+
+      /* From GLSL ES 3.0, chapter 4.3.7 "Interface Blocks":
+       *
+       * "GLSL ES 3.0 does not support interface blocks for shader inputs or
+       * outputs."
+       *
+       * And from GLSL ES 3.0, chapter 4.6.1 "The invariant qualifier":.
+       *
+       * "Only variables output from a shader can be candidates for
+       * invariance."
+       *
+       * From GLSL 4.40 and GLSL 1.50, section "Interface Blocks":
+       *
+       * "If optional qualifiers are used, they can include interpolation
+       * qualifiers, auxiliary storage qualifiers, and storage qualifiers
+       * and they must declare an input, output, or uniform member
+       * consistent with the interface qualifier of the block"
+       */
+      if (qualifier.flags.q.invariant)
+         _mesa_glsl_error(locp, state,
+                          "invariant qualifiers cannot be used "
+                          "with interface blocks members");
+   }
+}
 
 void
 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
-- 
1.9.1



More information about the mesa-dev mailing list