[Mesa-dev] [PATCH 05/18] glsl: Add parsing for GLSL uniform blocks.

Kenneth Graunke kenneth at whitecape.org
Tue Jul 3 15:37:12 PDT 2012


On 07/02/2012 05:38 PM, Eric Anholt wrote:
> This doesn't do anything with the uniform block declarations yet, so
> usage of those uniforms finds them to be undeclared.
> ---
>  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 7538b58..4438b85 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 15aa88e..bbe8f05 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 2028d7f..24cda0c 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 7024ee4..ccc1abb 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:
> @@ -1152,6 +1160,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);
> @@ -1204,6 +1229,38 @@ layout_qualifier_id:
>  				 "identifier `%s' used\n", $1);
>  	   }
>  	}
> +	| uniform_block_layout_qualifier
> +	{
> +	   $$ = $1;
> +	   /* Layout qualifiers for AMD/ARB_conservative_depth. */

Not actually ARB_conservative_depth here.  Maybe:
/* Layout qualifiers for UBOs. */

> +	   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;
> +	}
>  	;

If you wanted to, you could instead change the lexer's rules for
row_major and packed to check for the incorrect keyword, then return
IDENTIFIER rather than making an actual token.  But it seems like one
solution is as good as another, so what you have looks fine to me.

With the comment change, Patches 1-5 are:
Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>

>  interpolation_qualifier:
> @@ -1857,3 +1914,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);
> +	}
> +	;
> 




More information about the mesa-dev mailing list