From: Francisco Casas fcasas@codeweavers.com
---
v2: - Improvements suggested by zf. - Implemented in add_cast() instead of as a compilation pass. - While at it, use hlsl_get_string_buffer() instead of vkd3d_get_string_buffer() in the matrix casts branch. --- libs/vkd3d-shader/hlsl.y | 37 +++++++++++++++++++++++++++++--- tests/cast-broadcast.shader_test | 4 ++-- 2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 624481d8..97e2012e 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -275,6 +275,9 @@ static bool implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_typ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, unsigned int comp, const struct vkd3d_shader_location *loc);
+static void initialize_var_components(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src); + static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) { @@ -287,8 +290,8 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, if ((src_type->type == HLSL_CLASS_MATRIX || dst_type->type == HLSL_CLASS_MATRIX) && src_type->type <= HLSL_CLASS_LAST_NUMERIC && dst_type->type <= HLSL_CLASS_LAST_NUMERIC) { + static unsigned int counter_casts = 0; struct vkd3d_string_buffer *name; - static unsigned int counter = 0; struct hlsl_deref var_deref; struct hlsl_ir_load *load; struct hlsl_ir_var *var; @@ -303,8 +306,8 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, assert(dst_type->dimy <= src_type->dimy); }
- name = vkd3d_string_buffer_get(&ctx->string_buffers); - vkd3d_string_buffer_printf(name, "<cast-%u>", counter++); + name = hlsl_get_string_buffer(ctx); + vkd3d_string_buffer_printf(name, "<cast-%u>", counter_casts++); var = hlsl_new_synthetic_var(ctx, name->buffer, dst_type, *loc); vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) @@ -356,6 +359,34 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
return &load->node; } + else if (src_type->type == HLSL_CLASS_SCALAR && dst_type->type > HLSL_CLASS_LAST_NUMERIC) + { + unsigned int size = hlsl_type_component_count(dst_type); + static unsigned int counter_broadcasts = 0; + struct vkd3d_string_buffer *name; + struct list broadcast_instrs; + unsigned int store_index = 0; + struct hlsl_ir_load *load; + struct hlsl_ir_var *var; + + if (!(name = hlsl_get_string_buffer(ctx))) + return false; + vkd3d_string_buffer_printf(name, "<broadcast-%u>", counter_broadcasts++); + var = hlsl_new_synthetic_var(ctx, name->buffer, dst_type, *loc); + hlsl_release_string_buffer(ctx, name); + if (!var) + return false; + + list_init(&broadcast_instrs); + while (store_index < size) + initialize_var_components(ctx, &broadcast_instrs, var, &store_index, node); + list_move_tail(instrs, &broadcast_instrs); + + load = hlsl_new_var_load(ctx, var, var->loc); + list_add_tail(instrs, &load->node.entry); + + return &load->node; + } else { if (!(cast = hlsl_new_cast(ctx, node, dst_type, loc))) diff --git a/tests/cast-broadcast.shader_test b/tests/cast-broadcast.shader_test index 02d14c0b..8b1948f5 100644 --- a/tests/cast-broadcast.shader_test +++ b/tests/cast-broadcast.shader_test @@ -20,5 +20,5 @@ float4 main() : SV_TARGET }
[test] -todo draw quad -todo probe all rgba (84.0, 84.0, 84.0, 84.0) +draw quad +probe all rgba (84.0, 84.0, 84.0, 84.0)