Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 205 +++++++++++++++++++++++++++++++++++++++ libs/vkd3d-shader/hlsl.h | 22 ++++- libs/vkd3d-shader/hlsl.y | 205 --------------------------------------- 3 files changed, 224 insertions(+), 208 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index cd0d9cbc..e73ed923 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -18,6 +18,7 @@ */
#include "hlsl.h" +#include <stdio.h>
BOOL add_declaration(struct hlsl_scope *scope, struct hlsl_ir_var *decl, BOOL local_var) { @@ -102,6 +103,41 @@ struct hlsl_type *new_array_type(struct hlsl_type *basic_type, unsigned int arra return type; }
+static DWORD get_array_size(const struct hlsl_type *type) +{ + if (type->type == HLSL_CLASS_ARRAY) + return get_array_size(type->e.array.type) * type->e.array.elements_count; + return 1; +} + +struct hlsl_type *new_struct_type(const char *name, struct list *fields) +{ + struct hlsl_struct_field *field; + unsigned int reg_size = 0; + struct hlsl_type *type; + + if (!(type = vkd3d_calloc(1, sizeof(*type)))) + return NULL; + type->type = HLSL_CLASS_STRUCT; + type->base_type = HLSL_TYPE_VOID; + type->name = name; + type->dimx = 0; + type->dimy = 1; + type->e.elements = fields; + + LIST_FOR_EACH_ENTRY(field, fields, struct hlsl_struct_field, entry) + { + field->reg_offset = reg_size; + reg_size += field->type->reg_size; + type->dimx += field->type->dimx * field->type->dimy * get_array_size(field->type); + } + type->reg_size = reg_size; + + list_add_tail(&hlsl_ctx.types, &type->entry); + + return type; +} + struct hlsl_type *get_type(struct hlsl_scope *scope, const char *name, BOOL recursive) { struct rb_entry *entry = rb_get(&scope->types, name); @@ -639,6 +675,35 @@ struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type, return expr_from_node(cast); }
+struct hlsl_ir_var *new_var(const char *name, struct hlsl_type *type, const struct source_location loc, + const char *semantic, unsigned int modifiers, const struct reg_reservation *reg_reservation) +{ + struct hlsl_ir_var *var; + + if (!(var = vkd3d_calloc(1, sizeof(*var)))) + { + hlsl_ctx.status = PARSE_ERR; + return NULL; + } + + var->name = name; + var->data_type = type; + var->loc = loc; + var->semantic = semantic; + var->modifiers = modifiers; + var->reg_reservation = reg_reservation; + return var; +} + +struct hlsl_ir_var *new_synthetic_var(const char *name, struct hlsl_type *type, const struct source_location loc) +{ + struct hlsl_ir_var *var = new_var(vkd3d_strdup(name), type, loc, NULL, 0, NULL); + + if (var) + list_add_tail(&hlsl_ctx.globals->vars, &var->scope_entry); + return var; +} + static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) { static const enum hlsl_ir_expr_op ops[] = @@ -780,6 +845,146 @@ struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lh return &assign->node; }
+static BOOL type_is_single_reg(const struct hlsl_type *type) +{ + return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; +} + +struct hlsl_ir_assignment *new_assignment(struct hlsl_ir_var *var, struct hlsl_ir_node *offset, + struct hlsl_ir_node *rhs, unsigned int writemask, struct source_location loc) +{ + struct hlsl_ir_assignment *assign; + + if (!writemask && type_is_single_reg(rhs->data_type)) + writemask = (1 << rhs->data_type->dimx) - 1; + + if (!(assign = vkd3d_malloc(sizeof(*assign)))) + return NULL; + + init_node(&assign->node, HLSL_IR_ASSIGNMENT, NULL, loc); + assign->lhs.var = var; + hlsl_src_from_node(&assign->lhs.offset, offset); + hlsl_src_from_node(&assign->rhs, rhs); + assign->writemask = writemask; + return assign; +} + +struct hlsl_ir_assignment *new_simple_assignment(struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) +{ + return new_assignment(lhs, NULL, rhs, 0, rhs->loc); +} + +struct hlsl_ir_constant *new_uint_constant(unsigned int n, const struct source_location loc) +{ + struct hlsl_ir_constant *c; + + if (!(c = vkd3d_malloc(sizeof(*c)))) + return NULL; + init_node(&c->node, HLSL_IR_CONSTANT, hlsl_ctx.builtin_types.scalar[HLSL_TYPE_UINT], loc); + c->value.u[0] = n; + return c; +} + +struct hlsl_ir_node *new_unary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, struct source_location loc) +{ + struct hlsl_ir_expr *expr; + + if (!(expr = vkd3d_calloc(1, sizeof(*expr)))) + return NULL; + init_node(&expr->node, HLSL_IR_EXPR, arg->data_type, loc); + expr->op = op; + hlsl_src_from_node(&expr->operands[0], arg); + return &expr->node; +} + +struct hlsl_ir_node *new_binary_expr(enum hlsl_ir_expr_op op, + struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2) +{ + struct hlsl_ir_expr *expr; + + assert(compare_hlsl_types(arg1->data_type, arg2->data_type)); + + if (!(expr = vkd3d_calloc(1, sizeof(*expr)))) + return NULL; + init_node(&expr->node, HLSL_IR_EXPR, arg1->data_type, arg1->loc); + expr->op = op; + hlsl_src_from_node(&expr->operands[0], arg1); + hlsl_src_from_node(&expr->operands[1], arg2); + return &expr->node; +} + +struct hlsl_ir_if *new_if(struct hlsl_ir_node *condition, struct source_location loc) +{ + struct hlsl_ir_if *iff; + + if (!(iff = vkd3d_malloc(sizeof(*iff)))) + return NULL; + init_node(&iff->node, HLSL_IR_IF, NULL, loc); + hlsl_src_from_node(&iff->condition, condition); + list_init(&iff->then_instrs); + list_init(&iff->else_instrs); + return iff; +} + +struct hlsl_ir_load *new_var_load(struct hlsl_ir_var *var, const struct source_location loc) +{ + struct hlsl_ir_load *load; + + if (!(load = vkd3d_calloc(1, sizeof(*load)))) + return NULL; + init_node(&load->node, HLSL_IR_LOAD, var->data_type, loc); + load->src.var = var; + return load; +} + +struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components, + struct hlsl_ir_node *val, struct source_location *loc) +{ + struct hlsl_ir_swizzle *swizzle; + + if (!(swizzle = vkd3d_malloc(sizeof(*swizzle)))) + return NULL; + init_node(&swizzle->node, HLSL_IR_SWIZZLE, + new_hlsl_type(NULL, HLSL_CLASS_VECTOR, val->data_type->base_type, components, 1), *loc); + hlsl_src_from_node(&swizzle->val, val); + swizzle->swizzle = s; + return swizzle; +} + +BOOL type_is_void(const struct hlsl_type *type) +{ + return type->type == HLSL_CLASS_OBJECT && type->base_type == HLSL_TYPE_VOID; +} + +struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type, + struct list *parameters, const char *semantic, struct source_location loc) +{ + struct hlsl_ir_function_decl *decl; + + if (!(decl = vkd3d_calloc(1, sizeof(*decl)))) + return NULL; + decl->return_type = return_type; + decl->parameters = parameters; + decl->semantic = semantic; + decl->loc = loc; + + if (!type_is_void(return_type)) + { + struct hlsl_ir_var *return_var; + char name[28]; + + sprintf(name, "<retval-%p>", decl); + if (!(return_var = new_synthetic_var(name, return_type, loc))) + { + vkd3d_free(decl); + return NULL; + } + decl->return_var = return_var; + } + + return decl; +} + static int compare_hlsl_types_rb(const void *key, const struct rb_entry *entry) { const struct hlsl_type *type = RB_ENTRY_VALUE(entry, const struct hlsl_type, scope_entry); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 128de1d6..aabfbaf9 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -599,19 +599,34 @@ struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, stru struct hlsl_ir_node *add_implicit_conversion(struct list *instrs, struct hlsl_ir_node *node, struct hlsl_type *type, struct source_location *loc) DECLSPEC_HIDDEN;
-struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type, - struct source_location *loc) DECLSPEC_HIDDEN; +struct hlsl_type *new_array_type(struct hlsl_type *basic_type, unsigned int array_size) DECLSPEC_HIDDEN; +struct hlsl_ir_assignment *new_assignment(struct hlsl_ir_var *var, struct hlsl_ir_node *offset, + struct hlsl_ir_node *rhs, unsigned int writemask, struct source_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_node *new_binary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2) DECLSPEC_HIDDEN; +struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type, + struct source_location *loc) DECLSPEC_HIDDEN; +struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type, + struct list *parameters, const char *semantic, struct source_location loc) DECLSPEC_HIDDEN; +struct hlsl_ir_if *new_if(struct hlsl_ir_node *condition, struct source_location loc) DECLSPEC_HIDDEN; +struct hlsl_ir_assignment *new_simple_assignment(struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) DECLSPEC_HIDDEN; +struct hlsl_type *new_struct_type(const char *name, struct list *fields) DECLSPEC_HIDDEN; +struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components, + struct hlsl_ir_node *val, struct source_location *loc) DECLSPEC_HIDDEN; +struct hlsl_ir_var *new_synthetic_var(const char *name, struct hlsl_type *type, + const struct source_location loc) DECLSPEC_HIDDEN; +struct hlsl_ir_constant *new_uint_constant(unsigned int n, const struct source_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_node *new_unary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, struct source_location loc) DECLSPEC_HIDDEN; +struct hlsl_ir_var *new_var(const char *name, struct hlsl_type *type, const struct source_location loc, + const char *semantic, unsigned int modifiers, const struct reg_reservation *reg_reservation) DECLSPEC_HIDDEN; +struct hlsl_ir_load *new_var_load(struct hlsl_ir_var *var, const struct source_location loc) DECLSPEC_HIDDEN;
BOOL add_declaration(struct hlsl_scope *scope, struct hlsl_ir_var *decl, BOOL local_var) DECLSPEC_HIDDEN; struct hlsl_ir_var *get_variable(struct hlsl_scope *scope, const char *name) DECLSPEC_HIDDEN; void free_declaration(struct hlsl_ir_var *decl) DECLSPEC_HIDDEN; struct hlsl_type *new_hlsl_type(const char *name, enum hlsl_type_class type_class, enum hlsl_base_type base_type, unsigned dimx, unsigned dimy) DECLSPEC_HIDDEN; -struct hlsl_type *new_array_type(struct hlsl_type *basic_type, unsigned int array_size) DECLSPEC_HIDDEN; struct hlsl_type *clone_hlsl_type(struct hlsl_type *old, unsigned int default_majority) DECLSPEC_HIDDEN; struct hlsl_type *get_type(struct hlsl_scope *scope, const char *name, BOOL recursive) DECLSPEC_HIDDEN; BOOL is_row_major(const struct hlsl_type *type) DECLSPEC_HIDDEN; @@ -624,6 +639,7 @@ BOOL pop_scope(struct hlsl_parse_ctx *ctx) DECLSPEC_HIDDEN; void init_functions_tree(struct rb_tree *funcs) DECLSPEC_HIDDEN; void add_function_decl(struct rb_tree *funcs, char *name, struct hlsl_ir_function_decl *decl, BOOL intrinsic) DECLSPEC_HIDDEN; +BOOL type_is_void(const struct hlsl_type *type) DECLSPEC_HIDDEN;
int hlsl_lexer_compile(const char *text, enum vkd3d_shader_type type, DWORD major, DWORD minor, const char *entrypoint, struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context) DECLSPEC_HIDDEN; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 4e2218c5..df155a08 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -77,11 +77,6 @@ static void check_invalid_matrix_modifiers(DWORD modifiers, struct source_locati "'row_major' or 'column_major' modifiers are only allowed for matrices."); }
-static BOOL type_is_single_reg(const struct hlsl_type *type) -{ - return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; -} - static BOOL declare_variable(struct hlsl_ir_var *decl, BOOL local) { BOOL ret; @@ -232,24 +227,6 @@ static void declare_predefined_types(struct hlsl_scope *scope) add_type_to_scope(scope, type); }
-static BOOL type_is_void(const struct hlsl_type *type) -{ - return type->type == HLSL_CLASS_OBJECT && type->base_type == HLSL_TYPE_VOID; -} - -static struct hlsl_ir_if *new_if(struct hlsl_ir_node *condition, struct source_location loc) -{ - struct hlsl_ir_if *iff; - - if (!(iff = vkd3d_malloc(sizeof(*iff)))) - return NULL; - init_node(&iff->node, HLSL_IR_IF, NULL, loc); - hlsl_src_from_node(&iff->condition, condition); - list_init(&iff->then_instrs); - list_init(&iff->else_instrs); - return iff; -} - static BOOL append_conditional_break(struct list *cond_list) { struct hlsl_ir_node *condition, *not; @@ -352,20 +329,6 @@ static void free_parse_initializer(struct parse_initializer *initializer) vkd3d_free(initializer->args); }
-static struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components, - struct hlsl_ir_node *val, struct source_location *loc) -{ - struct hlsl_ir_swizzle *swizzle; - - if (!(swizzle = vkd3d_malloc(sizeof(*swizzle)))) - return NULL; - init_node(&swizzle->node, HLSL_IR_SWIZZLE, - new_hlsl_type(NULL, HLSL_CLASS_VECTOR, val->data_type->base_type, components, 1), *loc); - hlsl_src_from_node(&swizzle->val, val); - swizzle->swizzle = s; - return swizzle; -} - static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const char *swizzle, struct source_location *loc) { @@ -448,60 +411,6 @@ static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const cha return NULL; }
-static struct hlsl_ir_var *new_var(const char *name, struct hlsl_type *type, const struct source_location loc, - const char *semantic, unsigned int modifiers, const struct reg_reservation *reg_reservation) -{ - struct hlsl_ir_var *var; - - if (!(var = vkd3d_calloc(1, sizeof(*var)))) - { - hlsl_ctx.status = PARSE_ERR; - return NULL; - } - - var->name = name; - var->data_type = type; - var->loc = loc; - var->semantic = semantic; - var->modifiers = modifiers; - var->reg_reservation = reg_reservation; - return var; -} - -static struct hlsl_ir_var *new_synthetic_var(const char *name, struct hlsl_type *type, - const struct source_location loc) -{ - struct hlsl_ir_var *var = new_var(vkd3d_strdup(name), type, loc, NULL, 0, NULL); - - if (var) - list_add_tail(&hlsl_ctx.globals->vars, &var->scope_entry); - return var; -} - -static struct hlsl_ir_assignment *new_assignment(struct hlsl_ir_var *var, struct hlsl_ir_node *offset, - struct hlsl_ir_node *rhs, unsigned int writemask, struct source_location loc) -{ - struct hlsl_ir_assignment *assign; - - if (!writemask && type_is_single_reg(rhs->data_type)) - writemask = (1 << rhs->data_type->dimx) - 1; - - if (!(assign = vkd3d_malloc(sizeof(*assign)))) - return NULL; - - init_node(&assign->node, HLSL_IR_ASSIGNMENT, NULL, loc); - assign->lhs.var = var; - hlsl_src_from_node(&assign->lhs.offset, offset); - hlsl_src_from_node(&assign->rhs, rhs); - assign->writemask = writemask; - return assign; -} - -static struct hlsl_ir_assignment *new_simple_assignment(struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) -{ - return new_assignment(lhs, NULL, rhs, 0, rhs->loc); -} - static struct hlsl_ir_jump *add_return(struct list *instrs, struct hlsl_ir_node *return_value, struct source_location loc) { @@ -534,56 +443,6 @@ static struct hlsl_ir_jump *add_return(struct list *instrs, return jump; }
-static struct hlsl_ir_constant *new_uint_constant(unsigned int n, const struct source_location loc) -{ - struct hlsl_ir_constant *c; - - if (!(c = vkd3d_malloc(sizeof(*c)))) - return NULL; - init_node(&c->node, HLSL_IR_CONSTANT, hlsl_ctx.builtin_types.scalar[HLSL_TYPE_UINT], loc); - c->value.u[0] = n; - return c; -} - -struct hlsl_ir_node *new_unary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, struct source_location loc) -{ - struct hlsl_ir_expr *expr; - - if (!(expr = vkd3d_calloc(1, sizeof(*expr)))) - return NULL; - init_node(&expr->node, HLSL_IR_EXPR, arg->data_type, loc); - expr->op = op; - hlsl_src_from_node(&expr->operands[0], arg); - return &expr->node; -} - -struct hlsl_ir_node *new_binary_expr(enum hlsl_ir_expr_op op, - struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2) -{ - struct hlsl_ir_expr *expr; - - assert(compare_hlsl_types(arg1->data_type, arg2->data_type)); - - if (!(expr = vkd3d_calloc(1, sizeof(*expr)))) - return NULL; - init_node(&expr->node, HLSL_IR_EXPR, arg1->data_type, arg1->loc); - expr->op = op; - hlsl_src_from_node(&expr->operands[0], arg1); - hlsl_src_from_node(&expr->operands[1], arg2); - return &expr->node; -} - -static struct hlsl_ir_load *new_var_load(struct hlsl_ir_var *var, const struct source_location loc) -{ - struct hlsl_ir_load *load; - - if (!(load = vkd3d_calloc(1, sizeof(*load)))) - return NULL; - init_node(&load->node, HLSL_IR_LOAD, var->data_type, loc); - load->src.var = var; - return load; -} - static struct hlsl_ir_load *add_load(struct list *instrs, struct hlsl_ir_node *var_node, struct hlsl_ir_node *offset, struct hlsl_type *data_type, const struct source_location loc) { @@ -777,41 +636,6 @@ static struct list *gen_struct_fields(struct hlsl_type *type, DWORD modifiers, s return list; }
-static DWORD get_array_size(const struct hlsl_type *type) -{ - if (type->type == HLSL_CLASS_ARRAY) - return get_array_size(type->e.array.type) * type->e.array.elements_count; - return 1; -} - -static struct hlsl_type *new_struct_type(const char *name, struct list *fields) -{ - struct hlsl_struct_field *field; - unsigned int reg_size = 0; - struct hlsl_type *type; - - if (!(type = vkd3d_calloc(1, sizeof(*type)))) - return NULL; - type->type = HLSL_CLASS_STRUCT; - type->base_type = HLSL_TYPE_VOID; - type->name = name; - type->dimx = 0; - type->dimy = 1; - type->e.elements = fields; - - LIST_FOR_EACH_ENTRY(field, fields, struct hlsl_struct_field, entry) - { - field->reg_offset = reg_size; - reg_size += field->type->reg_size; - type->dimx += field->type->dimx * field->type->dimy * get_array_size(field->type); - } - type->reg_size = reg_size; - - list_add_tail(&hlsl_ctx.types, &type->entry); - - return type; -} - static BOOL add_typedef(DWORD modifiers, struct hlsl_type *orig_type, struct list *list) { struct parse_variable_def *v, *v_next; @@ -1203,35 +1027,6 @@ static struct list *declare_vars(struct hlsl_type *basic_type, DWORD modifiers, return statements_list; }
-static struct hlsl_ir_function_decl *new_func_decl(struct hlsl_type *return_type, - struct list *parameters, const char *semantic, struct source_location loc) -{ - struct hlsl_ir_function_decl *decl; - - if (!(decl = vkd3d_calloc(1, sizeof(*decl)))) - return NULL; - decl->return_type = return_type; - decl->parameters = parameters; - decl->semantic = semantic; - decl->loc = loc; - - if (!type_is_void(return_type)) - { - struct hlsl_ir_var *return_var; - char name[28]; - - sprintf(name, "<retval-%p>", decl); - if (!(return_var = new_synthetic_var(name, return_type, loc))) - { - vkd3d_free(decl); - return NULL; - } - decl->return_var = return_var; - } - - return decl; -} - %}
%locations
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 141 --------------------------------------- libs/vkd3d-shader/hlsl.h | 2 - libs/vkd3d-shader/hlsl.y | 141 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 143 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index e73ed923..b919a53b 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -704,147 +704,6 @@ struct hlsl_ir_var *new_synthetic_var(const char *name, struct hlsl_type *type, return var; }
-static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) -{ - static const enum hlsl_ir_expr_op ops[] = - { - 0, - HLSL_IR_BINOP_ADD, - HLSL_IR_BINOP_SUB, - HLSL_IR_BINOP_MUL, - HLSL_IR_BINOP_DIV, - HLSL_IR_BINOP_MOD, - HLSL_IR_BINOP_LSHIFT, - HLSL_IR_BINOP_RSHIFT, - HLSL_IR_BINOP_BIT_AND, - HLSL_IR_BINOP_BIT_OR, - HLSL_IR_BINOP_BIT_XOR, - }; - - return ops[op]; -} - -static BOOL invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width) -{ - unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0; - - /* Apply the writemask to the swizzle to get a new writemask and swizzle. */ - for (i = 0; i < 4; ++i) - { - if (*writemask & (1 << i)) - { - unsigned int s = (*swizzle >> (i * 2)) & 3; - new_swizzle |= s << (bit++ * 2); - if (new_writemask & (1 << s)) - return FALSE; - new_writemask |= 1 << s; - } - } - width = bit; - - /* Invert the swizzle. */ - bit = 0; - for (i = 0; i < 4; ++i) - { - for (j = 0; j < width; ++j) - { - unsigned int s = (new_swizzle >> (j * 2)) & 3; - if (s == i) - inverted |= j << (bit++ * 2); - } - } - - *swizzle = inverted; - *writemask = new_writemask; - *ret_width = width; - return TRUE; -} - -struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lhs, - enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) -{ - struct hlsl_ir_assignment *assign; - struct hlsl_type *lhs_type; - DWORD writemask = 0; - - lhs_type = lhs->data_type; - if (lhs_type->type <= HLSL_CLASS_LAST_NUMERIC) - { - writemask = (1 << lhs_type->dimx) - 1; - - if (!(rhs = add_implicit_conversion(instrs, rhs, lhs_type, &rhs->loc))) - return NULL; - } - - if (!(assign = vkd3d_malloc(sizeof(*assign)))) - return NULL; - - while (lhs->type != HLSL_IR_LOAD) - { - struct hlsl_ir_node *lhs_inner; - - if (lhs->type == HLSL_IR_EXPR && expr_from_node(lhs)->op == HLSL_IR_UNOP_CAST) - { - FIXME("Cast on the lhs.\n"); - vkd3d_free(assign); - return NULL; - } - else if (lhs->type == HLSL_IR_SWIZZLE) - { - struct hlsl_ir_swizzle *swizzle = swizzle_from_node(lhs); - const struct hlsl_type *swizzle_type = swizzle->node.data_type; - unsigned int width; - - if (lhs->data_type->type == HLSL_CLASS_MATRIX) - FIXME("Assignments with writemasks and matrices on lhs are not supported yet.\n"); - - lhs_inner = swizzle->val.node; - hlsl_src_remove(&swizzle->val); - list_remove(&lhs->entry); - - list_add_after(&rhs->entry, &lhs->entry); - hlsl_src_from_node(&swizzle->val, rhs); - if (!invert_swizzle(&swizzle->swizzle, &writemask, &width)) - { - hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid writemask"); - vkd3d_free(assign); - return NULL; - } - assert(swizzle_type->type == HLSL_CLASS_VECTOR); - if (swizzle_type->dimx != width) - swizzle->node.data_type = hlsl_ctx.builtin_types.vector[swizzle_type->base_type][width - 1]; - rhs = &swizzle->node; - } - else - { - hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid lvalue"); - vkd3d_free(assign); - return NULL; - } - - lhs = lhs_inner; - } - - init_node(&assign->node, HLSL_IR_ASSIGNMENT, lhs_type, lhs->loc); - assign->writemask = writemask; - assign->lhs.var = load_from_node(lhs)->src.var; - hlsl_src_from_node(&assign->lhs.offset, load_from_node(lhs)->src.offset.node); - if (assign_op != ASSIGN_OP_ASSIGN) - { - enum hlsl_ir_expr_op op = op_from_assignment(assign_op); - struct hlsl_ir_node *expr; - - TRACE("Adding an expression for the compound assignment.\n"); - expr = new_binary_expr(op, lhs, rhs); - list_add_after(&rhs->entry, &expr->entry); - rhs = expr; - } - hlsl_src_from_node(&assign->rhs, rhs); - list_add_tail(instrs, &assign->node.entry); - - return &assign->node; -} - static BOOL type_is_single_reg(const struct hlsl_type *type) { return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index aabfbaf9..6efdfbb7 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -592,8 +592,6 @@ static inline void set_parse_status(enum parse_status *current, enum parse_statu *current = PARSE_WARN; }
-struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lhs, - enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) DECLSPEC_HIDDEN; struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[3], struct source_location *loc) DECLSPEC_HIDDEN; struct hlsl_ir_node *add_implicit_conversion(struct list *instrs, struct hlsl_ir_node *node, struct hlsl_type *type, diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index df155a08..15023019 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -842,6 +842,147 @@ static struct list *add_binary_expr(struct list *list1, struct list *list2, return list1; }
+static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) +{ + static const enum hlsl_ir_expr_op ops[] = + { + 0, + HLSL_IR_BINOP_ADD, + HLSL_IR_BINOP_SUB, + HLSL_IR_BINOP_MUL, + HLSL_IR_BINOP_DIV, + HLSL_IR_BINOP_MOD, + HLSL_IR_BINOP_LSHIFT, + HLSL_IR_BINOP_RSHIFT, + HLSL_IR_BINOP_BIT_AND, + HLSL_IR_BINOP_BIT_OR, + HLSL_IR_BINOP_BIT_XOR, + }; + + return ops[op]; +} + +static BOOL invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width) +{ + unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0; + + /* Apply the writemask to the swizzle to get a new writemask and swizzle. */ + for (i = 0; i < 4; ++i) + { + if (*writemask & (1 << i)) + { + unsigned int s = (*swizzle >> (i * 2)) & 3; + new_swizzle |= s << (bit++ * 2); + if (new_writemask & (1 << s)) + return FALSE; + new_writemask |= 1 << s; + } + } + width = bit; + + /* Invert the swizzle. */ + bit = 0; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < width; ++j) + { + unsigned int s = (new_swizzle >> (j * 2)) & 3; + if (s == i) + inverted |= j << (bit++ * 2); + } + } + + *swizzle = inverted; + *writemask = new_writemask; + *ret_width = width; + return TRUE; +} + +static struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lhs, + enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) +{ + struct hlsl_ir_assignment *assign; + struct hlsl_type *lhs_type; + DWORD writemask = 0; + + lhs_type = lhs->data_type; + if (lhs_type->type <= HLSL_CLASS_LAST_NUMERIC) + { + writemask = (1 << lhs_type->dimx) - 1; + + if (!(rhs = add_implicit_conversion(instrs, rhs, lhs_type, &rhs->loc))) + return NULL; + } + + if (!(assign = vkd3d_malloc(sizeof(*assign)))) + return NULL; + + while (lhs->type != HLSL_IR_LOAD) + { + struct hlsl_ir_node *lhs_inner; + + if (lhs->type == HLSL_IR_EXPR && expr_from_node(lhs)->op == HLSL_IR_UNOP_CAST) + { + FIXME("Cast on the lhs.\n"); + vkd3d_free(assign); + return NULL; + } + else if (lhs->type == HLSL_IR_SWIZZLE) + { + struct hlsl_ir_swizzle *swizzle = swizzle_from_node(lhs); + const struct hlsl_type *swizzle_type = swizzle->node.data_type; + unsigned int width; + + if (lhs->data_type->type == HLSL_CLASS_MATRIX) + FIXME("Assignments with writemasks and matrices on lhs are not supported yet.\n"); + + lhs_inner = swizzle->val.node; + hlsl_src_remove(&swizzle->val); + list_remove(&lhs->entry); + + list_add_after(&rhs->entry, &lhs->entry); + hlsl_src_from_node(&swizzle->val, rhs); + if (!invert_swizzle(&swizzle->swizzle, &writemask, &width)) + { + hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid writemask"); + vkd3d_free(assign); + return NULL; + } + assert(swizzle_type->type == HLSL_CLASS_VECTOR); + if (swizzle_type->dimx != width) + swizzle->node.data_type = hlsl_ctx.builtin_types.vector[swizzle_type->base_type][width - 1]; + rhs = &swizzle->node; + } + else + { + hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid lvalue"); + vkd3d_free(assign); + return NULL; + } + + lhs = lhs_inner; + } + + init_node(&assign->node, HLSL_IR_ASSIGNMENT, lhs_type, lhs->loc); + assign->writemask = writemask; + assign->lhs.var = load_from_node(lhs)->src.var; + hlsl_src_from_node(&assign->lhs.offset, load_from_node(lhs)->src.offset.node); + if (assign_op != ASSIGN_OP_ASSIGN) + { + enum hlsl_ir_expr_op op = op_from_assignment(assign_op); + struct hlsl_ir_node *expr; + + TRACE("Adding an expression for the compound assignment.\n"); + expr = new_binary_expr(op, lhs, rhs); + list_add_after(&rhs->entry, &expr->entry); + rhs = expr; + } + hlsl_src_from_node(&assign->rhs, rhs); + list_add_tail(instrs, &assign->node.entry); + + return &assign->node; +} + static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var, struct parse_initializer *initializer) {
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.c | 84 ------------------------------------- libs/vkd3d-shader/hlsl.h | 2 - libs/vkd3d-shader/hlsl.y | 89 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 86 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index b919a53b..9c1b6d1b 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -371,63 +371,6 @@ BOOL compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) return FALSE; }
-static BOOL implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) -{ - if (!convertible_data_type(t1) || !convertible_data_type(t2)) - return FALSE; - - if (t1->type <= HLSL_CLASS_LAST_NUMERIC) - { - /* Scalar vars can be converted to any other numeric data type */ - if (t1->dimx == 1 && t1->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) - return TRUE; - /* The other way around is true too */ - if (t2->dimx == 1 && t2->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) - return TRUE; - } - - if (t1->type == HLSL_CLASS_ARRAY && t2->type == HLSL_CLASS_ARRAY) - { - return components_count_type(t1) == components_count_type(t2); - } - - if ((t1->type == HLSL_CLASS_ARRAY && t2->type <= HLSL_CLASS_LAST_NUMERIC) - || (t1->type <= HLSL_CLASS_LAST_NUMERIC && t2->type == HLSL_CLASS_ARRAY)) - { - /* e.g. float4[3] to float4 is allowed */ - if (t1->type == HLSL_CLASS_ARRAY && compare_hlsl_types(t1->e.array.type, t2)) - return TRUE; - if (components_count_type(t1) == components_count_type(t2)) - return TRUE; - return FALSE; - } - - if (t1->type <= HLSL_CLASS_VECTOR && t2->type <= HLSL_CLASS_VECTOR) - { - if (t1->dimx >= t2->dimx) - return TRUE; - return FALSE; - } - - if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) - { - if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX - && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) - return TRUE; - - /* Matrix-vector conversion is apparently allowed if they have the same components count */ - if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) - && components_count_type(t1) == components_count_type(t2)) - return TRUE; - return FALSE; - } - - if (t1->type == HLSL_CLASS_STRUCT && t2->type == HLSL_CLASS_STRUCT) - return compare_hlsl_types(t1, t2); - - return FALSE; -} - static BOOL expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) { if (t1->base_type > HLSL_TYPE_LAST_SCALAR || t2->base_type > HLSL_TYPE_LAST_SCALAR) @@ -589,33 +532,6 @@ static struct hlsl_type *expr_common_type(struct hlsl_type *t1, struct hlsl_type return new_hlsl_type(NULL, type, base, dimx, dimy); }
-struct hlsl_ir_node *add_implicit_conversion(struct list *instrs, struct hlsl_ir_node *node, - struct hlsl_type *dst_type, struct source_location *loc) -{ - struct hlsl_type *src_type = node->data_type; - struct hlsl_ir_expr *cast; - - if (compare_hlsl_types(src_type, dst_type)) - return node; - - if (!implicit_compatible_data_types(src_type, dst_type)) - { - hlsl_report_message(*loc, HLSL_LEVEL_ERROR, "can't implicitly convert %s to %s", - debug_hlsl_type(src_type), debug_hlsl_type(dst_type)); - return NULL; - } - - if (dst_type->dimx * dst_type->dimy < src_type->dimx * src_type->dimy) - hlsl_report_message(*loc, HLSL_LEVEL_WARNING, "implicit truncation of vector type"); - - TRACE("Implicit conversion from %s to %s.\n", debug_hlsl_type(src_type), debug_hlsl_type(dst_type)); - - if (!(cast = new_cast(node, dst_type, loc))) - return NULL; - list_add_tail(instrs, &cast->node.entry); - return &cast->node; -} - struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[3], struct source_location *loc) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 6efdfbb7..ab7b99c2 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -594,8 +594,6 @@ static inline void set_parse_status(enum parse_status *current, enum parse_statu
struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[3], struct source_location *loc) DECLSPEC_HIDDEN; -struct hlsl_ir_node *add_implicit_conversion(struct list *instrs, struct hlsl_ir_node *node, struct hlsl_type *type, - struct source_location *loc) DECLSPEC_HIDDEN;
struct hlsl_type *new_array_type(struct hlsl_type *basic_type, unsigned int array_size) DECLSPEC_HIDDEN; struct hlsl_ir_assignment *new_assignment(struct hlsl_ir_var *var, struct hlsl_ir_node *offset, diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 15023019..5d200e4f 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -77,6 +77,95 @@ static void check_invalid_matrix_modifiers(DWORD modifiers, struct source_locati "'row_major' or 'column_major' modifiers are only allowed for matrices."); }
+static BOOL convertible_data_type(struct hlsl_type *type) +{ + return type->type != HLSL_CLASS_OBJECT; +} + +static BOOL implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +{ + if (!convertible_data_type(t1) || !convertible_data_type(t2)) + return FALSE; + + if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + { + /* Scalar vars can be converted to any other numeric data type */ + if (t1->dimx == 1 && t1->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) + return TRUE; + /* The other way around is true too */ + if (t2->dimx == 1 && t2->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) + return TRUE; + } + + if (t1->type == HLSL_CLASS_ARRAY && t2->type == HLSL_CLASS_ARRAY) + { + return components_count_type(t1) == components_count_type(t2); + } + + if ((t1->type == HLSL_CLASS_ARRAY && t2->type <= HLSL_CLASS_LAST_NUMERIC) + || (t1->type <= HLSL_CLASS_LAST_NUMERIC && t2->type == HLSL_CLASS_ARRAY)) + { + /* e.g. float4[3] to float4 is allowed */ + if (t1->type == HLSL_CLASS_ARRAY && compare_hlsl_types(t1->e.array.type, t2)) + return TRUE; + if (components_count_type(t1) == components_count_type(t2)) + return TRUE; + return FALSE; + } + + if (t1->type <= HLSL_CLASS_VECTOR && t2->type <= HLSL_CLASS_VECTOR) + { + if (t1->dimx >= t2->dimx) + return TRUE; + return FALSE; + } + + if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + { + if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX + && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) + return TRUE; + + /* Matrix-vector conversion is apparently allowed if they have the same components count */ + if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + && components_count_type(t1) == components_count_type(t2)) + return TRUE; + return FALSE; + } + + if (t1->type == HLSL_CLASS_STRUCT && t2->type == HLSL_CLASS_STRUCT) + return compare_hlsl_types(t1, t2); + + return FALSE; +} + +static struct hlsl_ir_node *add_implicit_conversion(struct list *instrs, struct hlsl_ir_node *node, + struct hlsl_type *dst_type, struct source_location *loc) +{ + struct hlsl_type *src_type = node->data_type; + struct hlsl_ir_expr *cast; + + if (compare_hlsl_types(src_type, dst_type)) + return node; + + if (!implicit_compatible_data_types(src_type, dst_type)) + { + hlsl_report_message(*loc, HLSL_LEVEL_ERROR, "can't implicitly convert %s to %s", + debug_hlsl_type(src_type), debug_hlsl_type(dst_type)); + return NULL; + } + + if (dst_type->dimx * dst_type->dimy < src_type->dimx * src_type->dimy) + hlsl_report_message(*loc, HLSL_LEVEL_WARNING, "implicit truncation of vector type"); + + TRACE("Implicit conversion from %s to %s.\n", debug_hlsl_type(src_type), debug_hlsl_type(dst_type)); + + if (!(cast = new_cast(node, dst_type, loc))) + return NULL; + list_add_tail(instrs, &cast->node.entry); + return &cast->node; +} + static BOOL declare_variable(struct hlsl_ir_var *decl, BOOL local) { BOOL ret;
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.c | 209 --------------------------------------- libs/vkd3d-shader/hlsl.h | 3 - libs/vkd3d-shader/hlsl.y | 209 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+), 212 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 9c1b6d1b..9b76fb44 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -371,215 +371,6 @@ BOOL compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) return FALSE; }
-static BOOL expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) -{ - if (t1->base_type > HLSL_TYPE_LAST_SCALAR || t2->base_type > HLSL_TYPE_LAST_SCALAR) - return FALSE; - - /* Scalar vars can be converted to pretty much everything */ - if ((t1->dimx == 1 && t1->dimy == 1) || (t2->dimx == 1 && t2->dimy == 1)) - return TRUE; - - if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) - return TRUE; - - if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) - { - /* Matrix-vector conversion is apparently allowed if either they have the same components - count or the matrix is nx1 or 1xn */ - if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) - { - if (components_count_type(t1) == components_count_type(t2)) - return TRUE; - - return (t1->type == HLSL_CLASS_MATRIX && (t1->dimx == 1 || t1->dimy == 1)) - || (t2->type == HLSL_CLASS_MATRIX && (t2->dimx == 1 || t2->dimy == 1)); - } - - /* Both matrices */ - if ((t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) - || (t1->dimx <= t2->dimx && t1->dimy <= t2->dimy)) - return TRUE; - } - - return FALSE; -} - -static enum hlsl_base_type expr_common_base_type(enum hlsl_base_type t1, enum hlsl_base_type t2) -{ - static const enum hlsl_base_type types[] = - { - HLSL_TYPE_BOOL, - HLSL_TYPE_INT, - HLSL_TYPE_UINT, - HLSL_TYPE_HALF, - HLSL_TYPE_FLOAT, - HLSL_TYPE_DOUBLE, - }; - int t1_idx = -1, t2_idx = -1, i; - - for (i = 0; i < ARRAY_SIZE(types); ++i) - { - /* Always convert away from HLSL_TYPE_HALF */ - if (t1 == types[i]) - t1_idx = t1 == HLSL_TYPE_HALF ? i + 1 : i; - if (t2 == types[i]) - t2_idx = t2 == HLSL_TYPE_HALF ? i + 1 : i; - - if (t1_idx != -1 && t2_idx != -1) - break; - } - if (t1_idx == -1 || t2_idx == -1) - { - FIXME("Unexpected base type.\n"); - return HLSL_TYPE_FLOAT; - } - return t1_idx >= t2_idx ? t1 : t2; -} - -static struct hlsl_type *expr_common_type(struct hlsl_type *t1, struct hlsl_type *t2, - struct source_location *loc) -{ - enum hlsl_type_class type; - enum hlsl_base_type base; - unsigned int dimx, dimy; - - if (t1->type > HLSL_CLASS_LAST_NUMERIC || t2->type > HLSL_CLASS_LAST_NUMERIC) - { - hlsl_report_message(*loc, HLSL_LEVEL_ERROR, "non scalar/vector/matrix data type in expression"); - return NULL; - } - - if (compare_hlsl_types(t1, t2)) - return t1; - - if (!expr_compatible_data_types(t1, t2)) - { - hlsl_report_message(*loc, HLSL_LEVEL_ERROR, "expression data types are incompatible"); - return NULL; - } - - if (t1->base_type == t2->base_type) - base = t1->base_type; - else - base = expr_common_base_type(t1->base_type, t2->base_type); - - if (t1->dimx == 1 && t1->dimy == 1) - { - type = t2->type; - dimx = t2->dimx; - dimy = t2->dimy; - } - else if (t2->dimx == 1 && t2->dimy == 1) - { - type = t1->type; - dimx = t1->dimx; - dimy = t1->dimy; - } - else if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX) - { - type = HLSL_CLASS_MATRIX; - dimx = min(t1->dimx, t2->dimx); - dimy = min(t1->dimy, t2->dimy); - } - else - { - /* Two vectors or a vector and a matrix (matrix must be 1xn or nx1) */ - unsigned int max_dim_1, max_dim_2; - - max_dim_1 = max(t1->dimx, t1->dimy); - max_dim_2 = max(t2->dimx, t2->dimy); - if (t1->dimx * t1->dimy == t2->dimx * t2->dimy) - { - type = HLSL_CLASS_VECTOR; - dimx = max(t1->dimx, t2->dimx); - dimy = 1; - } - else if (max_dim_1 <= max_dim_2) - { - type = t1->type; - if (type == HLSL_CLASS_VECTOR) - { - dimx = max_dim_1; - dimy = 1; - } - else - { - dimx = t1->dimx; - dimy = t1->dimy; - } - } - else - { - type = t2->type; - if (type == HLSL_CLASS_VECTOR) - { - dimx = max_dim_2; - dimy = 1; - } - else - { - dimx = t2->dimx; - dimy = t2->dimy; - } - } - } - - if (type == HLSL_CLASS_SCALAR) - return hlsl_ctx.builtin_types.scalar[base]; - if (type == HLSL_CLASS_VECTOR) - return hlsl_ctx.builtin_types.vector[base][dimx - 1]; - return new_hlsl_type(NULL, type, base, dimx, dimy); -} - -struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[3], - struct source_location *loc) -{ - struct hlsl_ir_expr *expr; - struct hlsl_type *type; - unsigned int i; - - type = operands[0]->data_type; - for (i = 1; i <= 2; ++i) - { - if (!operands[i]) - break; - type = expr_common_type(type, operands[i]->data_type, loc); - if (!type) - return NULL; - } - for (i = 0; i <= 2; ++i) - { - struct hlsl_ir_expr *cast; - - if (!operands[i]) - break; - if (compare_hlsl_types(operands[i]->data_type, type)) - continue; - TRACE("Implicitly converting %s into %s in an expression.\n", debug_hlsl_type(operands[i]->data_type), debug_hlsl_type(type)); - if (operands[i]->data_type->dimx * operands[i]->data_type->dimy != 1 - && operands[i]->data_type->dimx * operands[i]->data_type->dimy != type->dimx * type->dimy) - { - hlsl_report_message(operands[i]->loc, HLSL_LEVEL_WARNING, "implicit truncation of vector/matrix type"); - } - - if (!(cast = new_cast(operands[i], type, &operands[i]->loc))) - return NULL; - list_add_after(&operands[i]->entry, &cast->node.entry); - operands[i] = &cast->node; - } - - if (!(expr = vkd3d_calloc(1, sizeof(*expr)))) - return NULL; - init_node(&expr->node, HLSL_IR_EXPR, type, *loc); - expr->op = op; - for (i = 0; i <= 2; ++i) - hlsl_src_from_node(&expr->operands[i], operands[i]); - list_add_tail(instrs, &expr->node.entry); - - return expr; -} - struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type, struct source_location *loc) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index ab7b99c2..492b6d6c 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -592,9 +592,6 @@ static inline void set_parse_status(enum parse_status *current, enum parse_statu *current = PARSE_WARN; }
-struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[3], - struct source_location *loc) DECLSPEC_HIDDEN; - struct hlsl_type *new_array_type(struct hlsl_type *basic_type, unsigned int array_size) DECLSPEC_HIDDEN; struct hlsl_ir_assignment *new_assignment(struct hlsl_ir_var *var, struct hlsl_ir_node *offset, struct hlsl_ir_node *rhs, unsigned int writemask, struct source_location loc) DECLSPEC_HIDDEN; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 5d200e4f..339a30dc 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -914,6 +914,215 @@ static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node) } }
+static BOOL expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +{ + if (t1->base_type > HLSL_TYPE_LAST_SCALAR || t2->base_type > HLSL_TYPE_LAST_SCALAR) + return FALSE; + + /* Scalar vars can be converted to pretty much everything */ + if ((t1->dimx == 1 && t1->dimy == 1) || (t2->dimx == 1 && t2->dimy == 1)) + return TRUE; + + if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) + return TRUE; + + if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + { + /* Matrix-vector conversion is apparently allowed if either they have the same components + count or the matrix is nx1 or 1xn */ + if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + { + if (components_count_type(t1) == components_count_type(t2)) + return TRUE; + + return (t1->type == HLSL_CLASS_MATRIX && (t1->dimx == 1 || t1->dimy == 1)) + || (t2->type == HLSL_CLASS_MATRIX && (t2->dimx == 1 || t2->dimy == 1)); + } + + /* Both matrices */ + if ((t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) + || (t1->dimx <= t2->dimx && t1->dimy <= t2->dimy)) + return TRUE; + } + + return FALSE; +} + +static enum hlsl_base_type expr_common_base_type(enum hlsl_base_type t1, enum hlsl_base_type t2) +{ + static const enum hlsl_base_type types[] = + { + HLSL_TYPE_BOOL, + HLSL_TYPE_INT, + HLSL_TYPE_UINT, + HLSL_TYPE_HALF, + HLSL_TYPE_FLOAT, + HLSL_TYPE_DOUBLE, + }; + int t1_idx = -1, t2_idx = -1, i; + + for (i = 0; i < ARRAY_SIZE(types); ++i) + { + /* Always convert away from HLSL_TYPE_HALF */ + if (t1 == types[i]) + t1_idx = t1 == HLSL_TYPE_HALF ? i + 1 : i; + if (t2 == types[i]) + t2_idx = t2 == HLSL_TYPE_HALF ? i + 1 : i; + + if (t1_idx != -1 && t2_idx != -1) + break; + } + if (t1_idx == -1 || t2_idx == -1) + { + FIXME("Unexpected base type.\n"); + return HLSL_TYPE_FLOAT; + } + return t1_idx >= t2_idx ? t1 : t2; +} + +static struct hlsl_type *expr_common_type(struct hlsl_type *t1, struct hlsl_type *t2, + struct source_location *loc) +{ + enum hlsl_type_class type; + enum hlsl_base_type base; + unsigned int dimx, dimy; + + if (t1->type > HLSL_CLASS_LAST_NUMERIC || t2->type > HLSL_CLASS_LAST_NUMERIC) + { + hlsl_report_message(*loc, HLSL_LEVEL_ERROR, "non scalar/vector/matrix data type in expression"); + return NULL; + } + + if (compare_hlsl_types(t1, t2)) + return t1; + + if (!expr_compatible_data_types(t1, t2)) + { + hlsl_report_message(*loc, HLSL_LEVEL_ERROR, "expression data types are incompatible"); + return NULL; + } + + if (t1->base_type == t2->base_type) + base = t1->base_type; + else + base = expr_common_base_type(t1->base_type, t2->base_type); + + if (t1->dimx == 1 && t1->dimy == 1) + { + type = t2->type; + dimx = t2->dimx; + dimy = t2->dimy; + } + else if (t2->dimx == 1 && t2->dimy == 1) + { + type = t1->type; + dimx = t1->dimx; + dimy = t1->dimy; + } + else if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX) + { + type = HLSL_CLASS_MATRIX; + dimx = min(t1->dimx, t2->dimx); + dimy = min(t1->dimy, t2->dimy); + } + else + { + /* Two vectors or a vector and a matrix (matrix must be 1xn or nx1) */ + unsigned int max_dim_1, max_dim_2; + + max_dim_1 = max(t1->dimx, t1->dimy); + max_dim_2 = max(t2->dimx, t2->dimy); + if (t1->dimx * t1->dimy == t2->dimx * t2->dimy) + { + type = HLSL_CLASS_VECTOR; + dimx = max(t1->dimx, t2->dimx); + dimy = 1; + } + else if (max_dim_1 <= max_dim_2) + { + type = t1->type; + if (type == HLSL_CLASS_VECTOR) + { + dimx = max_dim_1; + dimy = 1; + } + else + { + dimx = t1->dimx; + dimy = t1->dimy; + } + } + else + { + type = t2->type; + if (type == HLSL_CLASS_VECTOR) + { + dimx = max_dim_2; + dimy = 1; + } + else + { + dimx = t2->dimx; + dimy = t2->dimy; + } + } + } + + if (type == HLSL_CLASS_SCALAR) + return hlsl_ctx.builtin_types.scalar[base]; + if (type == HLSL_CLASS_VECTOR) + return hlsl_ctx.builtin_types.vector[base][dimx - 1]; + return new_hlsl_type(NULL, type, base, dimx, dimy); +} + +static struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, + struct hlsl_ir_node *operands[3], struct source_location *loc) +{ + struct hlsl_ir_expr *expr; + struct hlsl_type *type; + unsigned int i; + + type = operands[0]->data_type; + for (i = 1; i <= 2; ++i) + { + if (!operands[i]) + break; + type = expr_common_type(type, operands[i]->data_type, loc); + if (!type) + return NULL; + } + for (i = 0; i <= 2; ++i) + { + struct hlsl_ir_expr *cast; + + if (!operands[i]) + break; + if (compare_hlsl_types(operands[i]->data_type, type)) + continue; + TRACE("Implicitly converting %s into %s in an expression.\n", debug_hlsl_type(operands[i]->data_type), debug_hlsl_type(type)); + if (operands[i]->data_type->dimx * operands[i]->data_type->dimy != 1 + && operands[i]->data_type->dimx * operands[i]->data_type->dimy != type->dimx * type->dimy) + { + hlsl_report_message(operands[i]->loc, HLSL_LEVEL_WARNING, "implicit truncation of vector/matrix type"); + } + + if (!(cast = new_cast(operands[i], type, &operands[i]->loc))) + return NULL; + list_add_after(&operands[i]->entry, &cast->node.entry); + operands[i] = &cast->node; + } + + if (!(expr = vkd3d_calloc(1, sizeof(*expr)))) + return NULL; + init_node(&expr->node, HLSL_IR_EXPR, type, *loc); + expr->op = op; + for (i = 0; i <= 2; ++i) + hlsl_src_from_node(&expr->operands[i], operands[i]); + list_add_tail(instrs, &expr->node.entry); + + return expr; +} + static struct list *append_unop(struct list *list, struct hlsl_ir_node *node) { list_add_tail(list, &node->entry);
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.c | 59 ---------------------------------------- libs/vkd3d-shader/hlsl.h | 1 - libs/vkd3d-shader/hlsl.y | 54 ++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 60 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 9b76fb44..ebd74e64 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -312,65 +312,6 @@ struct hlsl_type *clone_hlsl_type(struct hlsl_type *old, unsigned int default_ma return type; }
-static BOOL convertible_data_type(struct hlsl_type *type) -{ - return type->type != HLSL_CLASS_OBJECT; -} - -BOOL compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) -{ - if (!convertible_data_type(t1) || !convertible_data_type(t2)) - return FALSE; - - if (t1->type <= HLSL_CLASS_LAST_NUMERIC) - { - /* Scalar vars can be cast to pretty much everything */ - if (t1->dimx == 1 && t1->dimy == 1) - return TRUE; - - if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) - return t1->dimx >= t2->dimx; - } - - /* The other way around is true too i.e. whatever to scalar */ - if (t2->type <= HLSL_CLASS_LAST_NUMERIC && t2->dimx == 1 && t2->dimy == 1) - return TRUE; - - if (t1->type == HLSL_CLASS_ARRAY) - { - if (compare_hlsl_types(t1->e.array.type, t2)) - /* e.g. float4[3] to float4 is allowed */ - return TRUE; - - if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) - return components_count_type(t1) >= components_count_type(t2); - else - return components_count_type(t1) == components_count_type(t2); - } - - if (t1->type == HLSL_CLASS_STRUCT) - return components_count_type(t1) >= components_count_type(t2); - - if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) - return components_count_type(t1) == components_count_type(t2); - - if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) - { - if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) - return TRUE; - - /* Matrix-vector conversion is apparently allowed if they have the same components count */ - if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) - && components_count_type(t1) == components_count_type(t2)) - return TRUE; - return FALSE; - } - - if (components_count_type(t1) >= components_count_type(t2)) - return TRUE; - return FALSE; -} - struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type, struct source_location *loc) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 492b6d6c..88ed6de4 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -626,7 +626,6 @@ BOOL is_row_major(const struct hlsl_type *type) DECLSPEC_HIDDEN; BOOL find_function(const char *name) DECLSPEC_HIDDEN; unsigned int components_count_type(struct hlsl_type *type) DECLSPEC_HIDDEN; BOOL compare_hlsl_types(const struct hlsl_type *t1, const struct hlsl_type *t2) DECLSPEC_HIDDEN; -BOOL compatible_data_types(struct hlsl_type *s1, struct hlsl_type *s2) DECLSPEC_HIDDEN; void push_scope(struct hlsl_parse_ctx *ctx) DECLSPEC_HIDDEN; BOOL pop_scope(struct hlsl_parse_ctx *ctx) DECLSPEC_HIDDEN; void init_functions_tree(struct rb_tree *funcs) DECLSPEC_HIDDEN; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 339a30dc..ed832077 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -82,6 +82,60 @@ static BOOL convertible_data_type(struct hlsl_type *type) return type->type != HLSL_CLASS_OBJECT; }
+static BOOL compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +{ + if (!convertible_data_type(t1) || !convertible_data_type(t2)) + return FALSE; + + if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + { + /* Scalar vars can be cast to pretty much everything */ + if (t1->dimx == 1 && t1->dimy == 1) + return TRUE; + + if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) + return t1->dimx >= t2->dimx; + } + + /* The other way around is true too i.e. whatever to scalar */ + if (t2->type <= HLSL_CLASS_LAST_NUMERIC && t2->dimx == 1 && t2->dimy == 1) + return TRUE; + + if (t1->type == HLSL_CLASS_ARRAY) + { + if (compare_hlsl_types(t1->e.array.type, t2)) + /* e.g. float4[3] to float4 is allowed */ + return TRUE; + + if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) + return components_count_type(t1) >= components_count_type(t2); + else + return components_count_type(t1) == components_count_type(t2); + } + + if (t1->type == HLSL_CLASS_STRUCT) + return components_count_type(t1) >= components_count_type(t2); + + if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) + return components_count_type(t1) == components_count_type(t2); + + if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + { + if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) + return TRUE; + + /* Matrix-vector conversion is apparently allowed if they have the same components count */ + if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + && components_count_type(t1) == components_count_type(t2)) + return TRUE; + return FALSE; + } + + if (components_count_type(t1) >= components_count_type(t2)) + return TRUE; + return FALSE; +} + static BOOL implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) { if (!convertible_data_type(t1) || !convertible_data_type(t2))
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com