From a905a78a9627962431cc9bc81ba73ef57b45ba36 Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Sat, 20 Jul 2024 12:26:56 -0500 Subject: [PATCH] vkd3d-shader/hlsl: Use a structure for matrix swizzles. --- libs/vkd3d-shader/hlsl.c | 48 +++++++++++++++++++++------ libs/vkd3d-shader/hlsl.h | 16 +++++++-- libs/vkd3d-shader/hlsl.y | 48 ++++++++++++++++----------- libs/vkd3d-shader/hlsl_codegen.c | 18 +++++----- libs/vkd3d-shader/hlsl_constant_ops.c | 2 +- 5 files changed, 88 insertions(+), 44 deletions(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index b324e196..c70ab658 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1854,22 +1854,45 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct 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_swizzle *swizzle; struct hlsl_type *type; + VKD3D_ASSERT(val->data_type->class <= HLSL_CLASS_VECTOR); + if (!(swizzle = hlsl_alloc(ctx, sizeof(*swizzle)))) return NULL; - VKD3D_ASSERT(hlsl_is_numeric_type(val->data_type)); - if (components == 1) - type = hlsl_get_scalar_type(ctx, val->data_type->e.numeric.type); + if (component_count > 1) + type = hlsl_get_vector_type(ctx, val->data_type->e.numeric.type, component_count); 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); 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; } @@ -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, struct clone_instr_map *map, struct hlsl_ir_swizzle *src) { - return hlsl_new_swizzle(ctx, src->swizzle, src->node.data_type->dimx, - map_instr(map, src->val.node), &src->node.loc); + if (src->val.node->data_type->class == HLSL_CLASS_MATRIX) + 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, @@ -3412,11 +3439,12 @@ static void dump_ir_swizzle(struct vkd3d_string_buffer *buffer, const struct hls { vkd3d_string_buffer_printf(buffer, "."); 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 { - 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)); } } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index a93e29ea..122f1014 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -802,9 +802,17 @@ struct hlsl_ir_swizzle { struct hlsl_ir_node node; struct hlsl_src val; - /* For vectors, a swizzle described by hlsl_swizzle_get_component(). - * For matrices, a swizzle described by hlsl_matrix_swizzle_get_component(). */ - uint32_t swizzle; + union + { + uint32_t vector; + struct hlsl_matrix_swizzle + { + struct + { + uint8_t x, y; + } components[4]; + } matrix; + } u; }; 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_block *block, enum hlsl_loop_unroll_type unroll_type, 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, 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, diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index f59fdc56..acbfdafd 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -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) { /* Matrix swizzle */ + struct hlsl_matrix_swizzle s; bool m_swizzle; 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) return NULL; - swiz |= (y << 4 | x) << component * 8; + s.components[component].x = x; + s.components[component].y = y; component++; } - return hlsl_new_swizzle(ctx, swiz, component, value, loc); + return hlsl_new_matrix_swizzle(ctx, s, component, value, loc); } /* Vector swizzle */ @@ -2112,22 +2114,22 @@ static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned 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. - * components are indexed by their sources. i.e. the first component comes from the first - * component of the rhs. */ - unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0; + unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0; + struct hlsl_matrix_swizzle new_swizzle = {0}; /* First, we filter the swizzle to remove components that aren't enabled by writemask. */ for (i = 0; i < 4; ++i) { if (*writemask & (1 << i)) { - unsigned int s = (*swizzle >> (i * 8)) & 0xff; - unsigned int x = s & 0xf, y = (s >> 4) & 0xf; + unsigned int x = swizzle->components[i].x; + unsigned int y = swizzle->components[i].y; unsigned int idx = x + y * 4; - new_swizzle |= s << (bit++ * 8); + + new_swizzle.components[bit++] = swizzle->components[i]; if (new_writemask & (1 << idx)) return false; new_writemask |= 1 << idx; @@ -2135,22 +2137,22 @@ static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, un } width = bit; - /* Then we invert the swizzle. The resulting swizzle has 2 bits per component, because it's for the - * incoming vector. */ + /* Then we invert the swizzle. The resulting swizzle uses a uint32_t + * vector format, because it's for the incoming vector. */ bit = 0; for (i = 0; i < 16; ++i) { for (j = 0; j < width; ++j) { - unsigned int s = (new_swizzle >> (j * 8)) & 0xff; - unsigned int x = s & 0xf, y = (s >> 4) & 0xf; + unsigned int x = new_swizzle.components[j].x; + unsigned int y = new_swizzle.components[j].y; unsigned int idx = x + y * 4; if (idx == i) inverted |= j << (bit++ * 2); } } - *swizzle = inverted; + *ret_inverted = inverted; *writemask = new_writemask; *ret_width = width; 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_node *new_swizzle; - uint32_t s = swizzle->swizzle; + uint32_t s; VKD3D_ASSERT(!matrix_writemask); 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) { hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle."); 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."); return false; } matrix_writemask = true; } - else if (!invert_swizzle(&s, &writemask, &width)) + else { - hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask."); - return false; + s = swizzle->u.vector; + 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))) diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 7a19dafb..f20a98ac 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -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_type *matrix_type; struct hlsl_ir_var *var; - unsigned int x, y, k, i; + unsigned int k, i; if (instr->type != HLSL_IR_SWIZZLE) 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_ir_node *load; - y = (swizzle->swizzle >> (8 * i + 4)) & 0xf; - x = (swizzle->swizzle >> 8 * i) & 0xf; - k = y * matrix_type->dimx + x; + k = swizzle->u.matrix.components[i].y * matrix_type->dimx + swizzle->u.matrix.components[i].x; if (!(load = hlsl_add_load_component(ctx, block, swizzle->val.node, k, &instr->loc))) return false; @@ -1757,10 +1755,10 @@ static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx, return false; 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; - 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 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; uint32_t combined_swizzle; - combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle, - swizzle->swizzle, instr->data_type->dimx); + combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->u.vector, + swizzle->u.vector, instr->data_type->dimx); 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))) @@ -2470,7 +2468,7 @@ static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *i return false; 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; 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; 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 = vsir_swizzle_from_hlsl(swizzle); diff --git a/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d-shader/hlsl_constant_ops.c index 60c5efcd..cd7cd2fe 100644 --- a/libs/vkd3d-shader/hlsl_constant_ops.c +++ b/libs/vkd3d-shader/hlsl_constant_ops.c @@ -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); 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))) return false;