vkd3d-shader/hlsl: Use a structure for matrix swizzles.

This commit is contained in:
Elizabeth Figura 2024-07-20 12:26:56 -05:00 committed by Henri Verbeet
parent 70e2148fcb
commit a905a78a96
Notes: Henri Verbeet 2024-12-12 17:48:24 +01:00
Approved-by: Francisco Casas (@fcasas)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1297
5 changed files with 88 additions and 44 deletions

View File

@ -1854,22 +1854,45 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct
return &store->node; return &store->node;
} }
struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int component_count,
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc) struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc)
{ {
struct hlsl_ir_swizzle *swizzle; struct hlsl_ir_swizzle *swizzle;
struct hlsl_type *type; struct hlsl_type *type;
VKD3D_ASSERT(val->data_type->class <= HLSL_CLASS_VECTOR);
if (!(swizzle = hlsl_alloc(ctx, sizeof(*swizzle)))) if (!(swizzle = hlsl_alloc(ctx, sizeof(*swizzle))))
return NULL; return NULL;
VKD3D_ASSERT(hlsl_is_numeric_type(val->data_type)); if (component_count > 1)
if (components == 1) type = hlsl_get_vector_type(ctx, val->data_type->e.numeric.type, component_count);
type = hlsl_get_scalar_type(ctx, val->data_type->e.numeric.type);
else else
type = hlsl_get_vector_type(ctx, val->data_type->e.numeric.type, components); type = hlsl_get_scalar_type(ctx, val->data_type->e.numeric.type);
init_node(&swizzle->node, HLSL_IR_SWIZZLE, type, loc); init_node(&swizzle->node, HLSL_IR_SWIZZLE, type, loc);
hlsl_src_from_node(&swizzle->val, val); hlsl_src_from_node(&swizzle->val, val);
swizzle->swizzle = s; swizzle->u.vector = s;
return &swizzle->node;
}
struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_matrix_swizzle s,
unsigned int component_count, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_swizzle *swizzle;
struct hlsl_type *type;
VKD3D_ASSERT(val->data_type->class == HLSL_CLASS_MATRIX);
if (!(swizzle = hlsl_alloc(ctx, sizeof(*swizzle))))
return NULL;
if (component_count > 1)
type = hlsl_get_vector_type(ctx, val->data_type->e.numeric.type, component_count);
else
type = hlsl_get_scalar_type(ctx, val->data_type->e.numeric.type);
init_node(&swizzle->node, HLSL_IR_SWIZZLE, type, loc);
hlsl_src_from_node(&swizzle->val, val);
swizzle->u.matrix = s;
return &swizzle->node; return &swizzle->node;
} }
@ -2331,8 +2354,12 @@ static struct hlsl_ir_node *clone_store(struct hlsl_ctx *ctx, struct clone_instr
static struct hlsl_ir_node *clone_swizzle(struct hlsl_ctx *ctx, static struct hlsl_ir_node *clone_swizzle(struct hlsl_ctx *ctx,
struct clone_instr_map *map, struct hlsl_ir_swizzle *src) struct clone_instr_map *map, struct hlsl_ir_swizzle *src)
{ {
return hlsl_new_swizzle(ctx, src->swizzle, src->node.data_type->dimx, if (src->val.node->data_type->class == HLSL_CLASS_MATRIX)
map_instr(map, src->val.node), &src->node.loc); return hlsl_new_matrix_swizzle(ctx, src->u.matrix, src->node.data_type->dimx,
map_instr(map, src->val.node), &src->node.loc);
else
return hlsl_new_swizzle(ctx, src->u.vector, src->node.data_type->dimx,
map_instr(map, src->val.node), &src->node.loc);
} }
static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr_map *map, static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr_map *map,
@ -3412,11 +3439,12 @@ static void dump_ir_swizzle(struct vkd3d_string_buffer *buffer, const struct hls
{ {
vkd3d_string_buffer_printf(buffer, "."); vkd3d_string_buffer_printf(buffer, ".");
for (i = 0; i < swizzle->node.data_type->dimx; ++i) for (i = 0; i < swizzle->node.data_type->dimx; ++i)
vkd3d_string_buffer_printf(buffer, "_m%u%u", (swizzle->swizzle >> i * 8) & 0xf, (swizzle->swizzle >> (i * 8 + 4)) & 0xf); vkd3d_string_buffer_printf(buffer, "_m%u%u",
swizzle->u.matrix.components[i].y, swizzle->u.matrix.components[i].x);
} }
else else
{ {
vkd3d_string_buffer_printf(buffer, "%s", debug_hlsl_swizzle(swizzle->swizzle, swizzle->node.data_type->dimx)); vkd3d_string_buffer_printf(buffer, "%s", debug_hlsl_swizzle(swizzle->u.vector, swizzle->node.data_type->dimx));
} }
} }

