mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
vkd3d-shader: Move add_assignment() to hlsl.y.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Matteo Bruni <mbruni@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9b2e8fb1db
commit
60cde237c5
@ -704,147 +704,6 @@ struct hlsl_ir_var *new_synthetic_var(const char *name, struct hlsl_type *type,
|
|||||||
return var;
|
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)
|
static BOOL type_is_single_reg(const struct hlsl_type *type)
|
||||||
{
|
{
|
||||||
return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR;
|
return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR;
|
||||||
|
@ -592,8 +592,6 @@ static inline void set_parse_status(enum parse_status *current, enum parse_statu
|
|||||||
*current = PARSE_WARN;
|
*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 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 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 hlsl_ir_node *add_implicit_conversion(struct list *instrs, struct hlsl_ir_node *node, struct hlsl_type *type,
|
||||||
|
@ -842,6 +842,147 @@ static struct list *add_binary_expr(struct list *list1, struct list *list2,
|
|||||||
return list1;
|
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,
|
static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var,
|
||||||
struct parse_initializer *initializer)
|
struct parse_initializer *initializer)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user