From: Timothy Arceri Date: Mon, 18 Jan 2016 06:06:57 +0000 (+1100) Subject: glsl: update parser to allow duplicate default layout qualifiers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=564009986ff1485c467664542a9042e6ce4dcdfe;p=mesa.git glsl: update parser to allow duplicate default layout qualifiers In order to only create a single node for each default declaration we add a new boolean parameter to the in/out merge function to only create one once we reach the rightmost layout qualifier. From the ARB_shading_language_420pack spec: "More than one layout qualifier may appear in a single declaration. If the same layout-qualifier-name occurs in multiple layout qualifiers for the same declaration, the last one overrides the former ones." Acked-by: Matt Turner Reviewed-by: Chris Forbes --- diff --git a/src/glsl/ast.h b/src/glsl/ast.h index f8ab0b71b7b..465166994ea 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -704,12 +704,12 @@ struct ast_type_qualifier { bool merge_out_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, const ast_type_qualifier &q, - ast_node* &node); + ast_node* &node, bool create_node); bool merge_in_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, const ast_type_qualifier &q, - ast_node* &node); + ast_node* &node, bool create_node); ast_subroutine_list *subroutine_list; }; diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp index e59d1b2754b..32cb0a0319c 100644 --- a/src/glsl/ast_type.cpp +++ b/src/glsl/ast_type.cpp @@ -291,7 +291,7 @@ bool ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, const ast_type_qualifier &q, - ast_node* &node) + ast_node* &node, bool create_node) { void *mem_ctx = state; const bool r = this->merge_qualifier(loc, state, q); @@ -314,7 +314,9 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc, /* Allow future assigments of global out's stream id value */ this->flags.q.explicit_stream = 0; } else if (state->stage == MESA_SHADER_TESS_CTRL) { - node = new(mem_ctx) ast_tcs_output_layout(*loc); + if (create_node) { + node = new(mem_ctx) ast_tcs_output_layout(*loc); + } } else { _mesa_glsl_error(loc, state, "out layout qualifiers only valid in " "tessellation control or geometry shaders"); @@ -327,7 +329,7 @@ bool ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state, const ast_type_qualifier &q, - ast_node* &node) + ast_node* &node, bool create_node) { void *mem_ctx = state; bool create_gs_ast = false; @@ -467,10 +469,12 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, this->point_mode = q.point_mode; } - if (create_gs_ast) { - node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); - } else if (create_cs_ast) { - node = new(mem_ctx) ast_cs_input_layout(*loc, q.local_size); + if (create_node) { + if (create_gs_ast) { + node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); + } else if (create_cs_ast) { + node = new(mem_ctx) ast_cs_input_layout(*loc, q.local_size); + } } return true; diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 925cb820ba9..6099aeb12ca 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -2742,7 +2742,20 @@ member_declaration: ; layout_uniform_defaults: - layout_qualifier UNIFORM ';' + layout_qualifier layout_uniform_defaults + { + $$ = NULL; + if (!state->has_420pack_or_es31()) { + _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers"); + YYERROR; + } else { + if (!state->default_uniform_qualifier-> + merge_qualifier(& @1, state, $1)) { + YYERROR; + } + } + } + | layout_qualifier UNIFORM ';' { if (!state->default_uniform_qualifier->merge_qualifier(& @1, state, $1)) { YYERROR; @@ -2752,7 +2765,20 @@ layout_uniform_defaults: ; layout_buffer_defaults: - layout_qualifier BUFFER ';' + layout_qualifier layout_buffer_defaults + { + $$ = NULL; + if (!state->has_420pack_or_es31()) { + _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers"); + YYERROR; + } else { + if (!state->default_shader_storage_qualifier-> + merge_qualifier(& @1, state, $1)) { + YYERROR; + } + } + } + | layout_qualifier BUFFER ';' { if (!state->default_shader_storage_qualifier->merge_qualifier(& @1, state, $1)) { YYERROR; @@ -2773,20 +2799,48 @@ layout_buffer_defaults: ; layout_in_defaults: - layout_qualifier IN_TOK ';' + layout_qualifier layout_in_defaults { $$ = NULL; - if (!state->in_qualifier->merge_in_qualifier(& @1, state, $1, $$)) { + if (!state->has_420pack_or_es31()) { + _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers"); + YYERROR; + } else { + if (!state->in_qualifier-> + merge_in_qualifier(& @1, state, $1, $$, false)) { + YYERROR; + } + } + } + | layout_qualifier IN_TOK ';' + { + $$ = NULL; + if (!state->in_qualifier-> + merge_in_qualifier(& @1, state, $1, $$, true)) { YYERROR; } } ; layout_out_defaults: - layout_qualifier OUT_TOK ';' + layout_qualifier layout_out_defaults + { + $$ = NULL; + if (!state->has_420pack_or_es31()) { + _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers"); + YYERROR; + } else { + if (!state->out_qualifier-> + merge_out_qualifier(& @1, state, $1, $$, false)) { + YYERROR; + } + } + } + | layout_qualifier OUT_TOK ';' { $$ = NULL; - if (!state->out_qualifier->merge_out_qualifier(& @1, state, $1, $$)) + if (!state->out_qualifier-> + merge_out_qualifier(& @1, state, $1, $$, true)) YYERROR; } ;