aboutsummaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/ast.h5
-rw-r--r--src/glsl/glsl_parser.yy127
-rw-r--r--src/glsl/glsl_parser_extras.cpp122
3 files changed, 128 insertions, 126 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 335f426d418..cca32b334b2 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 42108a3c1b6..7f00929d1e4 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 7d976c26f8c..67ef014c068 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -859,6 +859,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)