glsl parser: handle interface block member qualifier
authorJordan Justen <jordan.l.justen@intel.com>
Thu, 21 Mar 2013 17:52:19 +0000 (10:52 -0700)
committerJordan Justen <jordan.l.justen@intel.com>
Thu, 23 May 2013 16:37:11 +0000 (09:37 -0700)
An interface block member may specify the type:
in {
    in vec4 in_var_with_qualifier;
};

When specified with the member, it must match the same
type as interface block type.

It can also omit the qualifier:
uniform {
    vec4 uniform_var_without_qualifier;
};

When the type is not specified with the member,
it will adopt the same type as the interface block.

Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/glsl_parser.yy

index 70764d6dbf31d98e10c233425bab1d2cc74dbd54..baac84568cae00dfcc7c0d7559cfef3833e405ae 100644 (file)
@@ -1958,7 +1958,49 @@ basic_interface_block:
                        "an instance name are not allowed");
           }
 
-          block->layout.flags.i |= $1.flags.i;
+          unsigned 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).
+        */
+       unsigned block_interface_qualifier = $1.flags.i;
+
+          block->layout.flags.i |= block_interface_qualifier;
+
+          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\n");
+             }
+          }
 
           $$ = block;
        }