From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 156 +++++++++++++-------- tests/cast-componentwise-equal.shader_test | 16 +-- 2 files changed, 109 insertions(+), 63 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index c8bf75e7..90bbc75c 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -148,6 +148,26 @@ static void check_invalid_matrix_modifiers(struct hlsl_ctx *ctx, DWORD modifiers "'row_major' and 'column_major' modifiers are only allowed for matrices."); }
+static bool hlsl_types_are_componentwise_equal(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct hlsl_type *t2) +{ + unsigned int k, count = hlsl_type_component_count(t1); + + if (count != hlsl_type_component_count(t2)) + return false; + + for (k = 0; k < count; ++k) + { + struct hlsl_type *t1_comp_type, *t2_comp_type; + + t1_comp_type = hlsl_type_get_component_type(ctx, t1, k); + t2_comp_type = hlsl_type_get_component_type(ctx, t2, k); + + if (!hlsl_types_are_equal(t1_comp_type, t2_comp_type)) + return false; + } + return true; +} + static bool type_contains_only_numerics(struct hlsl_type *type) { unsigned int i; @@ -220,67 +240,67 @@ static bool compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) return false; }
-static bool implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +static bool implicit_compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct hlsl_type *t2) { - if (!type_contains_only_numerics(t1) || !type_contains_only_numerics(t2)) - return false; - - if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + if (type_contains_only_numerics(t1) && type_contains_only_numerics(t2)) { - /* Scalar vars can be converted to any other numeric data type */ - if (t1->dimx == 1 && t1->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) - return true; - /* The other way around is true too */ - if (t2->dimx == 1 && t2->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) - return true; - } - - if (t1->type == HLSL_CLASS_ARRAY && t2->type == HLSL_CLASS_ARRAY) - { - return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); - } - - if ((t1->type == HLSL_CLASS_ARRAY && t2->type <= HLSL_CLASS_LAST_NUMERIC) - || (t1->type <= HLSL_CLASS_LAST_NUMERIC && t2->type == HLSL_CLASS_ARRAY)) - { - /* e.g. float4[3] to float4 is allowed */ - if (t1->type == HLSL_CLASS_ARRAY && hlsl_types_are_equal(t1->e.array.type, t2)) - return true; - if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) - return true; - return false; - } - - if (t1->type <= HLSL_CLASS_VECTOR && t2->type <= HLSL_CLASS_VECTOR) - { - if (t1->dimx >= t2->dimx) - return true; - return false; - } + if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + { + /* Scalar vars can be converted to any other numeric data type */ + if (t1->dimx == 1 && t1->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) + return true; + /* The other way around is true too */ + if (t2->dimx == 1 && t2->dimy == 1 && t2->type <= HLSL_CLASS_LAST_NUMERIC) + return true; + }
- if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) - { - if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX) - return t1->dimx >= t2->dimx && t1->dimy >= t2->dimy; + if (t1->type == HLSL_CLASS_ARRAY && t2->type == HLSL_CLASS_ARRAY) + { + return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); + }
- /* Matrix-vector conversion is apparently allowed if they have - * the same components count, or if the matrix is 1xN or Nx1 - * and we are reducing the component count */ - if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + if ((t1->type == HLSL_CLASS_ARRAY && t2->type <= HLSL_CLASS_LAST_NUMERIC) + || (t1->type <= HLSL_CLASS_LAST_NUMERIC && t2->type == HLSL_CLASS_ARRAY)) { + /* e.g. float4[3] to float4 is allowed */ + if (t1->type == HLSL_CLASS_ARRAY && hlsl_types_are_equal(t1->e.array.type, t2)) + return true; if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) return true; + return false; + }
- if ((t1->type == HLSL_CLASS_VECTOR || t1->dimx == 1 || t1->dimy == 1) && - (t2->type == HLSL_CLASS_VECTOR || t2->dimx == 1 || t2->dimy == 1)) - return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2); + if (t1->type <= HLSL_CLASS_VECTOR && t2->type <= HLSL_CLASS_VECTOR) + { + if (t1->dimx >= t2->dimx) + return true; + return false; }
- return false; + if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + { + if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX) + return t1->dimx >= t2->dimx && t1->dimy >= t2->dimy; + + /* Matrix-vector conversion is apparently allowed if they have + * the same components count, or if the matrix is 1xN or Nx1 + * and we are reducing the component count */ + if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + { + if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) + return true; + + if ((t1->type == HLSL_CLASS_VECTOR || t1->dimx == 1 || t1->dimy == 1) && + (t2->type == HLSL_CLASS_VECTOR || t2->dimx == 1 || t2->dimy == 1)) + return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2); + } + + return false; + } }
- if (t1->type == HLSL_CLASS_STRUCT && t2->type == HLSL_CLASS_STRUCT) - return hlsl_types_are_equal(t1, t2); + if (t1->type > HLSL_CLASS_LAST_NUMERIC && t2->type > HLSL_CLASS_LAST_NUMERIC) + return hlsl_types_are_componentwise_equal(ctx, t1, t2);
return false; } @@ -291,8 +311,14 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list 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) { + unsigned int dst_component_count = hlsl_type_component_count(dst_type); struct hlsl_type *src_type = node->data_type; + struct hlsl_deref var_deref; + struct hlsl_ir_store *store; struct hlsl_ir_expr *cast; + struct hlsl_ir_load *load; + struct hlsl_ir_var *var; + struct hlsl_block block;
if (hlsl_types_are_equal(src_type, dst_type)) return node; @@ -300,9 +326,6 @@ 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) { - struct hlsl_deref var_deref; - struct hlsl_ir_load *load; - struct hlsl_ir_var *var; unsigned int dst_idx; bool broadcast;
@@ -321,8 +344,6 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) { struct hlsl_type *dst_scalar_type; - struct hlsl_ir_store *store; - struct hlsl_block block; unsigned int src_idx;
if (broadcast) @@ -363,6 +384,31 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
return &load->node; } + else if ((src_type->type > HLSL_CLASS_LAST_NUMERIC || dst_type->type > HLSL_CLASS_LAST_NUMERIC) + && hlsl_types_are_componentwise_equal(ctx, src_type, dst_type)) + { + unsigned int k; + + if (!(var = hlsl_new_synthetic_var(ctx, "cast", dst_type, loc))) + return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var); + + for (k = 0; k < dst_component_count; ++k) + { + if (!(load = add_load_component(ctx, instrs, node, k, loc))) + return NULL; + + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, k, &load->node))) + return NULL; + list_move_tail(instrs, &block.instrs); + } + + if (!(load = hlsl_new_var_load(ctx, var, *loc))) + return NULL; + list_add_tail(instrs, &load->node.entry); + + return &load->node; + } else { if (!(cast = hlsl_new_cast(ctx, node, dst_type, loc))) @@ -380,7 +426,7 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct if (hlsl_types_are_equal(src_type, dst_type)) return node;
- if (!implicit_compatible_data_types(src_type, dst_type)) + if (!implicit_compatible_data_types(ctx, src_type, dst_type)) { struct vkd3d_string_buffer *src_string, *dst_string;
diff --git a/tests/cast-componentwise-equal.shader_test b/tests/cast-componentwise-equal.shader_test index ac329112..d0775f47 100644 --- a/tests/cast-componentwise-equal.shader_test +++ b/tests/cast-componentwise-equal.shader_test @@ -50,8 +50,8 @@ float4 main() : sv_target
[test] -todo draw quad -todo probe all rgba (1.0, 2.0, 3.0, 1.0) +draw quad +probe all rgba (1.0, 2.0, 3.0, 1.0)
[pixel shader fail] @@ -89,8 +89,8 @@ float4 main() : sv_target
[test] -todo draw quad -todo probe all rgba (5.0, 6.0, 7.0, 8.0) +draw quad +probe all rgba (5.0, 6.0, 7.0, 8.0)
[pixel shader] @@ -120,8 +120,8 @@ float4 main() : sv_target }
[test] -todo draw quad -todo probe all rgba (4.0, 4.0, 4.0, 4.0) +draw quad +probe all rgba (4.0, 4.0, 4.0, 4.0)
[pixel shader] @@ -199,8 +199,8 @@ float4 main() : sv_target }
[test] -todo draw quad -todo probe all rgba (71.0, 73.0, 73.0, 74.0) +draw quad +probe all rgba (71.0, 73.0, 73.0, 74.0)
[pixel shader fail]