summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/glsl_parser.yy46
-rw-r--r--src/glsl/glsl_parser_extras.cpp20
-rw-r--r--src/glsl/glsl_parser_extras.h7
3 files changed, 70 insertions, 3 deletions
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 7f00929d1e4..028974e7eb9 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 67ef014c068..223596be798 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 d3b091d9dce..5b757d3716f 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.
*