From 2d03f48a65a666ecdcfaffa3d39ad1b77f2b25b6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Apr 2012 13:35:56 -0700 Subject: [PATCH] glsl: Add parsing for GLSL uniform blocks. This doesn't do anything with the uniform block declarations yet, so usage of those uniforms finds them to be undeclared. Reviewed-by: Kenneth Graunke Reviewed-by: Ian Romanick --- src/glsl/ast.h | 28 +++++++++ src/glsl/ast_to_hir.cpp | 11 ++++ src/glsl/glsl_lexer.ll | 5 +- src/glsl/glsl_parser.yy | 122 ++++++++++++++++++++++++++++++++++++++++ 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 interpolation_qualifier %type layout_qualifier %type layout_qualifier_id_list layout_qualifier_id +%type uniform_block_layout_qualifier %type type_specifier %type type_specifier_no_prec %type type_specifier_nonarray @@ -213,11 +214,14 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %type declaration %type declaration_statement %type jump_statement +%type uniform_block %type struct_specifier %type struct_declaration_list %type struct_declaration %type struct_declarator %type struct_declarator_list +%type member_list +%type member_declaration %type selection_statement %type selection_rest_statement %type 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); + } + ; -- 2.30.2