X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fglsl_parser.yy;h=78f5bf6f4f2038e318e09f2b27a9c4713136b278;hb=b2265db8e77b531e380c47bb5bf31a3c0aa36e08;hp=9ad67e27881923fab914bab74177288184b0fcd2;hpb=60a784d56e0034d32b9c243afd860cf095d3d2c5;p=mesa.git diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 9ad67e27881..78f5bf6f4f2 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -29,6 +29,7 @@ #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_types.h" +#include "main/context.h" #define YYLEX_PARAM state->scanner @@ -78,6 +79,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) ast_case_label_list *case_label_list; ast_case_statement *case_statement; ast_case_statement_list *case_statement_list; + ast_interface_block *interface_block; struct { ast_node *cond; @@ -100,15 +102,20 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %token MAT4X2 MAT4X3 MAT4X4 %token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW %token SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW -%token SAMPLER2DARRAYSHADOW ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE -%token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D -%token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY +%token SAMPLER2DARRAYSHADOW SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW +%token ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE +%token ISAMPLER1DARRAY ISAMPLER2DARRAY ISAMPLERCUBEARRAY +%token USAMPLER1D USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER1DARRAY +%token USAMPLER2DARRAY USAMPLERCUBEARRAY %token SAMPLER2DRECT ISAMPLER2DRECT USAMPLER2DRECT SAMPLER2DRECTSHADOW %token SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER +%token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS +%token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY %token SAMPLEREXTERNALOES %token STRUCT VOID_TOK WHILE %token IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER %type any_identifier +%type instance_name_opt %token FLOATCONSTANT %token INTCONSTANT UINTCONSTANT BOOLCONSTANT %token FIELD_SELECTION @@ -134,6 +141,8 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4 %token SAMPLER3DRECT %token SIZEOF CAST NAMESPACE USING +%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE ATOMIC_UINT PATCH SAMPLE +%token SUBROUTINE %token ERROR_TOK @@ -155,6 +164,8 @@ 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 interface_block_layout_qualifier +%type interface_qualifier %type type_specifier %type type_specifier_no_prec %type type_specifier_nonarray @@ -210,14 +221,19 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %type init_declarator_list %type single_declaration %type initializer +%type initializer_list %type declaration %type declaration_statement %type jump_statement +%type interface_block +%type basic_interface_block %type struct_specifier -%type struct_declaration_list +%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 @@ -231,6 +247,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %type conditionopt %type for_init_statement %type for_rest_statement +%type integer_constant %% translation_unit: @@ -250,44 +267,18 @@ version_statement: /* blank - no #version specified: defaults are already set */ | VERSION_TOK INTCONSTANT EOL { - bool supported = false; - - switch ($2) { - case 100: - state->es_shader = true; - supported = state->Const.GLSL_100ES; - break; - case 110: - supported = state->Const.GLSL_110; - break; - case 120: - supported = state->Const.GLSL_120; - break; - case 130: - supported = state->Const.GLSL_130; - break; - case 140: - supported = state->Const.GLSL_140; - break; - default: - supported = false; - break; - } - - state->language_version = $2; - state->version_string = - ralloc_asprintf(state, "GLSL%s %d.%02d", - state->es_shader ? " ES" : "", - state->language_version / 100, - state->language_version % 100); - - if (!supported) { - _mesa_glsl_error(& @2, state, "%s is not supported. " - "Supported versions are: %s\n", - state->version_string, - state->supported_version_string); + state->process_version_directive(&@2, $2, NULL); + if (state->error) { + YYERROR; } } + | VERSION_TOK INTCONSTANT any_identifier EOL + { + state->process_version_directive(&@2, $2, $3); + if (state->error) { + YYERROR; + } + } ; pragma_statement: @@ -297,10 +288,11 @@ pragma_statement: | PRAGMA_OPTIMIZE_OFF EOL | PRAGMA_INVARIANT_ALL EOL { - if (state->language_version < 120) { + if (!state->is_version(120, 100)) { _mesa_glsl_warning(& @1, state, - "pragma `invariant(all)' not supported in %s", - state->version_string); + "pragma `invariant(all)' not supported in %s " + "(GLSL ES 1.00 or GLSL 1.20 required).", + state->get_version_string()); } else { state->all_invariant = true; } @@ -800,6 +792,10 @@ declaration: $3->is_precision_statement = true; $$ = $3; } + | interface_block + { + $$ = $1; + } ; function_prototype: @@ -966,6 +962,11 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($7->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, NULL); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer { @@ -976,6 +977,11 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($8->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$8; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, $5); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | init_declarator_list ',' any_identifier '=' initializer { @@ -986,6 +992,10 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($5->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$5; + _mesa_ast_set_aggregate_type($1->type->specifier, ai, state); + } } ; @@ -1033,6 +1043,11 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($6->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$6; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, NULL); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | fully_specified_type any_identifier '[' constant_expression ']' '=' initializer { @@ -1042,6 +1057,11 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($7->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, $4); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | fully_specified_type any_identifier '=' initializer { @@ -1051,6 +1071,9 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($4->oper == ast_aggregate) { + _mesa_ast_set_aggregate_type($1->specifier, $4, state); + } } | INVARIANT variable_identifier // Vertex only. { @@ -1094,28 +1117,18 @@ layout_qualifier_id_list: layout_qualifier_id | layout_qualifier_id_list ',' layout_qualifier_id { - if (($1.flags.i & $3.flags.i) != 0) { - _mesa_glsl_error(& @3, state, - "duplicate layout qualifiers used\n"); + $$ = $1; + if (!$$.merge_qualifier(& @3, state, $3)) { YYERROR; } - - $$.flags.i = $1.flags.i | $3.flags.i; - - if ($1.flags.q.explicit_location) - $$.location = $1.location; - - if ($1.flags.q.explicit_index) - $$.index = $1.index; - - if ($3.flags.q.explicit_location) - $$.location = $3.location; - - if ($3.flags.q.explicit_index) - $$.index = $3.index; } ; +integer_constant: + INTCONSTANT { $$ = $1; } + | UINTCONSTANT { $$ = $1; } + ; + layout_qualifier_id: any_identifier { @@ -1162,20 +1175,42 @@ layout_qualifier_id: } } + /* See also interface_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; + /* "row_major" is a reserved word in GLSL 1.30+. Its token is parsed + * below in the interface_block_layout_qualifier rule. + * + * It is not a reserved word in GLSL ES 3.00, so it's handled here as + * an identifier. + */ + } else if (strcmp($1, "row_major") == 0) { + $$.flags.q.row_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); YYERROR; } } - | any_identifier '=' INTCONSTANT + | any_identifier '=' integer_constant { memset(& $$, 0, sizeof($$)); if (state->ARB_explicit_attrib_location_enable) { - /* FINISHME: Handle 'index' once GL_ARB_blend_func_exteneded and - * FINISHME: GLSL 1.30 (or later) are supported. - */ if (strcmp("location", $1) == 0) { $$.flags.q.explicit_location = 1; @@ -1214,6 +1249,38 @@ layout_qualifier_id: "identifier `%s' used\n", $1); } } + | interface_block_layout_qualifier + { + $$ = $1; + /* Layout qualifiers for ARB_uniform_buffer_object. */ + if ($$.flags.q.uniform && !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 ($$.flags.q.uniform && 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. + */ +interface_block_layout_qualifier: + ROW_MAJOR + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.row_major = 1; + } + | PACKED_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.packed = 1; + } ; interpolation_qualifier: @@ -1414,6 +1481,8 @@ basic_type_specifier_nonarray: | SAMPLER1DARRAYSHADOW { $$ = "sampler1DArrayShadow"; } | SAMPLER2DARRAYSHADOW { $$ = "sampler2DArrayShadow"; } | SAMPLERBUFFER { $$ = "samplerBuffer"; } + | SAMPLERCUBEARRAY { $$ = "samplerCubeArray"; } + | SAMPLERCUBEARRAYSHADOW { $$ = "samplerCubeArrayShadow"; } | ISAMPLER1D { $$ = "isampler1D"; } | ISAMPLER2D { $$ = "isampler2D"; } | ISAMPLER2DRECT { $$ = "isampler2DRect"; } @@ -1422,6 +1491,7 @@ basic_type_specifier_nonarray: | ISAMPLER1DARRAY { $$ = "isampler1DArray"; } | ISAMPLER2DARRAY { $$ = "isampler2DArray"; } | ISAMPLERBUFFER { $$ = "isamplerBuffer"; } + | ISAMPLERCUBEARRAY { $$ = "isamplerCubeArray"; } | USAMPLER1D { $$ = "usampler1D"; } | USAMPLER2D { $$ = "usampler2D"; } | USAMPLER2DRECT { $$ = "usampler2DRect"; } @@ -1430,36 +1500,28 @@ basic_type_specifier_nonarray: | USAMPLER1DARRAY { $$ = "usampler1DArray"; } | USAMPLER2DARRAY { $$ = "usampler2DArray"; } | USAMPLERBUFFER { $$ = "usamplerBuffer"; } + | USAMPLERCUBEARRAY { $$ = "usamplerCubeArray"; } + | SAMPLER2DMS { $$ = "sampler2DMS"; } + | ISAMPLER2DMS { $$ = "isampler2DMS"; } + | USAMPLER2DMS { $$ = "usampler2DMS"; } + | SAMPLER2DMSARRAY { $$ = "sampler2DMSArray"; } + | ISAMPLER2DMSARRAY { $$ = "isampler2DMSArray"; } + | USAMPLER2DMSARRAY { $$ = "usampler2DMSArray"; } ; precision_qualifier: HIGHP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_high; } | MEDIUMP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_medium; } | LOWP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_low; } @@ -1472,6 +1534,7 @@ struct_specifier: $$ = new(ctx) ast_struct_specifier($2, $4); $$->set_location(yylloc); state->symbols->add_type($2, glsl_type::void_type); + state->symbols->add_type_ast($2, new(ctx) ast_type_specifier($$)); } | STRUCT '{' struct_declaration_list '}' { @@ -1484,12 +1547,12 @@ struct_specifier: struct_declaration_list: struct_declaration { - $$ = (ast_node *) $1; + $$ = $1; $1->link.self_link(); } | struct_declaration_list struct_declaration { - $$ = (ast_node *) $1; + $$ = $1; $$->link.insert_before(& $2->link); } ; @@ -1528,7 +1591,6 @@ struct_declarator: void *ctx = state; $$ = new(ctx) ast_declaration($1, false, NULL, NULL); $$->set_location(yylloc); - state->symbols->add_variable(new(state) ir_variable(NULL, $1, ir_var_auto)); } | any_identifier '[' constant_expression ']' { @@ -1540,6 +1602,28 @@ struct_declarator: initializer: assignment_expression + | '{' initializer_list '}' + { + $$ = $2; + } + | '{' initializer_list ',' '}' + { + $$ = $2; + } + ; + +initializer_list: + initializer + { + void *ctx = state; + $$ = new(ctx) ast_aggregate_initializer(); + $$->set_location(yylloc); + $$->expressions.push_tail(& $1->link); + } + | initializer_list ',' initializer + { + $1->expressions.push_tail(& $3->link); + } ; declaration_statement: @@ -1853,6 +1937,7 @@ external_declaration: function_definition { $$ = $1; } | declaration { $$ = $1; } | pragma_statement { $$ = NULL; } + | layout_defaults { $$ = NULL; } ; function_definition: @@ -1867,3 +1952,211 @@ function_definition: state->symbols->pop_scope(); } ; + +/* layout_qualifieropt is packed into this rule */ +interface_block: + basic_interface_block + { + $$ = $1; + } + | layout_qualifier basic_interface_block + { + ast_interface_block *block = $2; + if (!block->layout.merge_qualifier(& @1, state, $1)) { + YYERROR; + } + $$ = block; + } + ; + +basic_interface_block: + interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';' + { + ast_interface_block *const block = $6; + + block->block_name = $2; + block->declarations.push_degenerate_list_at_head(& $4->link); + + if ($1.flags.q.uniform) { + if (!state->ARB_uniform_buffer_object_enable) { + _mesa_glsl_error(& @1, state, + "#version 140 / GL_ARB_uniform_buffer_object " + "required for defining uniform blocks\n"); + } else if (state->ARB_uniform_buffer_object_warn) { + _mesa_glsl_warning(& @1, state, + "#version 140 / GL_ARB_uniform_buffer_object " + "required for defining uniform blocks\n"); + } + } else { + if (state->es_shader || state->language_version < 150) { + _mesa_glsl_error(& @1, state, + "#version 150 required for using " + "interface blocks.\n"); + } + } + + /* From the GLSL 1.50.11 spec, section 4.3.7 ("Interface Blocks"): + * "It is illegal to have an input block in a vertex shader + * or an output block in a fragment shader" + */ + if ((state->target == vertex_shader) && $1.flags.q.in) { + _mesa_glsl_error(& @1, state, + "`in' interface block is not allowed for " + "a vertex shader\n"); + } else if ((state->target == fragment_shader) && $1.flags.q.out) { + _mesa_glsl_error(& @1, state, + "`out' interface block is not allowed for " + "a fragment shader\n"); + } + + /* Since block arrays require names, and both features are added in + * the same language versions, we don't have to explicitly + * version-check both things. + */ + if (block->instance_name != NULL) { + state->check_version(150, 300, & @1, "interface blocks with " + "an instance name are not allowed"); + } + + unsigned interface_type_mask; + struct ast_type_qualifier temp_type_qualifier; + + /* Get a bitmask containing only the in/out/uniform flags, allowing us + * to ignore other irrelevant flags like interpolation qualifiers. + */ + temp_type_qualifier.flags.i = 0; + temp_type_qualifier.flags.q.uniform = true; + temp_type_qualifier.flags.q.in = true; + temp_type_qualifier.flags.q.out = true; + interface_type_mask = temp_type_qualifier.flags.i; + + /* Get the block's interface qualifier. The interface_qualifier + * production rule guarantees that only one bit will be set (and + * it will be in/out/uniform). + */ + unsigned block_interface_qualifier = $1.flags.i; + + block->layout.flags.i |= block_interface_qualifier; + + foreach_list_typed (ast_declarator_list, member, link, &block->declarations) { + ast_type_qualifier& qualifier = member->type->qualifier; + if ((qualifier.flags.i & interface_type_mask) == 0) { + /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks): + * "If no optional qualifier is used in a member declaration, the + * qualifier of the variable is just in, out, or uniform as declared + * by interface-qualifier." + */ + qualifier.flags.i |= block_interface_qualifier; + } else if ((qualifier.flags.i & interface_type_mask) != + block_interface_qualifier) { + /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks): + * "If optional qualifiers are used, they can include interpolation + * and storage qualifiers and they must declare an input, output, + * or uniform variable consistent with the interface qualifier of + * the block." + */ + _mesa_glsl_error(& @1, state, + "uniform/in/out qualifier on " + "interface block member does not match " + "the interface block\n"); + } + } + + $$ = block; + } + ; + +interface_qualifier: + IN_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.in = 1; + } + | OUT_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.out = 1; + } + | UNIFORM + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.uniform = 1; + } + ; + +instance_name_opt: + /* empty */ + { + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + NULL, + NULL); + } + | NEW_IDENTIFIER + { + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + $1, + NULL); + } + | NEW_IDENTIFIER '[' constant_expression ']' + { + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + $1, + $3); + } + | NEW_IDENTIFIER '[' ']' + { + _mesa_glsl_error(& @1, state, + "instance block arrays must be explicitly sized\n"); + + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + $1, + NULL); + } + ; + +member_list: + member_declaration + { + $$ = $1; + $1->link.self_link(); + } + | member_declaration member_list + { + $$ = $1; + $2->link.insert_before(& $$->link); + } + ; + +member_declaration: + fully_specified_type struct_declarator_list ';' + { + void *ctx = state; + ast_fully_specified_type *type = $1; + type->set_location(yylloc); + + if (type->qualifier.flags.q.attribute) { + _mesa_glsl_error(& @1, state, + "keyword 'attribute' cannot be used with " + "interface block member\n"); + } else if (type->qualifier.flags.q.varying) { + _mesa_glsl_error(& @1, state, + "keyword 'varying' cannot be used with " + "interface block member\n"); + } + + $$ = new(ctx) ast_declarator_list(type); + $$->set_location(yylloc); + $$->ubo_qualifiers_valid = true; + + $$->declarations.push_degenerate_list_at_head(& $2->link); + } + ; + +layout_defaults: + layout_qualifier UNIFORM ';' + { + if (!state->default_uniform_qualifier->merge_qualifier(& @1, state, + $1)) { + YYERROR; + } + }