From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 110 +++++++++++------- .../cast-componentwise-compatible.shader_test | 20 ++-- 2 files changed, 78 insertions(+), 52 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 90bbc75c..4ae746ac 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -168,6 +168,27 @@ static bool hlsl_types_are_componentwise_equal(struct hlsl_ctx *ctx, struct hlsl return true; }
+static bool hlsl_types_are_componentwise_compatible(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct hlsl_type *t2) +{ + unsigned int k, count = hlsl_type_component_count(t2); + + if (count > hlsl_type_component_count(t1)) + 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 ((t1_comp_type->type != HLSL_CLASS_SCALAR || t2_comp_type->type != HLSL_CLASS_SCALAR) + && !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; @@ -186,58 +207,56 @@ static bool type_contains_only_numerics(struct hlsl_type *type) return type->type <= HLSL_CLASS_LAST_NUMERIC; }
-static bool compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +static bool 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 cast to pretty much everything */ - if (t1->dimx == 1 && t1->dimy == 1) + if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + { + /* Scalar vars can be cast to pretty much everything */ + if (t1->dimx == 1 && t1->dimy == 1) + return true; + + if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) + return t1->dimx >= t2->dimx; + } + + /* The other way around is true too i.e. whatever to scalar */ + if (t2->type <= HLSL_CLASS_LAST_NUMERIC && t2->dimx == 1 && t2->dimy == 1) return true;
- if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) - return t1->dimx >= t2->dimx; - } + if (t1->type == HLSL_CLASS_ARRAY) + { + if (hlsl_types_are_equal(t1->e.array.type, t2)) + /* e.g. float4[3] to float4 is allowed */ + return true;
- /* The other way around is true too i.e. whatever to scalar */ - if (t2->type <= HLSL_CLASS_LAST_NUMERIC && t2->dimx == 1 && t2->dimy == 1) - return true; + if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) + return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2); + else + return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); + }
- if (t1->type == HLSL_CLASS_ARRAY) - { - if (hlsl_types_are_equal(t1->e.array.type, t2)) - /* e.g. float4[3] to float4 is allowed */ - return true; + if (t1->type == HLSL_CLASS_STRUCT) + return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2);
if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2); - else return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); - } - - if (t1->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2);
- if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); - - if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) - { - if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) - return true; + if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + { + if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) + return true;
- /* Matrix-vector conversion is apparently allowed if they have the same components count */ - if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) - && hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) - return true; - return false; + /* Matrix-vector conversion is apparently allowed if they have the same components count */ + if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + && hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) + return true; + return false; + } }
- if (hlsl_type_component_count(t1) >= hlsl_type_component_count(t2)) - return true; - return false; + return hlsl_types_are_componentwise_compatible(ctx, t1, t2); }
static bool implicit_compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct hlsl_type *t2) @@ -385,8 +404,9 @@ 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)) + && dst_component_count <= hlsl_type_component_count(src_type)) { + struct hlsl_type *dst_comp_type; unsigned int k;
if (!(var = hlsl_new_synthetic_var(ctx, "cast", dst_type, loc))) @@ -395,10 +415,16 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
for (k = 0; k < dst_component_count; ++k) { + dst_comp_type = hlsl_type_get_component_type(ctx, dst_type, 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))) + if (!(cast = hlsl_new_cast(ctx, &load->node, dst_comp_type, loc))) + return NULL; + list_add_tail(instrs, &cast->node.entry); + + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, k, &cast->node))) return NULL; list_move_tail(instrs, &block.instrs); } @@ -4412,7 +4438,7 @@ unary_expr: dst_type = hlsl_new_array_type(ctx, dst_type, $4.sizes[i]); }
- if (!compatible_data_types(src_type, dst_type)) + if (!compatible_data_types(ctx, src_type, dst_type)) { struct vkd3d_string_buffer *src_string, *dst_string;
diff --git a/tests/cast-componentwise-compatible.shader_test b/tests/cast-componentwise-compatible.shader_test index c6402cf5..286c180b 100644 --- a/tests/cast-componentwise-compatible.shader_test +++ b/tests/cast-componentwise-compatible.shader_test @@ -16,8 +16,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] @@ -39,8 +39,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] @@ -55,8 +55,8 @@ float4 main() : sv_target
[test] -todo draw quad -todo probe all rgba (1.0, 2.0, 3.0, 4.0) +draw quad +probe all rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader] @@ -86,8 +86,8 @@ float4 main() : sv_target }
[test] -todo draw quad -todo probe all rgba (7.0, 7.0, 7.0, 7.0) +draw quad +probe all rgba (7.0, 7.0, 7.0, 7.0)
[pixel shader] @@ -119,8 +119,8 @@ float4 main() : sv_target }
[test] -todo draw quad -todo probe all rgba (3.0, 3.0, 3.0, 3.0) +draw quad +probe all rgba (3.0, 3.0, 3.0, 3.0)
[pixel shader fail]