diff options
-rw-r--r-- | src/glsl/ast.h | 5 | ||||
-rw-r--r-- | src/glsl/glsl_parser.yy | 127 | ||||
-rw-r--r-- | 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 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) |