summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ast.h28
-rw-r--r--src/glsl/ast_to_hir.cpp11
-rw-r--r--src/glsl/glsl_lexer.ll5
-rw-r--r--src/glsl/glsl_parser.yy122
4 files changed, 164 insertions, 2 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 7538b58e460..4438b85bbda 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -376,6 +376,15 @@ struct ast_type_qualifier {
unsigned depth_less:1;
unsigned depth_unchanged:1;
/** \} */
+
+ /** \name Layout qualifiers for GL_ARB_uniform_buffer_object */
+ /** \{ */
+ unsigned std140:1;
+ unsigned shared:1;
+ unsigned packed:1;
+ unsigned column_major:1;
+ unsigned row_major:1;
+ /** \} */
}
/** \brief Set of flags, accessed by name. */
q;
@@ -762,6 +771,25 @@ public:
ast_function *prototype;
ast_compound_statement *body;
};
+
+class ast_uniform_block : public ast_node {
+public:
+ ast_uniform_block(ast_type_qualifier layout,
+ const char *block_name,
+ ast_declarator_list *member_list)
+ : layout(layout), block_name(block_name)
+ {
+ declarations.push_degenerate_list_at_head(&member_list->link);
+ }
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_type_qualifier layout;
+ const char *block_name;
+ /** List of ast_declarator_list * */
+ exec_list declarations;
+};
/*@}*/
extern void
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 15aa88ea9ef..bbe8f0596f9 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -3989,6 +3989,17 @@ ast_struct_specifier::hir(exec_list *instructions,
return NULL;
}
+ir_rvalue *
+ast_uniform_block::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ /* The ast_uniform_block has a list of ast_declarator_lists. We
+ * need to turn those into ir_variables with an association
+ * with this uniform block.
+ */
+ return NULL;
+}
+
static void
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
exec_list *instructions)
diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
index 2028d7f4768..24cda0c45ea 100644
--- a/src/glsl/glsl_lexer.ll
+++ b/src/glsl/glsl_lexer.ll
@@ -312,6 +312,7 @@ layout {
|| yyextra->AMD_conservative_depth_enable
|| yyextra->ARB_conservative_depth_enable
|| yyextra->ARB_explicit_attrib_location_enable
+ || yyextra->ARB_uniform_buffer_object_enable
|| yyextra->ARB_fragment_coord_conventions_enable) {
return LAYOUT_TOK;
} else {
@@ -392,7 +393,7 @@ enum KEYWORD(110 || ES, 999, ENUM);
typedef KEYWORD(110 || ES, 999, TYPEDEF);
template KEYWORD(110 || ES, 999, TEMPLATE);
this KEYWORD(110 || ES, 999, THIS);
-packed KEYWORD(110 || ES, 999, PACKED_TOK);
+packed KEYWORD(110 || ES, 140 || yyextra->ARB_uniform_buffer_object_enable, PACKED_TOK);
goto KEYWORD(110 || ES, 999, GOTO);
switch KEYWORD(110 || ES, 130, SWITCH);
default KEYWORD(110 || ES, 130, DEFAULT);
@@ -468,7 +469,7 @@ image2DArrayShadow KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
imageBuffer KEYWORD(130, 999, IMAGEBUFFER);
iimageBuffer KEYWORD(130, 999, IIMAGEBUFFER);
uimageBuffer KEYWORD(130, 999, UIMAGEBUFFER);
-row_major KEYWORD(130, 999, ROW_MAJOR);
+row_major KEYWORD(130, 140 || yyextra->ARB_uniform_buffer_object_enable, ROW_MAJOR);
/* Additional reserved words in GLSL 1.40 */
isampler2DRect KEYWORD(140, 140, ISAMPLER2DRECT);
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 8759863271e..3373375911b 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -155,6 +155,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
%type <type_qualifier> interpolation_qualifier
%type <type_qualifier> layout_qualifier
%type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
+%type <type_qualifier> uniform_block_layout_qualifier
%type <type_specifier> type_specifier
%type <type_specifier> type_specifier_no_prec
%type <type_specifier> type_specifier_nonarray
@@ -213,11 +214,14 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
%type <node> declaration
%type <node> declaration_statement
%type <node> jump_statement
+%type <node> uniform_block
%type <struct_specifier> struct_specifier
%type <declarator_list> struct_declaration_list
%type <declarator_list> struct_declaration
%type <declaration> struct_declarator
%type <declaration> struct_declarator_list
+%type <declarator_list> member_list
+%type <declarator_list> member_declaration
%type <node> selection_statement
%type <selection_rest_statement> selection_rest_statement
%type <node> switch_statement
@@ -800,6 +804,10 @@ declaration:
$3->is_precision_statement = true;
$$ = $3;
}
+ | uniform_block
+ {
+ $$ = $1;
+ }
;
function_prototype:
@@ -1157,6 +1165,23 @@ layout_qualifier_id:
}
}
+ /* See also uniform_block_layout_qualifier. */
+ if (!$$.flags.i && state->ARB_uniform_buffer_object_enable) {
+ if (strcmp($1, "std140") == 0) {
+ $$.flags.q.std140 = 1;
+ } else if (strcmp($1, "shared") == 0) {
+ $$.flags.q.shared = 1;
+ } else if (strcmp($1, "column_major") == 0) {
+ $$.flags.q.column_major = 1;
+ }
+
+ if ($$.flags.i && state->ARB_uniform_buffer_object_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "layout qualifier `%s' is used\n", $1);
+ }
+ }
+
if (!$$.flags.i) {
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
"`%s'\n", $1);
@@ -1209,6 +1234,38 @@ layout_qualifier_id:
"identifier `%s' used\n", $1);
}
}
+ | uniform_block_layout_qualifier
+ {
+ $$ = $1;
+ /* Layout qualifiers for ARB_uniform_buffer_object. */
+ if (!state->ARB_uniform_buffer_object_enable) {
+ _mesa_glsl_error(& @1, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "layout qualifier `%s' is used\n", $1);
+ } else if (state->ARB_uniform_buffer_object_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "layout qualifier `%s' is used\n", $1);
+ }
+ }
+ ;
+
+/* This is a separate language rule because we parse these as tokens
+ * (due to them being reserved keywords) instead of identifiers like
+ * most qualifiers. See the any_identifier path of
+ * layout_qualifier_id for the others.
+ */
+uniform_block_layout_qualifier:
+ ROW_MAJOR
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.row_major = 1;
+ }
+ | PACKED_TOK
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.packed = 1;
+ }
;
interpolation_qualifier:
@@ -1862,3 +1919,68 @@ function_definition:
state->symbols->pop_scope();
}
;
+
+/* layout_qualifieropt is packed into this rule */
+uniform_block:
+ UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
+ {
+ void *ctx = state;
+ ast_type_qualifier no_qual;
+ memset(&no_qual, 0, sizeof(no_qual));
+ $$ = new(ctx) ast_uniform_block(no_qual, $2, $4);
+ }
+ | layout_qualifier UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_uniform_block($1, $3, $5);
+ }
+ ;
+
+member_list:
+ member_declaration
+ {
+ $$ = $1;
+ $1->link.self_link();
+ }
+ | member_declaration member_list
+ {
+ $$ = $1;
+ $2->link.insert_before(& $$->link);
+ }
+ ;
+
+/* Specifying "uniform" inside of a uniform block is redundant. */
+uniformopt:
+ /* nothing */
+ | UNIFORM
+ ;
+
+member_declaration:
+ layout_qualifier uniformopt type_specifier struct_declarator_list ';'
+ {
+ void *ctx = state;
+ ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+ type->set_location(yylloc);
+
+ type->qualifier = $1;
+ type->qualifier.flags.q.uniform = true;
+ type->specifier = $3;
+ $$ = new(ctx) ast_declarator_list(type);
+ $$->set_location(yylloc);
+
+ $$->declarations.push_degenerate_list_at_head(& $4->link);
+ }
+ | uniformopt type_specifier struct_declarator_list ';'
+ {
+ void *ctx = state;
+ ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+ type->set_location(yylloc);
+
+ type->qualifier.flags.q.uniform = true;
+ type->specifier = $2;
+ $$ = new(ctx) ast_declarator_list(type);
+ $$->set_location(yylloc);
+
+ $$->declarations.push_degenerate_list_at_head(& $3->link);
+ }
+ ;