mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user