diff options
-rw-r--r-- | src/glsl/glsl_parser.yy | 46 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.cpp | 20 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.h | 7 |
3 files changed, 70 insertions, 3 deletions
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 7f00929..028974e 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -169,6 +169,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER %type <identifier> any_identifier %type <interface_block> instance_name_opt +%type <interface_block> buffer_instance_name_opt %token <real> FLOATCONSTANT %token <dreal> DOUBLECONSTANT %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT @@ -218,6 +219,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %type <type_qualifier> subroutine_qualifier %type <subroutine_list> subroutine_type_list %type <type_qualifier> interface_qualifier +%type <type_qualifier> buffer_interface_qualifier %type <type_specifier> type_specifier %type <type_specifier> type_specifier_nonarray %type <array_specifier> array_specifier @@ -2638,6 +2640,17 @@ basic_interface_block: $$ = block; } + | buffer_interface_qualifier NEW_IDENTIFIER '{' member_list '}' buffer_instance_name_opt ';' + { + ast_interface_block *const block = $6; + + block->block_name = $2; + block->declarations.push_degenerate_list_at_head(& $4->link); + + _mesa_ast_process_interface_block(& @1, state, block, $1); + + $$ = block; + } ; interface_qualifier: @@ -2656,7 +2669,10 @@ interface_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.uniform = 1; } - | BUFFER + ; + +buffer_interface_qualifier: + BUFFER { memset(& $$, 0, sizeof($$)); $$.flags.q.buffer = 1; @@ -2683,6 +2699,26 @@ instance_name_opt: } ; +buffer_instance_name_opt: + /* empty */ + { + $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier, + NULL, NULL); + } + | NEW_IDENTIFIER + { + $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier, + $1, NULL); + $$->set_location(@1); + } + | NEW_IDENTIFIER array_specifier + { + $$ = new(state) ast_interface_block(*state->default_shader_storage_qualifier, + $1, $2); + $$->set_location_range(@1, @2); + } + ; + member_list: member_declaration { @@ -2729,6 +2765,14 @@ layout_defaults: $$ = NULL; } + | layout_qualifier BUFFER ';' + { + if (!state->default_shader_storage_qualifier->merge_qualifier(& @1, state, $1)) { + YYERROR; + } + $$ = NULL; + } + | layout_qualifier IN_TOK ';' { $$ = NULL; diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 67ef014..223596b 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -244,6 +244,11 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier->flags.q.column_major = 1; this->default_uniform_qualifier->is_default_qualifier = true; + this->default_shader_storage_qualifier = new(this) ast_type_qualifier(); + this->default_shader_storage_qualifier->flags.q.shared = 1; + this->default_shader_storage_qualifier->flags.q.column_major = 1; + this->default_shader_storage_qualifier->is_default_qualifier = true; + this->fs_uses_gl_fragcoord = false; this->fs_redeclares_gl_fragcoord = false; this->fs_origin_upper_left = false; @@ -865,7 +870,17 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, ast_interface_block *const block, const struct ast_type_qualifier q) { - if (q.flags.q.uniform) { + if (q.flags.q.buffer) { + if (!state->has_shader_storage_buffer_objects()) { + _mesa_glsl_error(locp, 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(locp, state, + "#version 430 / GL_ARB_shader_storage_buffer_object " + "required for defining shader storage blocks"); + } + } else if (q.flags.q.uniform) { if (!state->has_uniform_buffer_objects()) { _mesa_glsl_error(locp, state, "#version 140 / GL_ARB_uniform_buffer_object " @@ -909,7 +924,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, uint64_t interface_type_mask; struct ast_type_qualifier temp_type_qualifier; - /* Get a bitmask containing only the in/out/uniform + /* Get a bitmask containing only the in/out/uniform/buffer * flags, allowing us to ignore other irrelevant flags like * interpolation qualifiers. */ @@ -917,6 +932,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp, temp_type_qualifier.flags.q.uniform = true; temp_type_qualifier.flags.q.in = true; temp_type_qualifier.flags.q.out = true; + temp_type_qualifier.flags.q.buffer = true; interface_type_mask = temp_type_qualifier.flags.i; /* Get the block's interface qualifier. The interface_qualifier diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index d3b091d..5b757d3 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -275,6 +275,13 @@ struct _mesa_glsl_parse_state { struct ast_type_qualifier *default_uniform_qualifier; /** + * Default shader storage layout qualifiers tracked during parsing. + * Currently affects shader storage blocks and shader storage buffer + * variables in those blocks. + */ + struct ast_type_qualifier *default_shader_storage_qualifier; + + /** * Variables to track different cases if a fragment shader redeclares * built-in variable gl_FragCoord. * |