View File

@ -802,9 +802,17 @@ struct hlsl_ir_swizzle
{ {
struct hlsl_ir_node node; struct hlsl_ir_node node;
struct hlsl_src val; struct hlsl_src val;
/* For vectors, a swizzle described by hlsl_swizzle_get_component(). union
* For matrices, a swizzle described by hlsl_matrix_swizzle_get_component(). */ {
uint32_t swizzle; uint32_t vector;
struct hlsl_matrix_swizzle
{
struct
{
uint8_t x, y;
} components[4];
} matrix;
} u;
}; };
struct hlsl_ir_index struct hlsl_ir_index
@ -1564,6 +1572,8 @@ struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *v
struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx, struct hlsl_block *iter, struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx, struct hlsl_block *iter,
struct hlsl_block *block, enum hlsl_loop_unroll_type unroll_type, struct hlsl_block *block, enum hlsl_loop_unroll_type unroll_type,
unsigned int unroll_limit, const struct vkd3d_shader_location *loc); unsigned int unroll_limit, const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_matrix_swizzle s,
unsigned int width, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx,
const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc); const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct hlsl_deref *resource, struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct hlsl_deref *resource,

View File

@ -845,6 +845,7 @@ static struct hlsl_ir_node *get_swizzle(struct hlsl_ctx *ctx, struct hlsl_ir_nod
if (value->data_type->class == HLSL_CLASS_MATRIX) if (value->data_type->class == HLSL_CLASS_MATRIX)
{ {
/* Matrix swizzle */ /* Matrix swizzle */
struct hlsl_matrix_swizzle s;
bool m_swizzle; bool m_swizzle;
unsigned int inc, x, y; unsigned int inc, x, y;
@ -875,10 +876,11 @@ static struct hlsl_ir_node *get_swizzle(struct hlsl_ctx *ctx, struct hlsl_ir_nod
if (x >= value->data_type->dimx || y >= value->data_type->dimy) if (x >= value->data_type->dimx || y >= value->data_type->dimy)
return NULL; return NULL;
swiz |= (y << 4 | x) << component * 8; s.components[component].x = x;
s.components[component].y = y;
component++; component++;
} }
return hlsl_new_swizzle(ctx, swiz, component, value, loc); return hlsl_new_matrix_swizzle(ctx, s, component, value, loc);
} }
/* Vector swizzle */ /* Vector swizzle */
@ -2112,22 +2114,22 @@ static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned
return true; return true;
} }
static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, unsigned int *ret_width) static bool invert_swizzle_matrix(const struct hlsl_matrix_swizzle *swizzle,
uint32_t *ret_inverted, unsigned int *writemask, unsigned int *ret_width)
{ {
/* swizzle is 8 bits per component, each component is (from LSB) 4 bits X, then 4 bits Y. unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0;
* components are indexed by their sources. i.e. the first component comes from the first struct hlsl_matrix_swizzle new_swizzle = {0};
* component of the rhs. */
unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0;
/* First, we filter the swizzle to remove components that aren't enabled by writemask. */ /* First, we filter the swizzle to remove components that aren't enabled by writemask. */
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
if (*writemask & (1 << i)) if (*writemask & (1 << i))
{ {
unsigned int s = (*swizzle >> (i * 8)) & 0xff; unsigned int x = swizzle->components[i].x;
unsigned int x = s & 0xf, y = (s >> 4) & 0xf; unsigned int y = swizzle->components[i].y;
unsigned int idx = x + y * 4; unsigned int idx = x + y * 4;
new_swizzle |= s << (bit++ * 8);
new_swizzle.components[bit++] = swizzle->components[i];
if (new_writemask & (1 << idx)) if (new_writemask & (1 << idx))
return false; return false;
new_writemask |= 1 << idx; new_writemask |= 1 << idx;
@ -2135,22 +2137,22 @@ static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, un
} }
width = bit; width = bit;
/* Then we invert the swizzle. The resulting swizzle has 2 bits per component, because it's for the /* Then we invert the swizzle. The resulting swizzle uses a uint32_t
* incoming vector. */ * vector format, because it's for the incoming vector. */
bit = 0; bit = 0;
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
for (j = 0; j < width; ++j) for (j = 0; j < width; ++j)
{ {
unsigned int s = (new_swizzle >> (j * 8)) & 0xff; unsigned int x = new_swizzle.components[j].x;
unsigned int x = s & 0xf, y = (s >> 4) & 0xf; unsigned int y = new_swizzle.components[j].y;
unsigned int idx = x + y * 4; unsigned int idx = x + y * 4;
if (idx == i) if (idx == i)
inverted |= j << (bit++ * 2); inverted |= j << (bit++ * 2);
} }
} }
*swizzle = inverted; *ret_inverted = inverted;
*writemask = new_writemask; *writemask = new_writemask;
*ret_width = width; *ret_width = width;
return true; return true;
@ -2204,28 +2206,34 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc
{ {
struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs); struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs);
struct hlsl_ir_node *new_swizzle; struct hlsl_ir_node *new_swizzle;
uint32_t s = swizzle->swizzle; uint32_t s;
VKD3D_ASSERT(!matrix_writemask); VKD3D_ASSERT(!matrix_writemask);
if (swizzle->val.node->data_type->class == HLSL_CLASS_MATRIX) if (swizzle->val.node->data_type->class == HLSL_CLASS_MATRIX)
{ {
struct hlsl_matrix_swizzle ms = swizzle->u.matrix;
if (swizzle->val.node->type != HLSL_IR_LOAD && swizzle->val.node->type != HLSL_IR_INDEX) if (swizzle->val.node->type != HLSL_IR_LOAD && swizzle->val.node->type != HLSL_IR_INDEX)
{ {
hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle."); hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle.");
return false; return false;
} }
if (!invert_swizzle_matrix(&s, &writemask, &width)) if (!invert_swizzle_matrix(&ms, &s, &writemask, &width))
{ {
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask for matrix."); hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask for matrix.");
return false; return false;
} }
matrix_writemask = true; matrix_writemask = true;
} }
else if (!invert_swizzle(&s, &writemask, &width)) else
{ {
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask."); s = swizzle->u.vector;
return false; if (!invert_swizzle(&s, &writemask, &width))
{
hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask.");
return false;
}
} }
if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc))) if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc)))

