Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.y | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 1341de13..50aeeab4 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1714,7 +1714,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t %%
hlsl_prog: - /* empty */ + %empty | hlsl_prog func_declaration { const struct hlsl_ir_function_decl *decl; @@ -1833,7 +1833,7 @@ any_identifier: | NEW_IDENTIFIER
fields_list: - /* empty */ + %empty { if (!($$ = make_empty_list())) YYABORT; @@ -1930,7 +1930,7 @@ compound_statement: }
scope_start: - /* empty */ + %empty { hlsl_push_scope(ctx); } @@ -1940,7 +1940,7 @@ var_identifier: | NEW_IDENTIFIER
colon_attribute: - /* empty */ + %empty { $$.semantic = NULL; $$.reg_reservation = NULL; @@ -2030,7 +2030,7 @@ parameter: }
input_mods: - /* empty */ + %empty { $$ = 0; } @@ -2206,7 +2206,7 @@ declaration: }
variables_def_optional: - /* empty */ + %empty { $$ = NULL; } @@ -2247,7 +2247,7 @@ variable_def: }
array: - /* empty */ + %empty { $$ = 0; } @@ -2274,7 +2274,7 @@ array: }
var_modifiers: - /* empty */ + %empty { $$ = 0; }
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 1 + libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl.y | 89 +++++++++++++++++++++------------------- 3 files changed, 49 insertions(+), 42 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 4e73060a..0486c952 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -319,6 +319,7 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, u vkd3d_free(type); return NULL; } + field->loc = old_field->loc; field->type = hlsl_type_clone(ctx, old_field->type, default_majority); field->name = vkd3d_strdup(old_field->name); if (old_field->semantic) diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 36e7dd0f..33eefe9f 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -130,6 +130,7 @@ struct hlsl_type struct hlsl_struct_field { struct list entry; + struct vkd3d_shader_location loc; struct hlsl_type *type; const char *name; const char *semantic; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 50aeeab4..1caeb41f 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -286,8 +286,25 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct return &cast->node; }
+static struct hlsl_ir_function_decl *get_func_entry(struct hlsl_ctx *ctx, const char *name) +{ + struct hlsl_ir_function_decl *decl; + struct hlsl_ir_function *func; + struct rb_entry *entry; + + if ((entry = rb_get(&ctx->functions, name))) + { + func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry); + RB_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) + return decl; + } + + return NULL; +} + static bool declare_variable(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local) { + struct hlsl_ir_function_decl *func; bool ret;
if (decl->data_type->type != HLSL_CLASS_MATRIX) @@ -317,10 +334,12 @@ static bool declare_variable(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, boo } else { - if (hlsl_get_function(ctx, decl->name)) + if ((func = get_func_entry(ctx, decl->name))) { hlsl_error(ctx, decl->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Variable '%s' is already defined as a function.", decl->name); + hlsl_note(ctx, func->loc, VKD3D_SHADER_LOG_ERROR, + ""%s" was previously defined here.", decl->name); return false; } } @@ -660,17 +679,16 @@ static struct hlsl_ir_load *add_array_load(struct hlsl_ctx *ctx, struct list *in return add_load(ctx, instrs, array, index, data_type, loc); }
-static bool add_struct_field(struct list *fields, struct hlsl_struct_field *field) +static struct hlsl_struct_field *get_struct_field(struct list *fields, const char *name) { struct hlsl_struct_field *f;
LIST_FOR_EACH_ENTRY(f, fields, struct hlsl_struct_field, entry) { - if (!strcmp(f->name, field->name)) - return false; + if (!strcmp(f->name, name)) + return f; } - list_add_tail(fields, &field->entry); - return true; + return NULL; }
bool hlsl_type_is_row_major(const struct hlsl_type *type) @@ -739,6 +757,7 @@ static struct list *gen_struct_fields(struct hlsl_ctx *ctx, struct hlsl_type *ty field->type = hlsl_new_array_type(ctx, type, v->array_size); else field->type = type; + field->loc = v->loc; field->name = v->name; field->modifiers = modifiers; field->semantic = v->semantic; @@ -873,22 +892,6 @@ static const struct hlsl_ir_function_decl *get_overloaded_func(struct rb_tree *f return NULL; }
-static struct hlsl_ir_function_decl *get_func_entry(struct hlsl_ctx *ctx, const char *name) -{ - struct hlsl_ir_function_decl *decl; - struct hlsl_ir_function *func; - struct rb_entry *entry; - - if ((entry = rb_get(&ctx->functions, name))) - { - func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry); - RB_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) - return decl; - } - - return NULL; -} - static struct list *make_list(struct hlsl_ir_node *node) { struct list *list; @@ -1726,14 +1729,14 @@ hlsl_prog: { hlsl_error(ctx, $2.decl->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Function "%s" is already defined.", $2.name); + hlsl_note(ctx, decl->loc, VKD3D_SHADER_LOG_ERROR, ""%s" was previously defined here.", $2.name); YYABORT; } else if (!hlsl_type_compare(decl->return_type, $2.decl->return_type)) { hlsl_error(ctx, $2.decl->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Function "%s" was already declared with a different return type.", $2.name); - hlsl_note(ctx, decl->loc, VKD3D_SHADER_LOG_ERROR, - ""%s" previously declared here", $2.name); + hlsl_note(ctx, decl->loc, VKD3D_SHADER_LOG_ERROR, ""%s" was previously declared here.", $2.name); YYABORT; } } @@ -1840,19 +1843,23 @@ fields_list: } | fields_list field { - bool ret; - struct hlsl_struct_field *field, *next; + struct hlsl_struct_field *field, *next, *existing;
$$ = $1; LIST_FOR_EACH_ENTRY_SAFE(field, next, $2, struct hlsl_struct_field, entry) { - ret = add_struct_field($$, field); - if (ret == false) + if ((existing = get_struct_field($$, field->name))) { hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Field "%s" is already defined.", field->name); + hlsl_note(ctx, existing->loc, VKD3D_SHADER_LOG_ERROR, + "'%s' was previously defined here.", field->name); vkd3d_free(field); } + else + { + list_add_tail($$, &field->entry); + } } vkd3d_free($2); } @@ -1889,15 +1896,20 @@ func_prototype: /* var_modifiers is necessary to avoid shift/reduce conflicts. */ var_modifiers type var_identifier '(' parameters ')' colon_attribute { + struct hlsl_ir_var *var; + if ($1) { hlsl_error(ctx, @1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Modifiers are not allowed on functions."); YYABORT; } - if (hlsl_get_var(ctx->globals, $3)) + if ((var = hlsl_get_var(ctx->globals, $3))) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Function "%s" is already defined.", $3); + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_REDEFINED, + ""%s" is already declared as a variable.", $3); + hlsl_note(ctx, var->loc, VKD3D_SHADER_LOG_ERROR, + ""%s" was previously declared here.", $3); YYABORT; } if (hlsl_type_is_void($2) && $7.semantic) @@ -2565,22 +2577,15 @@ postfix_expr: struct hlsl_type *type = node->data_type; struct hlsl_struct_field *field;
- $$ = NULL; - LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) - { - if (!strcmp($3, field->name)) - { - if (!add_record_load(ctx, $1, node, field, @2)) - YYABORT; - $$ = $1; - break; - } - } - if (!$$) + if (!(field = get_struct_field(type->e.elements, $3))) { hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Field "%s" is not defined.", $3); YYABORT; } + + if (!add_record_load(ctx, $1, node, field, @2)) + YYABORT; + $$ = $1; } else if (node->data_type->type <= HLSL_CLASS_LAST_NUMERIC) {
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.y | 97 ++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 23 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 1caeb41f..b11b7d08 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1021,10 +1021,25 @@ static struct hlsl_type *expr_common_type(struct hlsl_ctx *ctx, struct hlsl_type enum hlsl_base_type base; unsigned int dimx, dimy;
- if (t1->type > HLSL_CLASS_LAST_NUMERIC || t2->type > HLSL_CLASS_LAST_NUMERIC) + if (t1->type > HLSL_CLASS_LAST_NUMERIC) { - hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Non-numeric types cannot be used in expressions."); + char *string; + + if ((string = hlsl_type_to_string(t1))) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression of type "%s" cannot be used used in a numeric expression.", string); + vkd3d_free(string); + return NULL; + } + + if (t2->type > HLSL_CLASS_LAST_NUMERIC) + { + char *string; + + if ((string = hlsl_type_to_string(t2))) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression of type "%s" cannot be used used in a numeric expression.", string); + vkd3d_free(string); return NULL; }
@@ -1033,8 +1048,13 @@ static struct hlsl_type *expr_common_type(struct hlsl_ctx *ctx, struct hlsl_type
if (!expr_compatible_data_types(t1, t2)) { - hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Expression data types are incompatible."); + char *t1_string = hlsl_type_to_string(t1), *t2_string = hlsl_type_to_string(t2); + + if (t1_string && t2_string) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression data types "%s" and "%s" are incompatible.", t1_string, t2_string); + vkd3d_free(t1_string); + vkd3d_free(t2_string); return NULL; }
@@ -1325,7 +1345,8 @@ static void struct_var_initializer(struct hlsl_ctx *ctx, struct list *list, stru if (initializer_size(initializer) != hlsl_type_component_count(type)) { hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in struct initializer."); + "Expected %u components in initializer, but got %u.", + hlsl_type_component_count(type), initializer_size(initializer)); free_parse_initializer(initializer); return; } @@ -1438,7 +1459,8 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (size < type->dimx * type->dimy) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in numeric initializer."); + "Expected %u components in numeric initializer, but got %u.", + type->dimx * type->dimy, size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; @@ -1448,7 +1470,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t && hlsl_type_component_count(type) != size) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in initializer."); + "Expected %u components in initializer, but got %u.", hlsl_type_component_count(type), size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; @@ -2050,7 +2072,12 @@ input_mods: { if ($1 & $2) { - hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Duplicate modifiers specified."); + char *string; + + if ((string = hlsl_modifiers_to_string($2))) + hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Modifier "%s" was already specified.", string); + vkd3d_free(string); YYABORT; } $$ = $1 | $2; @@ -2079,14 +2106,19 @@ type: { if ($3->type != HLSL_CLASS_SCALAR) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Vectors of non-scalar types are not allowed."); + char *string; + + string = hlsl_type_to_string($3); + if (string) + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Vector base type %s is not scalar.", string); + vkd3d_free(string); YYABORT; } if ($5 < 1 || $5 > 4) { hlsl_error(ctx, @5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Vector size must be between 1 and 4."); + "Vector size %d is not between 1 and 4.", $5); YYABORT; }
@@ -2096,20 +2128,25 @@ type: { if ($3->type != HLSL_CLASS_SCALAR) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Matrices of non-scalar types are not allowed."); + char *string; + + string = hlsl_type_to_string($3); + if (string) + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Matrix base type %s is not scalar.", string); + vkd3d_free(string); YYABORT; } if ($5 < 1 || $5 > 4) { hlsl_error(ctx, @5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Matrix row count must be between 1 and 4."); + "Matrix row count %d is not between 1 and 4.", $5); YYABORT; } if ($7 < 1 || $7 > 4) { hlsl_error(ctx, @7, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Matrix column count must be between 1 and 4."); + "Matrix column count %d is not between 1 and 4.", $7); YYABORT; }
@@ -2279,7 +2316,7 @@ array: if (size > 65536) { hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Array size must be between 1 and 65536."); + "Array size %u is not between 1 and 65536.", size); YYABORT; } $$ = size; @@ -2430,8 +2467,14 @@ selection_statement: vkd3d_free($5.then_instrs); vkd3d_free($5.else_instrs); if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1) - hlsl_error(ctx, instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "if condition requires a scalar."); + { + char *string; + + if ((string = hlsl_type_to_string(condition->data_type))) + hlsl_error(ctx, instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "if condition type %s is not scalar.", string); + vkd3d_free(string); + } $$ = $3; list_add_tail($$, &instr->node.entry); } @@ -2644,8 +2687,12 @@ postfix_expr: } if ($2->type > HLSL_CLASS_LAST_NUMERIC) { - hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Constructors may only be used with numeric data types."); + char *string; + + if ((string = hlsl_type_to_string($2))) + hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Constructor data type %s is not numeric.", string); + vkd3d_free(string); YYABORT; } if ($2->dimx * $2->dimy != initializer_size(&$4)) @@ -2669,8 +2716,12 @@ postfix_expr:
if (arg->data_type->type == HLSL_CLASS_OBJECT) { - hlsl_error(ctx, arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Invalid type for constructor argument."); + char *string; + + if ((string = hlsl_type_to_string(arg->data_type))) + hlsl_error(ctx, arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Invalid type %s for constructor argument.", string); + vkd3d_free(string); continue; } width = hlsl_type_component_count(arg->data_type);
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Fix for hlsl_type_to_string() now returning a struct vkd3d_string_buffer *.
This supersedes patch 200898.
libs/vkd3d-shader/hlsl.y | 99 ++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 23 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index abcafa2..beb3357 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1021,10 +1021,25 @@ static struct hlsl_type *expr_common_type(struct hlsl_ctx *ctx, struct hlsl_type enum hlsl_base_type base; unsigned int dimx, dimy;
- if (t1->type > HLSL_CLASS_LAST_NUMERIC || t2->type > HLSL_CLASS_LAST_NUMERIC) + if (t1->type > HLSL_CLASS_LAST_NUMERIC) { - hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Non-numeric types cannot be used in expressions."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, t1))) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression of type "%s" cannot be used used in a numeric expression.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); + return NULL; + } + + if (t2->type > HLSL_CLASS_LAST_NUMERIC) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, t2))) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression of type "%s" cannot be used used in a numeric expression.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); return NULL; }
@@ -1033,8 +1048,15 @@ static struct hlsl_type *expr_common_type(struct hlsl_ctx *ctx, struct hlsl_type
if (!expr_compatible_data_types(t1, t2)) { - hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Expression data types are incompatible."); + struct vkd3d_string_buffer *t1_string = hlsl_type_to_string(&ctx->string_buffers, t1); + struct vkd3d_string_buffer *t2_string = hlsl_type_to_string(&ctx->string_buffers, t2); + + if (t1_string && t2_string) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression data types "%s" and "%s" are incompatible.", + t1_string->buffer, t2_string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, t1_string); + vkd3d_string_buffer_release(&ctx->string_buffers, t2_string); return NULL; }
@@ -1325,7 +1347,8 @@ static void struct_var_initializer(struct hlsl_ctx *ctx, struct list *list, stru if (initializer_size(initializer) != hlsl_type_component_count(type)) { hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in struct initializer."); + "Expected %u components in initializer, but got %u.", + hlsl_type_component_count(type), initializer_size(initializer)); free_parse_initializer(initializer); return; } @@ -1438,7 +1461,8 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (size < type->dimx * type->dimy) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in numeric initializer."); + "Expected %u components in numeric initializer, but got %u.", + type->dimx * type->dimy, size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; @@ -1448,7 +1472,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t && hlsl_type_component_count(type) != size) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in initializer."); + "Expected %u components in initializer, but got %u.", hlsl_type_component_count(type), size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; @@ -2050,7 +2074,12 @@ input_mods: { if ($1 & $2) { - hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Duplicate modifiers specified."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_modifiers_to_string(&ctx->string_buffers, $2))) + hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Modifier "%s" was already specified.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } $$ = $1 | $2; @@ -2079,14 +2108,19 @@ type: { if ($3->type != HLSL_CLASS_SCALAR) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Vectors of non-scalar types are not allowed."); + struct vkd3d_string_buffer *string; + + string = hlsl_type_to_string(&ctx->string_buffers, $3); + if (string) + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Vector base type %s is not scalar.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } if ($5 < 1 || $5 > 4) { hlsl_error(ctx, @5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Vector size must be between 1 and 4."); + "Vector size %d is not between 1 and 4.", $5); YYABORT; }
@@ -2096,20 +2130,25 @@ type: { if ($3->type != HLSL_CLASS_SCALAR) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Matrices of non-scalar types are not allowed."); + struct vkd3d_string_buffer *string; + + string = hlsl_type_to_string(&ctx->string_buffers, $3); + if (string) + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Matrix base type %s is not scalar.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } if ($5 < 1 || $5 > 4) { hlsl_error(ctx, @5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Matrix row count must be between 1 and 4."); + "Matrix row count %d is not between 1 and 4.", $5); YYABORT; } if ($7 < 1 || $7 > 4) { hlsl_error(ctx, @7, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Matrix column count must be between 1 and 4."); + "Matrix column count %d is not between 1 and 4.", $7); YYABORT; }
@@ -2279,7 +2318,7 @@ array: if (size > 65536) { hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Array size must be between 1 and 65536."); + "Array size %u is not between 1 and 65536.", size); YYABORT; } $$ = size; @@ -2430,8 +2469,14 @@ selection_statement: vkd3d_free($5.then_instrs); vkd3d_free($5.else_instrs); if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1) - hlsl_error(ctx, instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "if condition requires a scalar."); + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, condition->data_type))) + hlsl_error(ctx, instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "if condition type %s is not scalar.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); + } $$ = $3; list_add_tail($$, &instr->node.entry); } @@ -2644,8 +2689,12 @@ postfix_expr: } if ($2->type > HLSL_CLASS_LAST_NUMERIC) { - hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Constructors may only be used with numeric data types."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, $2))) + hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Constructor data type %s is not numeric.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } if ($2->dimx * $2->dimy != initializer_size(&$4)) @@ -2669,8 +2718,12 @@ postfix_expr:
if (arg->data_type->type == HLSL_CLASS_OBJECT) { - hlsl_error(ctx, arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Invalid type for constructor argument."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, arg->data_type))) + hlsl_error(ctx, arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Invalid type %s for constructor argument.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); continue; } width = hlsl_type_component_count(arg->data_type);
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Fix for hlsl_type_to_string() now returning a struct vkd3d_string_buffer *. v3: Fix a couple of typos in error messages (thanks Andrey)
libs/vkd3d-shader/hlsl.y | 99 ++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 23 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 1caeb41..f1db9be 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1021,10 +1021,25 @@ static struct hlsl_type *expr_common_type(struct hlsl_ctx *ctx, struct hlsl_type enum hlsl_base_type base; unsigned int dimx, dimy;
- if (t1->type > HLSL_CLASS_LAST_NUMERIC || t2->type > HLSL_CLASS_LAST_NUMERIC) + if (t1->type > HLSL_CLASS_LAST_NUMERIC) { - hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Non-numeric types cannot be used in expressions."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, t1))) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression of type "%s" cannot be used in a numeric expression.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); + return NULL; + } + + if (t2->type > HLSL_CLASS_LAST_NUMERIC) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, t2))) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression of type "%s" cannot be used in a numeric expression.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); return NULL; }
@@ -1033,8 +1048,15 @@ static struct hlsl_type *expr_common_type(struct hlsl_ctx *ctx, struct hlsl_type
if (!expr_compatible_data_types(t1, t2)) { - hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Expression data types are incompatible."); + struct vkd3d_string_buffer *t1_string = hlsl_type_to_string(&ctx->string_buffers, t1); + struct vkd3d_string_buffer *t2_string = hlsl_type_to_string(&ctx->string_buffers, t2); + + if (t1_string && t2_string) + hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Expression data types "%s" and "%s" are incompatible.", + t1_string->buffer, t2_string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, t1_string); + vkd3d_string_buffer_release(&ctx->string_buffers, t2_string); return NULL; }
@@ -1325,7 +1347,8 @@ static void struct_var_initializer(struct hlsl_ctx *ctx, struct list *list, stru if (initializer_size(initializer) != hlsl_type_component_count(type)) { hlsl_error(ctx, var->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in struct initializer."); + "Expected %u components in initializer, but got %u.", + hlsl_type_component_count(type), initializer_size(initializer)); free_parse_initializer(initializer); return; } @@ -1438,7 +1461,8 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (size < type->dimx * type->dimy) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in numeric initializer."); + "Expected %u components in numeric initializer, but got %u.", + type->dimx * type->dimy, size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; @@ -1448,7 +1472,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t && hlsl_type_component_count(type) != size) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of parameters in initializer."); + "Expected %u components in initializer, but got %u.", hlsl_type_component_count(type), size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; @@ -2050,7 +2074,12 @@ input_mods: { if ($1 & $2) { - hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Duplicate modifiers specified."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_modifiers_to_string(&ctx->string_buffers, $2))) + hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Modifier "%s" was already specified.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } $$ = $1 | $2; @@ -2079,14 +2108,19 @@ type: { if ($3->type != HLSL_CLASS_SCALAR) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Vectors of non-scalar types are not allowed."); + struct vkd3d_string_buffer *string; + + string = hlsl_type_to_string(&ctx->string_buffers, $3); + if (string) + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Vector base type %s is not scalar.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } if ($5 < 1 || $5 > 4) { hlsl_error(ctx, @5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Vector size must be between 1 and 4."); + "Vector size %d is not between 1 and 4.", $5); YYABORT; }
@@ -2096,20 +2130,25 @@ type: { if ($3->type != HLSL_CLASS_SCALAR) { - hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Matrices of non-scalar types are not allowed."); + struct vkd3d_string_buffer *string; + + string = hlsl_type_to_string(&ctx->string_buffers, $3); + if (string) + hlsl_error(ctx, @3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Matrix base type %s is not scalar.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } if ($5 < 1 || $5 > 4) { hlsl_error(ctx, @5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Matrix row count must be between 1 and 4."); + "Matrix row count %d is not between 1 and 4.", $5); YYABORT; } if ($7 < 1 || $7 > 4) { hlsl_error(ctx, @7, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Matrix column count must be between 1 and 4."); + "Matrix column count %d is not between 1 and 4.", $7); YYABORT; }
@@ -2279,7 +2318,7 @@ array: if (size > 65536) { hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, - "Array size must be between 1 and 65536."); + "Array size %u is not between 1 and 65536.", size); YYABORT; } $$ = size; @@ -2430,8 +2469,14 @@ selection_statement: vkd3d_free($5.then_instrs); vkd3d_free($5.else_instrs); if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1) - hlsl_error(ctx, instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "if condition requires a scalar."); + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, condition->data_type))) + hlsl_error(ctx, instr->node.loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "if condition type %s is not scalar.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); + } $$ = $3; list_add_tail($$, &instr->node.entry); } @@ -2644,8 +2689,12 @@ postfix_expr: } if ($2->type > HLSL_CLASS_LAST_NUMERIC) { - hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Constructors may only be used with numeric data types."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, $2))) + hlsl_error(ctx, @2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Constructor data type %s is not numeric.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); YYABORT; } if ($2->dimx * $2->dimy != initializer_size(&$4)) @@ -2669,8 +2718,12 @@ postfix_expr:
if (arg->data_type->type == HLSL_CLASS_OBJECT) { - hlsl_error(ctx, arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Invalid type for constructor argument."); + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(&ctx->string_buffers, arg->data_type))) + hlsl_error(ctx, arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Invalid type %s for constructor argument.", string->buffer); + vkd3d_string_buffer_release(&ctx->string_buffers, string); continue; } width = hlsl_type_component_count(arg->data_type);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On Tue, Mar 2, 2021 at 10:35 PM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl.y | 97 ++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 23 deletions(-)
I'm hijacking this one just to refer to the existing code.
@@ -1438,7 +1459,8 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (size < type->dimx * type->dimy) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
"Wrong number of parameters in numeric initializer.");
"Expected %u components in numeric initializer, but got %u.",
type->dimx * type->dimy, size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue;
It would be interesting to know (or probably, remember) why this is complaining if the initializer is smaller than required but not if it's larger. Native _43 seems to report an error in both cases, maybe older compilers didn't? Or maybe it's just wrong...
On 3/4/21 3:54 AM, Matteo Bruni wrote:
On Tue, Mar 2, 2021 at 10:35 PM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl.y | 97 ++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 23 deletions(-)
I'm hijacking this one just to refer to the existing code.
@@ -1438,7 +1459,8 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (size < type->dimx * type->dimy) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
"Wrong number of parameters in numeric initializer.");
"Expected %u components in numeric initializer, but got %u.",
type->dimx * type->dimy, size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue;
It would be interesting to know (or probably, remember) why this is complaining if the initializer is smaller than required but not if it's larger. Native _43 seems to report an error in both cases, maybe older compilers didn't? Or maybe it's just wrong...
I believe you're half right, which unfortunately isn't enough. I think the point of this is to catch
float4 a; float3 b = {a.x, a.y};
but it also catches
float4 a; float4 b = a.xy;
and may in fact have been written with solely the latter in mind, in which case truncation is not an error. The tricky thing is that
float4 a; float3 b = {a.x, a.y, a.z, a.w};
is invalid (native says "initializer does not match type"), and so is
float4 a; float3 b = {a.xyzw};
but
float4 a; float3 b = a.xyzw;
only yields an "implicit truncation" warning.
We get the warning and type checking from the add_assignment() call, for what it's worth, so we really only need to check when there are explicit braces.
On Fri, Mar 5, 2021 at 3:31 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 3/4/21 3:54 AM, Matteo Bruni wrote:
On Tue, Mar 2, 2021 at 10:35 PM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl.y | 97 ++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 23 deletions(-)
I'm hijacking this one just to refer to the existing code.
@@ -1438,7 +1459,8 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (size < type->dimx * type->dimy) { hlsl_error(ctx, v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
"Wrong number of parameters in numeric initializer.");
"Expected %u components in numeric initializer, but got %u.",
type->dimx * type->dimy, size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue;
It would be interesting to know (or probably, remember) why this is complaining if the initializer is smaller than required but not if it's larger. Native _43 seems to report an error in both cases, maybe older compilers didn't? Or maybe it's just wrong...
I believe you're half right, which unfortunately isn't enough. I think the point of this is to catch
float4 a; float3 b = {a.x, a.y};
but it also catches
float4 a; float4 b = a.xy;
and may in fact have been written with solely the latter in mind, in which case truncation is not an error. The tricky thing is that
float4 a; float3 b = {a.x, a.y, a.z, a.w};
is invalid (native says "initializer does not match type"), and so is
float4 a; float3 b = {a.xyzw};
but
float4 a; float3 b = a.xyzw;
only yields an "implicit truncation" warning.
We get the warning and type checking from the add_assignment() call, for what it's worth, so we really only need to check when there are explicit braces.
This sounds somewhat familiar now. I think you're correct that this was added only for the second case and tightening the error check is the way to go.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.y | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index b11b7d08..41384f6c 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1763,10 +1763,6 @@ hlsl_prog: } }
- if (hlsl_type_is_void($2.decl->return_type) && $2.decl->semantic) - hlsl_error(ctx, $2.decl->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, - "Semantics are not allowed on void functions."); - hlsl_add_function(&ctx->functions, $2.name, $2.decl, false); } | hlsl_prog declaration_statement
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 1 + libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d-shader/hlsl.y | 153 +------------------------- libs/vkd3d-shader/hlsl_codegen.c | 177 +++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+), 152 deletions(-) create mode 100644 libs/vkd3d-shader/hlsl_codegen.c
diff --git a/Makefile.am b/Makefile.am index 3c219e8a..3b09dc7f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -160,6 +160,7 @@ libvkd3d_shader_la_SOURCES = \ libs/vkd3d-shader/checksum.c \ libs/vkd3d-shader/dxbc.c \ libs/vkd3d-shader/hlsl.c \ + libs/vkd3d-shader/hlsl_codegen.c \ libs/vkd3d-shader/spirv.c \ libs/vkd3d-shader/trace.c \ libs/vkd3d-shader/vkd3d_shader.map \ diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 33eefe9f..73ba2bec 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -510,6 +510,8 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var
void hlsl_dump_function(const struct hlsl_ir_function_decl *func) DECLSPEC_HIDDEN;
+int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) DECLSPEC_HIDDEN; + void hlsl_free_instr(struct hlsl_ir_node *node) DECLSPEC_HIDDEN; void hlsl_free_instr_list(struct list *list) DECLSPEC_HIDDEN; void hlsl_free_type(struct hlsl_type *type) DECLSPEC_HIDDEN; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 41384f6c..66a36600 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3013,145 +3013,6 @@ expr:
%%
-static void dump_function_decl(struct rb_entry *entry, void *context) -{ - struct hlsl_ir_function_decl *func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry); - - if (func->body) - hlsl_dump_function(func); -} - -static void dump_function(struct rb_entry *entry, void *context) -{ - struct hlsl_ir_function *func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry); - rb_for_each_entry(&func->overloads, dump_function_decl, NULL); -} - -/* Allocate a unique, ordered index to each instruction, which will be used for - * computing liveness ranges. */ -static unsigned int index_instructions(struct list *instrs, unsigned int index) -{ - struct hlsl_ir_node *instr; - - LIST_FOR_EACH_ENTRY(instr, instrs, struct hlsl_ir_node, entry) - { - instr->index = index++; - - if (instr->type == HLSL_IR_IF) - { - struct hlsl_ir_if *iff = hlsl_ir_if(instr); - index = index_instructions(&iff->then_instrs, index); - index = index_instructions(&iff->else_instrs, index); - } - else if (instr->type == HLSL_IR_LOOP) - { - index = index_instructions(&hlsl_ir_loop(instr)->body, index); - hlsl_ir_loop(instr)->next_index = index; - } - } - - return index; -} - -/* Compute the earliest and latest liveness for each variable. In the case that - * a variable is accessed inside of a loop, we promote its liveness to extend - * to at least the range of the entire loop. Note that we don't need to do this - * for anonymous nodes, since there's currently no way to use a node which was - * calculated in an earlier iteration of the loop. */ -static void compute_liveness_recurse(struct list *instrs, unsigned int loop_first, unsigned int loop_last) -{ - struct hlsl_ir_node *instr; - struct hlsl_ir_var *var; - - LIST_FOR_EACH_ENTRY(instr, instrs, struct hlsl_ir_node, entry) - { - switch (instr->type) - { - case HLSL_IR_ASSIGNMENT: - { - struct hlsl_ir_assignment *assignment = hlsl_ir_assignment(instr); - - var = assignment->lhs.var; - if (!var->first_write) - var->first_write = loop_first ? min(instr->index, loop_first) : instr->index; - assignment->rhs.node->last_read = instr->index; - if (assignment->lhs.offset.node) - assignment->lhs.offset.node->last_read = instr->index; - break; - } - case HLSL_IR_EXPR: - { - struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(expr->operands) && expr->operands[i].node; ++i) - expr->operands[i].node->last_read = instr->index; - break; - } - case HLSL_IR_IF: - { - struct hlsl_ir_if *iff = hlsl_ir_if(instr); - - compute_liveness_recurse(&iff->then_instrs, loop_first, loop_last); - compute_liveness_recurse(&iff->else_instrs, loop_first, loop_last); - iff->condition.node->last_read = instr->index; - break; - } - case HLSL_IR_LOAD: - { - struct hlsl_ir_load *load = hlsl_ir_load(instr); - - var = load->src.var; - var->last_read = loop_last ? max(instr->index, loop_last) : instr->index; - if (load->src.offset.node) - load->src.offset.node->last_read = instr->index; - break; - } - case HLSL_IR_LOOP: - { - struct hlsl_ir_loop *loop = hlsl_ir_loop(instr); - - compute_liveness_recurse(&loop->body, loop_first ? loop_first : instr->index, - loop_last ? loop_last : loop->next_index); - break; - } - case HLSL_IR_SWIZZLE: - { - struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr); - - swizzle->val.node->last_read = instr->index; - break; - } - case HLSL_IR_CONSTANT: - case HLSL_IR_JUMP: - break; - } - } -} - -static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) -{ - struct hlsl_ir_var *var; - - LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) - { - var->first_write = 1; - } - - LIST_FOR_EACH_ENTRY(var, entry_func->parameters, struct hlsl_ir_var, param_entry) - { - if (var->modifiers & HLSL_STORAGE_IN) - var->first_write = 1; - if (var->modifiers & HLSL_STORAGE_OUT) - var->last_read = UINT_MAX; - } - - if (entry_func->return_var) - entry_func->return_var->last_read = UINT_MAX; - - compute_liveness_recurse(entry_func->body, 0, 0); -} - int hlsl_parser_compile(struct hlsl_ctx *ctx, const char *entrypoint) { struct hlsl_ir_function_decl *entry_func; @@ -3176,17 +3037,5 @@ int hlsl_parser_compile(struct hlsl_ctx *ctx, const char *entrypoint) "Entry point "%s" is missing a return value semantic.", entry_func->func->name); }
- list_move_head(entry_func->body, &ctx->static_initializers); - - /* Index 0 means unused; index 1 means function entry, so start at 2. */ - index_instructions(entry_func->body, 2); - - if (TRACE_ON()) - rb_for_each_entry(&ctx->functions, dump_function, NULL); - - compute_liveness(ctx, entry_func); - - if (ctx->failed) - return VKD3D_ERROR_INVALID_SHADER; - return VKD3D_ERROR_NOT_IMPLEMENTED; + return hlsl_emit_dxbc(ctx, entry_func); } diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c new file mode 100644 index 00000000..39984702 --- /dev/null +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -0,0 +1,177 @@ +/* + * HLSL optimization and code generation + * + * Copyright 2019-2020 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "hlsl.h" + +/* Allocate a unique, ordered index to each instruction, which will be used for + * computing liveness ranges. */ +static unsigned int index_instructions(struct list *instrs, unsigned int index) +{ + struct hlsl_ir_node *instr; + + LIST_FOR_EACH_ENTRY(instr, instrs, struct hlsl_ir_node, entry) + { + instr->index = index++; + + if (instr->type == HLSL_IR_IF) + { + struct hlsl_ir_if *iff = hlsl_ir_if(instr); + index = index_instructions(&iff->then_instrs, index); + index = index_instructions(&iff->else_instrs, index); + } + else if (instr->type == HLSL_IR_LOOP) + { + index = index_instructions(&hlsl_ir_loop(instr)->body, index); + hlsl_ir_loop(instr)->next_index = index; + } + } + + return index; +} + +static void dump_function_decl(struct rb_entry *entry, void *context) +{ + struct hlsl_ir_function_decl *func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry); + + if (func->body) + hlsl_dump_function(func); +} + +static void dump_function(struct rb_entry *entry, void *context) +{ + struct hlsl_ir_function *func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry); + rb_for_each_entry(&func->overloads, dump_function_decl, NULL); +} + +/* Compute the earliest and latest liveness for each variable. In the case that + * a variable is accessed inside of a loop, we promote its liveness to extend + * to at least the range of the entire loop. Note that we don't need to do this + * for anonymous nodes, since there's currently no way to use a node which was + * calculated in an earlier iteration of the loop. */ +static void compute_liveness_recurse(struct list *instrs, unsigned int loop_first, unsigned int loop_last) +{ + struct hlsl_ir_node *instr; + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(instr, instrs, struct hlsl_ir_node, entry) + { + switch (instr->type) + { + case HLSL_IR_ASSIGNMENT: + { + struct hlsl_ir_assignment *assignment = hlsl_ir_assignment(instr); + + var = assignment->lhs.var; + if (!var->first_write) + var->first_write = loop_first ? min(instr->index, loop_first) : instr->index; + assignment->rhs.node->last_read = instr->index; + if (assignment->lhs.offset.node) + assignment->lhs.offset.node->last_read = instr->index; + break; + } + case HLSL_IR_EXPR: + { + struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(expr->operands) && expr->operands[i].node; ++i) + expr->operands[i].node->last_read = instr->index; + break; + } + case HLSL_IR_IF: + { + struct hlsl_ir_if *iff = hlsl_ir_if(instr); + + compute_liveness_recurse(&iff->then_instrs, loop_first, loop_last); + compute_liveness_recurse(&iff->else_instrs, loop_first, loop_last); + iff->condition.node->last_read = instr->index; + break; + } + case HLSL_IR_LOAD: + { + struct hlsl_ir_load *load = hlsl_ir_load(instr); + + var = load->src.var; + var->last_read = loop_last ? max(instr->index, loop_last) : instr->index; + if (load->src.offset.node) + load->src.offset.node->last_read = instr->index; + break; + } + case HLSL_IR_LOOP: + { + struct hlsl_ir_loop *loop = hlsl_ir_loop(instr); + + compute_liveness_recurse(&loop->body, loop_first ? loop_first : instr->index, + loop_last ? loop_last : loop->next_index); + break; + } + case HLSL_IR_SWIZZLE: + { + struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr); + + swizzle->val.node->last_read = instr->index; + break; + } + case HLSL_IR_CONSTANT: + case HLSL_IR_JUMP: + break; + } + } +} + +static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) +{ + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) + { + var->first_write = 1; + } + + LIST_FOR_EACH_ENTRY(var, entry_func->parameters, struct hlsl_ir_var, param_entry) + { + if (var->modifiers & HLSL_STORAGE_IN) + var->first_write = 1; + if (var->modifiers & HLSL_STORAGE_OUT) + var->last_read = UINT_MAX; + } + + if (entry_func->return_var) + entry_func->return_var->last_read = UINT_MAX; + + compute_liveness_recurse(entry_func->body, 0, 0); +} + +int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) +{ + list_move_head(entry_func->body, &ctx->static_initializers); + + /* Index 0 means unused; index 1 means function entry, so start at 2. */ + index_instructions(entry_func->body, 2); + + if (TRACE_ON()) + rb_for_each_entry(&ctx->functions, dump_function, NULL); + + compute_liveness(ctx, entry_func); + + if (ctx->failed) + return VKD3D_ERROR_INVALID_SHADER; + return VKD3D_ERROR_NOT_IMPLEMENTED; +}
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com