summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTimothy Arceri <[email protected]>2016-01-18 17:06:57 +1100
committerTimothy Arceri <[email protected]>2016-01-20 08:06:45 +1100
commit564009986ff1485c467664542a9042e6ce4dcdfe (patch)
treed9ced4f72b47da1d1319b70d6219025122fff124 /src
parenta0a93470e3413d5a5890d988462bb898362bd68f (diff)
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 <[email protected]> Reviewed-by: Chris Forbes <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/glsl/ast.h4
-rw-r--r--src/glsl/ast_type.cpp18
-rw-r--r--src/glsl/glsl_parser.yy66
3 files changed, 73 insertions, 15 deletions
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;
}
;