View File

@ -1076,7 +1076,7 @@ static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins
struct hlsl_deref var_deref; struct hlsl_deref var_deref;
struct hlsl_type *matrix_type; struct hlsl_type *matrix_type;
struct hlsl_ir_var *var; struct hlsl_ir_var *var;
unsigned int x, y, k, i; unsigned int k, i;
if (instr->type != HLSL_IR_SWIZZLE) if (instr->type != HLSL_IR_SWIZZLE)
return false; return false;
@ -1094,9 +1094,7 @@ static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins
struct hlsl_block store_block; struct hlsl_block store_block;
struct hlsl_ir_node *load; struct hlsl_ir_node *load;
y = (swizzle->swizzle >> (8 * i + 4)) & 0xf; k = swizzle->u.matrix.components[i].y * matrix_type->dimx + swizzle->u.matrix.components[i].x;
x = (swizzle->swizzle >> 8 * i) & 0xf;
k = y * matrix_type->dimx + x;
if (!(load = hlsl_add_load_component(ctx, block, swizzle->val.node, k, &instr->loc))) if (!(load = hlsl_add_load_component(ctx, block, swizzle->val.node, k, &instr->loc)))
return false; return false;
@ -1757,10 +1755,10 @@ static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx,
return false; return false;
load = hlsl_ir_load(swizzle->val.node); load = hlsl_ir_load(swizzle->val.node);
if (copy_propagation_replace_with_constant_vector(ctx, state, load, swizzle->swizzle, &swizzle->node)) if (copy_propagation_replace_with_constant_vector(ctx, state, load, swizzle->u.vector, &swizzle->node))
return true; return true;
if (copy_propagation_replace_with_single_instr(ctx, state, load, swizzle->swizzle, &swizzle->node)) if (copy_propagation_replace_with_single_instr(ctx, state, load, swizzle->u.vector, &swizzle->node))
return true; return true;
return false; return false;
@ -2442,8 +2440,8 @@ static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr
struct hlsl_ir_node *new_swizzle; struct hlsl_ir_node *new_swizzle;
uint32_t combined_swizzle; uint32_t combined_swizzle;
combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle, combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->u.vector,
swizzle->swizzle, instr->data_type->dimx); swizzle->u.vector, instr->data_type->dimx);
next_instr = hlsl_ir_swizzle(next_instr)->val.node; next_instr = hlsl_ir_swizzle(next_instr)->val.node;
if (!(new_swizzle = hlsl_new_swizzle(ctx, combined_swizzle, instr->data_type->dimx, next_instr, &instr->loc))) if (!(new_swizzle = hlsl_new_swizzle(ctx, combined_swizzle, instr->data_type->dimx, next_instr, &instr->loc)))
@ -2470,7 +2468,7 @@ static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *i
return false; return false;
for (i = 0; i < instr->data_type->dimx; ++i) for (i = 0; i < instr->data_type->dimx; ++i)
if (hlsl_swizzle_get_component(swizzle->swizzle, i) != i) if (hlsl_swizzle_get_component(swizzle->u.vector, i) != i)
return false; return false;
hlsl_replace_node(instr, swizzle->val.node); hlsl_replace_node(instr, swizzle->val.node);
@ -7895,7 +7893,7 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx,
dst_param->write_mask = instr->reg.writemask; dst_param->write_mask = instr->reg.writemask;
swizzle = hlsl_swizzle_from_writemask(val->reg.writemask); swizzle = hlsl_swizzle_from_writemask(val->reg.writemask);
swizzle = hlsl_combine_swizzles(swizzle, swizzle_instr->swizzle, instr->data_type->dimx); swizzle = hlsl_combine_swizzles(swizzle, swizzle_instr->u.vector, instr->data_type->dimx);
swizzle = hlsl_map_swizzle(swizzle, ins->dst[0].write_mask); swizzle = hlsl_map_swizzle(swizzle, ins->dst[0].write_mask);
swizzle = vsir_swizzle_from_hlsl(swizzle); swizzle = vsir_swizzle_from_hlsl(swizzle);

View File

@ -1705,7 +1705,7 @@ bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
src = hlsl_ir_constant(swizzle->val.node); src = hlsl_ir_constant(swizzle->val.node);
for (i = 0; i < swizzle->node.data_type->dimx; ++i) for (i = 0; i < swizzle->node.data_type->dimx; ++i)
value.u[i] = src->value.u[hlsl_swizzle_get_component(swizzle->swizzle, i)]; value.u[i] = src->value.u[hlsl_swizzle_get_component(swizzle->u.vector, i)];
if (!(dst = hlsl_new_constant(ctx, instr->data_type, &value, &instr->loc))) if (!(dst = hlsl_new_constant(ctx, instr->data_type, &value, &instr->loc)))
return false; return false;