From: Francisco Casas fcasas@codeweavers.com
In a declaration with multiple variables, the variables must be created before the initializer of the next variable is parsed. This is required for initializers such as:
float a = 1, b = a, c = b + 1;
A requisite for this is that the type information is parsed in the same rule as the first variable (as a variable_def_typed) so it is immediately available to declare the first variable. Then, the next untyped variable declaration is parsed, and the type from the first variable can be used to declare the second, before the third is parsed, and so on. --- libs/vkd3d-shader/hlsl.y | 76 ++++++++++++++++++------ tests/hlsl-initializer-multi.shader_test | 4 +- 2 files changed, 61 insertions(+), 19 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 8831a0ad9..c36ae01b8 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -73,6 +73,10 @@ struct parse_variable_def struct hlsl_semantic semantic; struct hlsl_reg_reservation reg_reservation; struct parse_initializer initializer; + + struct hlsl_type *basic_type; + unsigned int modifiers; + struct vkd3d_shader_location modifiers_loc; };
struct parse_function @@ -1924,10 +1928,12 @@ static bool type_has_numeric_components(struct hlsl_type *type) return false; }
-static void declare_var(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, - unsigned int modifiers, const struct vkd3d_shader_location *modifiers_loc, struct parse_variable_def *v) +static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) { + const struct vkd3d_shader_location *modifiers_loc = &v->modifiers_loc; + struct hlsl_type *basic_type = v->basic_type; struct hlsl_ir_function_decl *func; + uint32_t modifiers = v->modifiers; bool unbounded_res_array = false; unsigned int invalid_modifiers; struct hlsl_ir_var *var; @@ -4436,6 +4442,7 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type %type <list> unary_expr %type <list> variables_def %type <list> variables_def_optional +%type <list> variables_def_typed
%token <name> VAR_IDENTIFIER %token <name> NEW_IDENTIFIER @@ -4498,6 +4505,7 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type %type <variable_def> type_spec %type <variable_def> variable_decl %type <variable_def> variable_def +%type <variable_def> variable_def_typed
%%
@@ -4590,7 +4598,11 @@ struct_declaration: { LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $3, struct parse_variable_def, entry) { - declare_var(ctx, type, modifiers, &@1, v); + v->basic_type = type; + v->modifiers = modifiers; + v->modifiers_loc = @1; + + declare_var(ctx, v); }
if (!($$ = initialize_vars(ctx, $3))) @@ -5437,21 +5449,9 @@ type_spec: }
declaration: - var_modifiers type variables_def ';' + variables_def_typed ';' { - struct parse_variable_def *v, *v_next; - struct hlsl_type *type; - unsigned int modifiers = $1; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) - YYABORT; - - LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $3, struct parse_variable_def, entry) - { - declare_var(ctx, type, modifiers, &@1, v); - } - - if (!($$ = initialize_vars(ctx, $3))) + if (!($$ = initialize_vars(ctx, $1))) YYABORT; }
@@ -5475,6 +5475,33 @@ variables_def: list_add_tail($$, &$3->entry); }
+variables_def_typed: + variable_def_typed + { + if (!($$ = make_empty_list(ctx))) + YYABORT; + list_add_head($$, &$1->entry); + + declare_var(ctx, $1); + } + | variables_def_typed ',' variable_def + { + struct parse_variable_def *head_def; + + assert(!list_empty($1)); + head_def = LIST_ENTRY(list_head($1), struct parse_variable_def, entry); + + assert(head_def->basic_type); + $3->basic_type = head_def->basic_type; + $3->modifiers = head_def->modifiers; + $3->modifiers_loc = head_def->modifiers_loc; + + declare_var(ctx, $3); + + $$ = $1; + list_add_tail($$, &$3->entry); + } + variable_decl: any_identifier arrays colon_attribute { @@ -5516,6 +5543,21 @@ variable_def: ctx->in_state_block = 0; }
+variable_def_typed: + var_modifiers type variable_def + { + struct hlsl_type *type; + unsigned int modifiers = $1; + + if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) + YYABORT; + + $$ = $3; + $$->basic_type = type; + $$->modifiers = modifiers; + $$->modifiers_loc = @1; + } + arrays: %empty { diff --git a/tests/hlsl-initializer-multi.shader_test b/tests/hlsl-initializer-multi.shader_test index 6cb73503d..f542960d5 100644 --- a/tests/hlsl-initializer-multi.shader_test +++ b/tests/hlsl-initializer-multi.shader_test @@ -1,4 +1,4 @@ -[pixel shader todo] +[pixel shader] float4 main() : sv_target { float a = 2.0, b = a + 1.0, c = b; @@ -7,7 +7,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (2, 3, 3, 0)