%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
%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
$$ = 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:
memset(& $$, 0, sizeof($$));
$$.flags.q.uniform = 1;
}
- | BUFFER
+ ;
+
+buffer_interface_qualifier:
+ BUFFER
{
memset(& $$, 0, sizeof($$));
$$.flags.q.buffer = 1;
}
;
+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
{
$$ = NULL;
}
+ | layout_qualifier BUFFER ';'
+ {
+ if (!state->default_shader_storage_qualifier->merge_qualifier(& @1, state, $1)) {
+ YYERROR;
+ }
+ $$ = NULL;
+ }
+
| layout_qualifier IN_TOK ';'
{
$$ = NULL;
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;
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 "
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.
*/
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
*/
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.